diff options
| author | diogo464 <[email protected]> | 2023-06-28 08:58:22 +0100 |
|---|---|---|
| committer | diogo464 <[email protected]> | 2023-06-28 08:58:22 +0100 |
| commit | 66294e53ce2a9eb72af27bf595c64da4c7a1c0e2 (patch) | |
| tree | e2af7e73e0781de9d633e5798d0e50abf90683ea | |
| parent | c01d9d0445b5efa6ac0488667919fa51384d852e (diff) | |
fix: installing existing broken symlink.
When installing a symlink but the target symlink already existed and was
broken it would fail since it could not canonicalize the path properly.
`fs_exists` also failed to account for broken symlinks and would return
false when the symlink existed but was broken.
| -rw-r--r-- | src/dotup/mod.rs | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/src/dotup/mod.rs b/src/dotup/mod.rs index 3b0380b..4002f93 100644 --- a/src/dotup/mod.rs +++ b/src/dotup/mod.rs | |||
| @@ -181,8 +181,15 @@ pub fn install(dotup: &Dotup, params: &InstallParams, group: &str) -> Result<()> | |||
| 181 | let metadata = fs_symlink_metadata(&target)?; | 181 | let metadata = fs_symlink_metadata(&target)?; |
| 182 | 182 | ||
| 183 | // Early return if the symlink already points to the correct source | 183 | // Early return if the symlink already points to the correct source |
| 184 | if metadata.is_symlink() && fs_symlink_points_to(&target, &source)? { | 184 | if metadata.is_symlink() { |
| 185 | continue; | 185 | log::debug!( |
| 186 | "target is a symlink pointing to {}", | ||
| 187 | fs_read_symlink(&target)?.display() | ||
| 188 | ); | ||
| 189 | if fs_symlink_points_to(&target, &source)? { | ||
| 190 | log::debug!("target already points to the correct source, skipping"); | ||
| 191 | continue; | ||
| 192 | } | ||
| 186 | } | 193 | } |
| 187 | 194 | ||
| 188 | if !prompt_overwrite(params, &target)? { | 195 | if !prompt_overwrite(params, &target)? { |
| @@ -518,10 +525,14 @@ impl KeyValueParser { | |||
| 518 | // -------------------- Filesystem -------------------- // | 525 | // -------------------- Filesystem -------------------- // |
| 519 | 526 | ||
| 520 | fn fs_exists(path: impl AsRef<Path>) -> Result<bool> { | 527 | fn fs_exists(path: impl AsRef<Path>) -> Result<bool> { |
| 521 | path.as_ref().try_exists().map_err(|err| { | 528 | let path = path.as_ref(); |
| 529 | if path.is_symlink() { | ||
| 530 | return Ok(true); | ||
| 531 | } | ||
| 532 | path.try_exists().map_err(|err| { | ||
| 522 | Error::Custom(format!( | 533 | Error::Custom(format!( |
| 523 | "failed to check existence of target '{}': {}", | 534 | "failed to check existence of target '{}': {}", |
| 524 | path.as_ref().display(), | 535 | path.display(), |
| 525 | err | 536 | err |
| 526 | )) | 537 | )) |
| 527 | }) | 538 | }) |
| @@ -576,7 +587,10 @@ fn fs_symlink_points_to(path: impl AsRef<Path>, target: impl AsRef<Path>) -> Res | |||
| 576 | let path = path.as_ref(); | 587 | let path = path.as_ref(); |
| 577 | let target = target.as_ref(); | 588 | let target = target.as_ref(); |
| 578 | let link_target = fs_read_symlink(path)?; | 589 | let link_target = fs_read_symlink(path)?; |
| 579 | let target_canonical = fs_canonicalize(target)?; | 590 | let target_canonical = match fs_canonicalize(target) { |
| 591 | Ok(canonical) => canonical, | ||
| 592 | Err(_) => return Ok(false), | ||
| 593 | }; | ||
| 580 | let link_target_canonical = fs_canonicalize(link_target)?; | 594 | let link_target_canonical = fs_canonicalize(link_target)?; |
| 581 | Ok(target_canonical == link_target_canonical) | 595 | Ok(target_canonical == link_target_canonical) |
| 582 | } | 596 | } |
