diff --git a/src/git_tests.rs b/src/git_tests.rs index b151584..b1ba5e7 100644 --- a/src/git_tests.rs +++ b/src/git_tests.rs @@ -50,10 +50,14 @@ fn test_init_works() -> TestResult { .assert() .success() .stdout(format!( - "{} --yolk-dir {} --home-dir {} git-filter\n", - yolk_binary_path.display(), - env.yolk_root().path().display(), - env.home.path().display(), + "{} --yolk-dir '{}' --home-dir '{}' git-filter\n", + yolk_binary_path.display().to_string().replace(r"\", r"\\"), + env.yolk_root() + .path() + .display() + .to_string() + .replace(r"\", r"\\"), + env.home.path().display().to_string().replace(r"\", r"\\"), )); Ok(()) } diff --git a/src/main.rs b/src/main.rs index f809459..3efb8fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -160,9 +160,11 @@ fn init_logging(args: &Args) { fn run_command(args: Args) -> Result<()> { let mut yolk_paths = yolk::yolk_paths::YolkPaths::from_env(); if let Some(d) = args.yolk_dir { + tracing::trace!("Setting yolk dir to {}", d.display()); yolk_paths.set_yolk_dir(d); } if let Some(d) = args.home_dir { + tracing::trace!("Setting home dir to {}", d.display()); yolk_paths.set_home_dir(d); } diff --git a/src/util.rs b/src/util.rs index 27bf965..54124eb 100644 --- a/src/util.rs +++ b/src/util.rs @@ -52,14 +52,20 @@ pub fn remove_symlink(path: impl AsRef) -> miette::Result<()> { if !path.is_symlink() { miette::bail!("Path is not a symlink: {}", path.abbr()); } - if path.is_dir() { + if path.symlink_metadata().into_diagnostic()?.is_dir() { symlink::remove_symlink_dir(path) .into_diagnostic() .wrap_err_with(|| format!("Failed to remove symlink dir at {}", path.abbr()))?; } else { - symlink::remove_symlink_file(path) - .into_diagnostic() - .wrap_err_with(|| format!("Failed to remove symlink file at {}", path.abbr()))?; + let result = symlink::remove_symlink_file(path); + if let Err(e) = result { + symlink::remove_symlink_dir(path) + .into_diagnostic() + .wrap_err("Failed to remove symlink dir as fallback from symlink file") + .wrap_err_with(|| { + format!("Failed to remove symlink file at {}: {e:?}", path.abbr()) + })?; + } } Ok(()) } diff --git a/src/yolk.rs b/src/yolk.rs index 7648c72..522265a 100644 --- a/src/yolk.rs +++ b/src/yolk.rs @@ -66,11 +66,27 @@ impl Yolk { ) .context("Failed to ensure .gitignore is configured correctly")?; + // Apparently, git on windows doesn't really deal with backslashes all that well. + // When you run git config to set a value that contains a backslash, the .git/config file will store + // it with two backslashes. However, when git actually executes the git filter process, + // it seems to just remove those, resulting in it trying to put "CUsersfoo" as the home argument, etc. + // Therefore, we add an extra level of backslashes here, resulting in four backslashes per backslash in the .git/config file. + // Then,... it just works. let yolk_process_cmd = &format!( - "{} --yolk-dir {} --home-dir {} git-filter", - yolk_binary.unwrap_or("yolk"), - self.yolk_paths.root_path().canonical()?.display(), - self.yolk_paths.home_path().canonical()?.display() + "{} --yolk-dir '{}' --home-dir '{}' git-filter", + yolk_binary.unwrap_or("yolk").replace(r"\", r"\\"), + self.yolk_paths + .root_path() + .canonical()? + .display() + .to_string() + .replace(r"\", r"\\"), + self.yolk_paths + .home_path() + .canonical()? + .display() + .to_string() + .replace(r"\", r"\\") ); self.paths() .start_git_command_builder() @@ -114,7 +130,7 @@ impl Yolk { if deployed.is_symlink() { let target = deployed.fs_err_read_link().into_diagnostic()?; if target.starts_with(egg.path()) { - fs_err::remove_file(deployed).into_diagnostic()?; + util::remove_symlink(deployed)?; tracing::info!("Removed dead symlink {}", deployed.abbr()); } } @@ -493,7 +509,7 @@ fn symlink_recursive( link_path.abbr(), link_target.abbr() ); - fs_err::remove_file(&link_path).into_diagnostic()?; + util::remove_symlink(&link_path)?; cov_mark::hit!(remove_dead_symlink); // After we've removed that file, creating the symlink later will succeed! } else { @@ -586,13 +602,13 @@ mod test { use crate::{ eggs_config::DeploymentStrategy, - util::{ - create_regex, - test_util::{render_error, render_report, setup_and_init_test_yolk, TestResult}, - }, + util::test_util::{setup_and_init_test_yolk, TestResult}, yolk::EvalMode, yolk_paths::Egg, }; + + #[cfg(not(windows))] + use crate::util::test_util; use assert_fs::{ assert::PathAssert, prelude::{FileWriteStr, PathChild, PathCreateDir}, @@ -888,6 +904,7 @@ mod test { } #[test] + #[cfg(not(windows))] fn test_sync_eggs_continues_after_failure() -> TestResult { let (home, yolk, eggs) = setup_and_init_test_yolk()?; home.child("yolk/yolk.rhai").write_str(indoc::indoc! {r#" @@ -902,7 +919,7 @@ mod test { eggs.child("foo/foo").assert(r#"{< invalid rhai >}"#); eggs.child("bar/bar") .assert(r#"# foo # {}"#); - assert!(render_error(result.unwrap_err()).contains("Syntax error")); + assert!(test_util::render_error(result.unwrap_err()).contains("Syntax error")); Ok(()) } @@ -978,7 +995,10 @@ mod test { } #[test] + #[cfg(not(windows))] pub fn test_syntax_error_in_yolk_rhai() -> TestResult { + use crate::util::create_regex; + let (home, yolk, _) = setup_and_init_test_yolk()?; home.child("yolk/yolk.rhai").write_str(indoc::indoc! {r#" fn foo( @@ -987,7 +1007,7 @@ mod test { .prepare_eval_ctx_for_templates(crate::yolk::EvalMode::Local) .map_err(|e| create_regex(r"\[.*.rhai:\d+:\d+]") .unwrap() - .replace(&render_report(e), "[no-filename-in-test]") + .replace(&test_util::render_report(e), "[no-filename-in-test]") .to_string()) .unwrap_err()); @@ -995,6 +1015,7 @@ mod test { } #[test] + #[cfg(not(windows))] pub fn test_deployment_error() -> TestResult { let (home, yolk, eggs) = setup_and_init_test_yolk()?; eggs.child("bar/file1").write_str("")?; @@ -1012,7 +1033,7 @@ mod test { (r"\.tmp[a-zA-Z0-9]{6}", "[tmp-dir]"), (r"file\d", "[filename]") ]}, { - insta::assert_snapshot!(render_error( + insta::assert_snapshot!(test_util::render_error( yolk.sync_egg_deployment(&egg).unwrap_err() )); }); diff --git a/src/yolk_paths.rs b/src/yolk_paths.rs index 2580f81..fabe8fa 100644 --- a/src/yolk_paths.rs +++ b/src/yolk_paths.rs @@ -58,9 +58,11 @@ impl YolkPaths { } pub fn set_yolk_dir(&mut self, path: PathBuf) { + tracing::trace!("Updating oylk-dir to {}", path.display()); self.root_path = path; } pub fn set_home_dir(&mut self, path: PathBuf) { + tracing::trace!("Updating home-dir to {}", path.display()); self.home = path .canonical() .expect("Failed to canonicalize home directory"); @@ -337,7 +339,7 @@ impl Iterator for TraverseDeployment { #[cfg(test)] mod test { use crate::{ - util::test_util::{setup_and_init_test_yolk, TestResult}, + util::{self, test_util::{setup_and_init_test_yolk, TestResult}}, yolk_paths::{Egg, DEFAULT_YOLK_RHAI}, }; use assert_fs::{ @@ -396,7 +398,7 @@ mod test { assert!(!(egg.is_deployed()?)); yolk.sync_egg_deployment(&egg)?; assert!(egg.is_deployed()?); - fs_err::remove_file(home.child("target"))?; + util::remove_symlink(home.child("target"))?; assert!(!(egg.is_deployed()?)); Ok(()) }