From 00a9a152075d9496c33622a9478364bdf718150f Mon Sep 17 00:00:00 2001 From: Riccardo Binetti Date: Wed, 21 Sep 2022 21:42:09 +0200 Subject: [PATCH] Split helix_core::find_root and helix_loader::find_local_config_dirs The documentation of find_root described the following priority for detecting a project root: - Top-most folder containing a root marker in current git repository - Git repository root if no marker detected - Top-most folder containing a root marker if not git repository detected - Current working directory as fallback The commit contained in https://github.com/helix-editor/helix/pull/1249 extracted and changed the implementation of find_root in find_root_impl, actually reversing its result order (since that is the order that made sense for the local configuration merge, from innermost to outermost ancestors). Since the two uses of find_root_impl have different requirements (and it's not a matter of reversing the order of results since, e.g., the top repository dir should be used by find_root only if there's not marker in other dirs), this PR splits the two implementations in two different specialized functions. In doing so, find_root_impl is removed and the implementation is moved back in find_root, moving it closer to the documented behaviour thus making it easier to verify it's actually correct --- helix-core/src/lib.rs | 37 ++++++++++++++++++++++++++++++++++--- helix-loader/src/lib.rs | 26 +++++--------------------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs index 735a62c1b2cad..3e1d2038a4602 100644 --- a/helix-core/src/lib.rs +++ b/helix-core/src/lib.rs @@ -47,9 +47,40 @@ pub fn find_first_non_whitespace_char(line: RopeSlice) -> Option { /// * Top-most folder containing a root marker if not git repository detected /// * Current working directory as fallback pub fn find_root(root: Option<&str>, root_markers: &[String]) -> Option { - helix_loader::find_root_impl(root, root_markers) - .first() - .cloned() + let current_dir = std::env::current_dir().expect("unable to determine current directory"); + + let root = match root { + Some(root) => { + let root = std::path::Path::new(root); + if root.is_absolute() { + root.to_path_buf() + } else { + current_dir.join(root) + } + } + None => current_dir.clone(), + }; + + let mut top_marker = None; + for ancestor in root.ancestors() { + if root_markers + .iter() + .any(|marker| ancestor.join(marker).exists()) + { + top_marker = Some(ancestor); + } + + // Don't go higher than repo if we're in one + if ancestor.join(".git").is_dir() { + // Top marker is repo root if not root marker is detected + if top_marker.is_none() { + top_marker = Some(ancestor); + } + } + } + + // Return the found top marker or the current_dir as fallback + top_marker.map(|a| a.to_path_buf()).or(Some(current_dir)) } pub use ropey::{str_utils, Rope, RopeBuilder, RopeSlice}; diff --git a/helix-loader/src/lib.rs b/helix-loader/src/lib.rs index 3c9905f5a14b4..46f6db8f1af5d 100644 --- a/helix-loader/src/lib.rs +++ b/helix-loader/src/lib.rs @@ -59,7 +59,7 @@ pub fn config_dir() -> PathBuf { } pub fn local_config_dirs() -> Vec { - let directories = find_root_impl(None, &[".helix".to_string()]) + let directories = find_local_config_dirs() .into_iter() .map(|path| path.join(".helix")) .collect(); @@ -90,32 +90,16 @@ pub fn log_file() -> PathBuf { cache_dir().join("helix.log") } -pub fn find_root_impl(root: Option<&str>, root_markers: &[String]) -> Vec { +pub fn find_local_config_dirs() -> Vec { let current_dir = std::env::current_dir().expect("unable to determine current directory"); let mut directories = Vec::new(); - let root = match root { - Some(root) => { - let root = std::path::Path::new(root); - if root.is_absolute() { - root.to_path_buf() - } else { - current_dir.join(root) - } - } - None => current_dir, - }; - - for ancestor in root.ancestors() { - // don't go higher than repo + for ancestor in current_dir.ancestors() { + // Don't go higher than repo if we're in one if ancestor.join(".git").is_dir() { - // Use workspace if detected from marker directories.push(ancestor.to_path_buf()); break; - } else if root_markers - .iter() - .any(|marker| ancestor.join(marker).exists()) - { + } else if ancestor.join(".helix").is_dir() { directories.push(ancestor.to_path_buf()); } }