From 638cddcf83e123821e55afb3abe579cc5666f8d5 Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Sat, 3 Jun 2023 04:24:39 -0400 Subject: [PATCH] handle relative paths when using Ignore programmatically (#599) --- crates/ignore-files/Cargo.toml | 3 ++- crates/ignore-files/src/error.rs | 11 +++++++++++ crates/ignore-files/src/filter.rs | 20 ++++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/crates/ignore-files/Cargo.toml b/crates/ignore-files/Cargo.toml index 21eaf95..7d1facc 100644 --- a/crates/ignore-files/Cargo.toml +++ b/crates/ignore-files/Cargo.toml @@ -20,11 +20,12 @@ gix-config = "0.22.0" ignore = "0.4.18" miette = "5.3.0" thiserror = "1.0.31" -tokio = { version = "1.24.2", default-features = false, features = ["fs"] } +tokio = { version = "1.24.2", default-features = false, features = ["fs", "macros", "rt"] } tracing = "0.1.35" radix_trie = "0.2.1" dunce = "1.0.4" + [dependencies.project-origins] version = "1.2.0" path = "../project-origins" diff --git a/crates/ignore-files/src/error.rs b/crates/ignore-files/src/error.rs index b96eb98..4291505 100644 --- a/crates/ignore-files/src/error.rs +++ b/crates/ignore-files/src/error.rs @@ -37,4 +37,15 @@ pub enum Error { #[error("multiple: {0:?}")] #[diagnostic(code(ignore_file::set))] Multi(#[related] Vec), + + /// Error received when trying to canonicalize a path + #[error("cannot canonicalize '{path:?}'")] + Canonicalize { + /// the path that cannot be canonicalized + path: PathBuf, + + /// the underlying error + #[source] + err: std::io::Error, + }, } diff --git a/crates/ignore-files/src/filter.rs b/crates/ignore-files/src/filter.rs index 49d5839..3663caf 100644 --- a/crates/ignore-files/src/filter.rs +++ b/crates/ignore-files/src/filter.rs @@ -6,7 +6,7 @@ use ignore::{ Match, }; use radix_trie::{Trie, TrieCommon}; -use tokio::fs::read_to_string; +use tokio::fs::{canonicalize, read_to_string}; use tracing::{trace, trace_span}; use crate::{Error, IgnoreFile}; @@ -55,7 +55,12 @@ impl IgnoreFilter { /// Use [`empty()`](IgnoreFilter::empty()) if you want an empty filterer, /// or to construct one outside an async environment. pub async fn new(origin: impl AsRef + Send, files: &[IgnoreFile]) -> Result { - let origin = dunce::simplified(origin.as_ref()); + let origin = origin.as_ref().to_owned(); + let origin = canonicalize(&origin) + .await + .map_err(move |err| Error::Canonicalize { path: origin, err })?; + + let origin = dunce::simplified(&origin); let _span = trace_span!("build_filterer", ?origin); trace!(files=%files.len(), "loading file contents"); @@ -368,3 +373,14 @@ fn prefix>(path: T) -> String { _ => "/".into(), } } + +#[cfg(test)] +mod tests { + use super::IgnoreFilter; + + #[tokio::test] + async fn handle_relative_paths() { + let ignore = IgnoreFilter::new(".", &[]).await.unwrap(); + assert!(ignore.origin.is_absolute()); + } +}