Use cygpath to translate paths on windows (#188)

I was previous doing it manually, which failed when running in
powershell in a Github Desktop for windows.

Use the `cygpath` utility instead.
This commit is contained in:
Casey Rodarmor 2017-04-23 16:09:34 -07:00 committed by GitHub
parent 832cf7b357
commit 165e7951af
2 changed files with 50 additions and 24 deletions

View File

@ -368,7 +368,8 @@ impl<'a> Recipe<'a> {
})?;
// create a command to run the script
let mut command = Platform::make_shebang_command(&path, shebang_command, shebang_argument);
let mut command = Platform::make_shebang_command(&path, shebang_command, shebang_argument)
.map_err(|output_error| RunError::Cygpath{recipe: self.name, output_error: output_error})?;
// export environment variables
export_env(&mut command, scope, exports)?;
@ -1300,6 +1301,7 @@ enum RunError<'a> {
ArgumentCountMismatch{recipe: &'a str, found: usize, min: usize, max: usize},
Backtick{token: Token<'a>, output_error: OutputError},
Code{recipe: &'a str, line_number: Option<usize>, code: i32},
Cygpath{recipe: &'a str, output_error: OutputError},
InternalError{message: String},
IoError{recipe: &'a str, io_error: io::Error},
Shebang{recipe: &'a str, command: String, argument: Option<String>, io_error: io::Error},
@ -1363,6 +1365,35 @@ impl<'a> Display for RunError<'a> {
write!(f, "Recipe `{}` failed with exit code {}", recipe, code)?;
}
},
Cygpath{recipe, ref output_error} => match *output_error {
OutputError::Code(code) => {
write!(f, "Cygpath failed with exit code {} while translating recipe `{}` \
shebang interpreter path", code, recipe)?;
}
OutputError::Signal(signal) => {
write!(f, "Cygpath terminated by signal {} while translating recipe `{}` \
shebang interpreter path", signal, recipe)?;
}
OutputError::Unknown => {
write!(f, "Cygpath experienced an unknown failure while translating recipe `{}` \
shebang interpreter path", recipe)?;
}
OutputError::Io(ref io_error) => {
match io_error.kind() {
io::ErrorKind::NotFound => write!(
f, "Could not find `cygpath` executable to translate recipe `{}` \
shebang interpreter path:\n{}", recipe, io_error),
io::ErrorKind::PermissionDenied => write!(
f, "Could not run `cygpath` executable to translate recipe `{}` \
shebang interpreter path:\n{}", recipe, io_error),
_ => write!(f, "Could not run `cygpath` executable:\n{}", io_error),
}?;
}
OutputError::Utf8(ref utf8_error) => {
write!(f, "Cygpath successfully translated recipe `{}` shebang interpreter path, \
but output was not utf8: {}", recipe, utf8_error)?;
}
},
Shebang{recipe, ref command, ref argument, ref io_error} => {
if let Some(ref argument) = *argument {
write!(f, "Recipe `{}` with shebang `#!{} {}` execution error: {}",
@ -1388,7 +1419,7 @@ impl<'a> Display for RunError<'a> {
IoError{recipe, ref io_error} => {
match io_error.kind() {
io::ErrorKind::NotFound => write!(f,
"Recipe `{}` could not be run because just could not find `sh` the command:\n{}",
"Recipe `{}` could not be run because just could not find `sh`:\n{}",
recipe, io_error),
io::ErrorKind::PermissionDenied => write!(
f, "Recipe `{}` could not be run because just could not run `sh`:\n{}",
@ -1417,7 +1448,7 @@ impl<'a> Display for RunError<'a> {
OutputError::Io(ref io_error) => {
match io_error.kind() {
io::ErrorKind::NotFound => write!(
f, "Backtick could not be run because just could not find `sh` the command:\n{}",
f, "Backtick could not be run because just could not find `sh`:\n{}",
io_error),
io::ErrorKind::PermissionDenied => write!(
f, "Backtick could not be run because just could not run `sh`:\n{}", io_error),

View File

@ -5,7 +5,8 @@ pub struct Platform;
pub trait PlatformInterface {
/// Construct a command equivelant to running the script at `path` with the
/// shebang line `shebang`
fn make_shebang_command(path: &Path, command: &str, argument: Option<&str>) -> process::Command;
fn make_shebang_command(path: &Path, command: &str, argument: Option<&str>)
-> Result<process::Command, super::OutputError>;
/// Set the execute permission on the file pointed to by `path`
fn set_execute_permission(path: &Path) -> Result<(), io::Error>;
@ -16,9 +17,11 @@ pub trait PlatformInterface {
#[cfg(unix)]
impl PlatformInterface for Platform {
fn make_shebang_command(path: &Path, _command: &str, _argument: Option<&str>) -> process::Command {
fn make_shebang_command(path: &Path, _command: &str, _argument: Option<&str>)
-> Result<process::Command, super::OutputError>
{
// shebang scripts can be executed directly on unix
process::Command::new(path)
Ok(process::Command::new(path))
}
fn set_execute_permission(path: &Path) -> Result<(), io::Error> {
@ -43,28 +46,20 @@ impl PlatformInterface for Platform {
#[cfg(windows)]
impl PlatformInterface for Platform {
fn make_shebang_command(path: &Path, command: &str, argument: Option<&str>) -> process::Command {
let mut cmd = match env::var_os("EXEPATH") {
Some(exepath) => {
// On MinGW, `EXEPATH` is the root of the installation. Use it to
// construct a full windows path to the binary in the shebang line.
let mut translated_command = PathBuf::from(exepath);
for part in command.split("/") {
translated_command.push(part);
}
process::Command::new(translated_command)
}
None => {
// We're not on MinGW >_< The path in the shebang might be a windows
// path, in which case it'll work, so just use it and hope for the best.
process::Command::new(command)
}
};
fn make_shebang_command(path: &Path, command: &str, argument: Option<&str>)
-> Result<process::Command, super::OutputError>
{
// Translate path to the interpreter from unix style to windows style
let mut cygpath = process::Command::new("cygpath");
cygpath.arg("--windows");
cygpath.arg(command);
let mut cmd = process::Command::new(super::output(cygpath)?);
if let Some(argument) = argument {
cmd.arg(argument);
}
cmd.arg(path);
cmd
Ok(cmd)
}
fn set_execute_permission(_path: &Path) -> Result<(), io::Error> {