coliru

A minimal, flexible, dotfile installer
git clone https://git.ashermorgan.net/coliru/
Log | Files | Refs | README

commit 12cf0824dfc11f983a3725ac9a3cc4fcb435a6f1
parent d53e8d5f6a9eb93cbc22f1374e36a75f6e8a83d0
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Thu,  4 Jul 2024 14:02:08 -0700

Refactor local script execution

Command is now assembled from prefix, src, and postfix inside of
core::execute_runs so it can easily be passed to both local::run_command and
ssh::send_command. run_command also now uses cmd instead of PowerShell on
Windows to better match SSH environment.

Diffstat:
MREADME.md | 4++--
Msrc/core.rs | 15+++++++--------
Msrc/local.rs | 55+++++++++++++++++++++++++------------------------------
3 files changed, 34 insertions(+), 40 deletions(-)

diff --git a/README.md b/README.md @@ -29,8 +29,8 @@ directory containing the manifest file. The copy command copies a file from a source (`src`) to a (`dst`). The link command links a file from a source (`src`) to a (`dst`) using symbolic links on Unix platforms and hard links on Windows. Finally, the run command executes a script (`src`) from the command line, using -`sh` on Unix platforms and `powershell` on Windows, with an optional `prefix` -(e.g. `python3`) or `postfix` (e.g. `arg1 arg2 arg3`) string. Inside `postfix`, +`sh` on Unix platforms and `cmd` on Windows, with an optional `prefix` (e.g. +`python3`) or `postfix` (e.g. `arg1 arg2 arg3`) string. Inside `postfix`, `$COLIRU_RULES` will be expanded into a space-delimited list of the current tag rules. diff --git a/src/core.rs b/src/core.rs @@ -2,7 +2,7 @@ use std::env::set_current_dir; use std::path::Path; use super::manifest::{CopyLinkOptions, RunOptions, parse_manifest_file}; use super::tags::tags_match; -use super::local::{copy_file, link_file, run_script}; +use super::local::{copy_file, link_file, run_command}; use super::ssh::{send_command, send_staged_files, stage_file}; use tempfile::tempdir; @@ -118,11 +118,11 @@ fn execute_runs(runs: &[RunOptions], tag_rules: &[String], host: &str, for run in runs { let postfix = run.postfix.replace("$COLIRU_RULES", &tag_rules.join(" ")); + let cmd = format!("{} {} {}", run.prefix, run.src, postfix); if host == "" { - print!("{} Run {} {} {}", step_str, run.prefix, run.src, postfix); + print!("{} Run {}", step_str, cmd); } else { - print!("{} Run {} {} {} on {}", step_str, run.prefix, run.src, - postfix, host); + print!("{} Run {} on {}", step_str, cmd, host); } if dry_run { @@ -132,13 +132,12 @@ fn execute_runs(runs: &[RunOptions], tag_rules: &[String], host: &str, println!(""); if host == "" { - if let Err(why) = run_script(&run.src, &run.prefix, &postfix) { + if let Err(why) = run_command(&cmd) { eprintln!(" Error: {}", why); } } else { - let cmd = format!("cd .coliru && {} {} {}", &run.prefix, &run.src, - &postfix); - if let Err(why) = send_command(&cmd, host) { + let ssh_cmd = format!("cd .coliru && {}", &cmd); + if let Err(why) = send_command(&ssh_cmd, host) { eprintln!(" Error: {}", why); } } diff --git a/src/local.rs b/src/local.rs @@ -50,25 +50,18 @@ fn prepare_path(path: &str) -> io::Result<PathBuf> { Ok(_dst) } -/// Executes a local shell script, optionally with a command prefix or postfix. -/// -/// Uses sh on Unix and PowerShell on Windows. -pub fn run_script(path: &str, prefix: &str, postfix: &str) -> Result<(), String> +/// Executes a local command using sh on Unix and cmd on Windows +pub fn run_command(command: &str) -> Result<(), String> { - // Use absolute() to avoid incompatible "UNC" paths on Windows: - // https://github.com/rust-lang/rust/issues/42869 - let _path = absolute(path).map_err(|why| why.to_string())?; let status; if cfg!(target_family = "unix") { status = Command::new("sh") - .arg("-c") - .arg(format!("{} {} {}", prefix, _path.display(), postfix)) + .args(["-c", command]) .status() .map_err(|why| why.to_string())?; } else { - status = Command::new("powershell") - .args(["-ExecutionPolicy", "Bypass", "-Command"]) - .arg(format!("{} {} {}", prefix, _path.display(), postfix)) + status = Command::new("cmd.exe") + .args(["/C", command]) .status() .map_err(|why| why.to_string())?; } @@ -277,39 +270,39 @@ mod tests { #[test] #[cfg(target_family = "unix")] - fn test_run_script_successful() { - let tmp = setup_integration("test_run_script_successful"); + fn test_run_command_successful() { + let tmp = setup_integration("test_run_command_successful"); let src = &tmp.local.join("foo"); write_file(src, "exit 0"); - let result = run_script(src.to_str().unwrap(), "sh", ""); + let result = run_command(&format!("sh {}", src.to_str().unwrap())); assert_eq!(result.is_ok(), true); } #[test] #[cfg(target_family = "windows")] - fn test_run_script_successful() { - let tmp = setup_integration("test_run_script_successful"); + fn test_run_command_successful() { + let tmp = setup_integration("test_run_command_successful"); let src = &tmp.local.join("foo.bat"); write_file(src, "exit 0"); - let result = run_script(src.to_str().unwrap(), "", ""); + let result = run_command(src.to_str().unwrap()); assert_eq!(result.is_ok(), true); } #[test] #[cfg(target_family = "unix")] - fn test_run_script_failure() { - let tmp = setup_integration("test_run_script_failure"); + fn test_run_command_failure() { + let tmp = setup_integration("test_run_command_failure"); let src = &tmp.local.join("foo"); write_file(src, "exit 2"); - let result = run_script(src.to_str().unwrap(), "sh", ""); + let result = run_command(&format!("sh {}", src.to_str().unwrap())); assert_eq!(result.is_ok(), false); assert_eq!(result.unwrap_err(), "Process exited with exit status: 2"); @@ -317,13 +310,13 @@ mod tests { #[test] #[cfg(target_family = "windows")] - fn test_run_script_failure() { - let tmp = setup_integration("test_run_script_failure"); + fn test_run_command_failure() { + let tmp = setup_integration("test_run_command_failure"); let src = &tmp.local.join("foo.bat"); write_file(src, "exit 1"); - let result = run_script(src.to_str().unwrap(), "", ""); + let result = run_command(src.to_str().unwrap()); assert_eq!(result.is_ok(), false); assert_eq!(result.unwrap_err(), "Process exited with exit code: 1"); @@ -331,14 +324,15 @@ mod tests { #[test] #[cfg(target_family = "unix")] - fn test_run_script_postfix() { - let tmp = setup_integration("test_run_script_postfix"); + fn test_run_command_arguments() { + let tmp = setup_integration("test_run_command_arguments"); let src = &tmp.local.join("foo"); let dst = &tmp.local.join("bar"); write_file(src, &format!("echo $@ > {}", dst.to_str().unwrap())); - let result = run_script(src.to_str().unwrap(), "sh", "arg1 arg2"); + let result = run_command(&format!("sh {} arg1 arg2", + src.to_str().unwrap())); let contents = fs::read_to_string(dst).unwrap(); assert_eq!(result.is_ok(), true); @@ -347,14 +341,15 @@ mod tests { #[test] #[cfg(target_family = "windows")] - fn test_run_script_postfix() { - let tmp = setup_integration("test_run_script_postfix"); + fn test_run_command_arguments() { + let tmp = setup_integration("test_run_command_arguments"); let src = &tmp.local.join("foo.bat"); let dst = &tmp.local.join("bar"); write_file(src, &format!("echo %* > {}", dst.to_str().unwrap())); - let result = run_script(src.to_str().unwrap(), "", "arg1 arg2"); + let result = run_command(&format!("{} arg1 arg2", + src.to_str().unwrap())); let contents = fs::read_to_string(dst).unwrap(); assert_eq!(result.is_ok(), true);