Skip to content

Commit

Permalink
fix: Fix path handling on windows when interacting with git
Browse files Browse the repository at this point in the history
  • Loading branch information
elkowar committed Feb 2, 2025
1 parent 89a866f commit db50b8c
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 23 deletions.
12 changes: 8 additions & 4 deletions src/git_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
14 changes: 10 additions & 4 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,20 @@ pub fn remove_symlink(path: impl AsRef<Path>) -> 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(())
}
Expand Down
47 changes: 34 additions & 13 deletions src/yolk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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());
}
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -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#"
Expand All @@ -902,7 +919,7 @@ mod test {
eggs.child("foo/foo").assert(r#"{< invalid rhai >}"#);
eggs.child("bar/bar")
.assert(r#"#<yolk> foo # {<if false>}"#);
assert!(render_error(result.unwrap_err()).contains("Syntax error"));
assert!(test_util::render_error(result.unwrap_err()).contains("Syntax error"));
Ok(())
}

Expand Down Expand Up @@ -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(
Expand All @@ -987,14 +1007,15 @@ 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());

Ok(())
}

#[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("")?;
Expand All @@ -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()
));
});
Expand Down
6 changes: 4 additions & 2 deletions src/yolk_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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::{
Expand Down Expand Up @@ -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(())
}
Expand Down

0 comments on commit db50b8c

Please sign in to comment.