Skip to content

Commit

Permalink
attempt ancestor canonicalization first, use in get_relative_path
Browse files Browse the repository at this point in the history
  • Loading branch information
jazzfool committed Mar 14, 2023
1 parent 4f066b1 commit 02ebcff
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions helix-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ regex = "1"
bitflags = "1.3"
ahash = "0.8.3"
hashbrown = { version = "0.13.2", features = ["raw"] }
dunce = "1.0"

log = "0.4"
serde = { version = "1.0", features = ["derive"] }
Expand Down
32 changes: 28 additions & 4 deletions helix-core/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ pub fn expand_tilde(path: &Path) -> PathBuf {
/// needs to improve on.
/// Copied from cargo: <https://github.com/rust-lang/cargo/blob/070e459c2d8b79c5b2ac5218064e7603329c92ae/crates/cargo-util/src/paths.rs#L81>
pub fn get_normalized_path(path: &Path) -> PathBuf {
// normalization strategy is to canonicalize first ancestor path that exists (i.e., canonicalize as much as possible),
// then run handrolled normalization on the non-existent remainder
let (base, path) = path
.ancestors()
.find(|path| path.exists())
.and_then(|path| Some((path, dunce::canonicalize(path).ok()?)))
.map(|(base, canonicalized)| {
(
canonicalized,
path.strip_prefix(base).unwrap(/* base is an ancestor of path */).into(),
)
})
.unwrap_or_else(|| (PathBuf::new(), PathBuf::from(path)));

if path.as_os_str().is_empty() {
return base;
}

let mut components = path.components().peekable();
let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
components.next();
Expand All @@ -63,7 +81,7 @@ pub fn get_normalized_path(path: &Path) -> PathBuf {
}
}
}
ret
base.join(ret)
}

/// Returns the canonical, absolute form of a path with all intermediate components normalized.
Expand All @@ -82,13 +100,19 @@ pub fn get_canonicalized_path(path: &Path) -> std::io::Result<PathBuf> {
}

pub fn get_relative_path(path: &Path) -> PathBuf {
let path = PathBuf::from(path);
let path = if path.is_absolute() {
let cwdir = std::env::current_dir().expect("couldn't determine current directory");
path.strip_prefix(cwdir).unwrap_or(path)
let cwdir = std::env::current_dir()
.map(|path| get_normalized_path(&path))
.expect("couldn't determine current directory");
get_normalized_path(&path)
.strip_prefix(cwdir)
.map(PathBuf::from)
.unwrap_or(path)
} else {
path
};
fold_home_dir(path)
fold_home_dir(&path)
}

/// Returns a truncated filepath where the basepart of the path is reduced to the first
Expand Down

0 comments on commit 02ebcff

Please sign in to comment.