diff --git a/Cargo.lock b/Cargo.lock index 836e2ab692..415fb19152 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -917,6 +917,7 @@ dependencies = [ "indicatif", "lazy_static", "log", + "pathdiff", "pprof", "pretty_assertions", "rand", @@ -1944,9 +1945,9 @@ dependencies = [ [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "percent-encoding" diff --git a/git-cliff-core/src/error.rs b/git-cliff-core/src/error.rs index 255d99c20d..0485209dc7 100644 --- a/git-cliff-core/src/error.rs +++ b/git-cliff-core/src/error.rs @@ -101,6 +101,9 @@ pub enum Error { /// Error that may occur while handling location of directories. #[error("Directory error: `{0}`")] DirsError(String), + /// Error that may occur while constructing patterns. + #[error("Pattern error: `{0}`")] + PatternError(#[from] glob::PatternError), } /// Result type of the core library. diff --git a/git-cliff-core/src/repo.rs b/git-cliff-core/src/repo.rs index eb9ad0b143..11fc2778ff 100644 --- a/git-cliff-core/src/repo.rs +++ b/git-cliff-core/src/repo.rs @@ -39,7 +39,7 @@ const CHANGED_FILES_CACHE: &str = "changed_files_cache"; pub struct Repository { inner: GitRepository, /// Repository path. - pub path: PathBuf, + path: PathBuf, /// Cache path for the changed files of the commits. changed_files_cache_path: PathBuf, } @@ -74,6 +74,15 @@ impl Repository { } } + /// Returns the path of the repository. + pub fn path(&self) -> PathBuf { + let mut path = self.inner.path().to_path_buf(); + if path.ends_with(".git") { + path.pop(); + } + path + } + /// Parses and returns the commits. /// /// Sorts the commits by their time. diff --git a/git-cliff/Cargo.toml b/git-cliff/Cargo.toml index 73d78d5c2d..cf2d286750 100644 --- a/git-cliff/Cargo.toml +++ b/git-cliff/Cargo.toml @@ -57,6 +57,7 @@ env_logger = "=0.10.2" pprof = { version = "0.14", optional = true } rand = { version = "0.8.4", optional = true } url.workspace = true +pathdiff = "0.2.3" [dependencies.git-cliff-core] version = "2.7.0" # managed by release.sh diff --git a/git-cliff/src/lib.rs b/git-cliff/src/lib.rs index 95d37b738e..48e0c15216 100644 --- a/git-cliff/src/lib.rs +++ b/git-cliff/src/lib.rs @@ -40,6 +40,7 @@ use git_cliff_core::{ DEFAULT_CONFIG, IGNORE_FILE, }; +use glob::Pattern; use std::env; use std::fs::{ self, @@ -210,9 +211,27 @@ fn process_repository<'a>( } } } + + // Include only the current directory if not running from the root repository + let mut include_path = args.include_path.clone(); + if let Some(mut path_diff) = + pathdiff::diff_paths(env::current_dir()?, repository.path()) + { + if include_path.is_none() && path_diff != Path::new("") { + info!( + "Including changes from the current directory: {:?}", + path_diff.display() + ); + path_diff.extend(["**", "*"]); + include_path = Some(vec![Pattern::new( + &path_diff.to_string_lossy().to_string(), + )?]); + } + } + let mut commits = repository.commits( commit_range.as_deref(), - args.include_path.clone(), + include_path, args.exclude_path.clone(), )?; if let Some(commit_limit_value) = config.git.limit_commits { @@ -250,7 +269,7 @@ fn process_repository<'a>( let commit = Commit::from(git_commit); let commit_id = commit.id.to_string(); release.commits.push(commit); - release.repository = Some(repository.path.to_string_lossy().into_owned()); + release.repository = Some(repository.path().to_string_lossy().into_owned()); if let Some(tag) = tags.get(&commit_id) { release.version = Some(tag.name.to_string()); release.message.clone_from(&tag.message); diff --git a/website/docs/usage/monorepos.md b/website/docs/usage/monorepos.md index 18e8a504b0..d60c2e8a93 100644 --- a/website/docs/usage/monorepos.md +++ b/website/docs/usage/monorepos.md @@ -4,16 +4,18 @@ sidebar_position: 5 # Monorepos -You can generate a changelog scoped to a specific directory via `--include-path` and `--exclude-path`. - -This requires changing the current working directory to the target folder. The included/excluded paths must be relative to the repository's root. +You can generate a changelog scoped to a specific directory by just switching to that directory: ```bash cd packages/some_library -git cliff --include-path "packages/some_library/**/*" --repository "../../" +git cliff ``` +To include/exclude specific paths, use the `--include-path` and `--exclude-path` arguments: + ```bash cd packages/some_library -git cliff --include-path "packages/some_library/**/*" --repository "../../" --exclude-path ".github/*" +git cliff --include-path "packages/some_library/**/*" --exclude-path ".github/*" ``` + +These paths must be relative to the repository's root and should be a valid glob pattern.