diff --git a/CHANGELOG.md b/CHANGELOG.md index f64bce337b2..a2f645f6de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * new function `working_copies()` for revsets to show the working copy commits of all workspaces. +* `jj status` now supports filtering by paths. For example, `jj status .` will + only list changed files that are descendants of the current directory. + ### Fixed bugs ## [0.15.1] - 2024-03-06 diff --git a/cli/src/commands/status.rs b/cli/src/commands/status.rs index 982570843a4..f73ec524218 100644 --- a/cli/src/commands/status.rs +++ b/cli/src/commands/status.rs @@ -13,7 +13,6 @@ // limitations under the License. use itertools::Itertools; -use jj_lib::matchers::EverythingMatcher; use jj_lib::repo::Repo; use jj_lib::rewrite::merge_commit_trees; use tracing::instrument; @@ -34,13 +33,17 @@ use crate::ui::Ui; /// * Conflicted branches (see https://github.com/martinvonz/jj/blob/main/docs/branches.md) #[derive(clap::Args, Clone, Debug)] #[command(visible_alias = "st")] -pub(crate) struct StatusArgs {} +pub(crate) struct StatusArgs { + /// Restrict the status display to these paths + #[arg(value_hint = clap::ValueHint::AnyPath)] + paths: Vec, +} #[instrument(skip_all)] pub(crate) fn cmd_status( ui: &mut Ui, command: &CommandHelper, - _args: &StatusArgs, + args: &StatusArgs, ) -> Result<(), CommandError> { let workspace_command = command.workspace_helper(ui)?; let repo = workspace_command.repo(); @@ -48,6 +51,7 @@ pub(crate) fn cmd_status( .get_wc_commit_id() .map(|id| repo.store().get_commit(id)) .transpose()?; + let matcher = workspace_command.matcher_from_values(&args.paths)?; ui.request_pager(); let mut formatter = ui.stdout_formatter(); let formatter = formatter.as_mut(); @@ -62,10 +66,12 @@ pub(crate) fn cmd_status( diff_util::show_diff_summary( formatter, &workspace_command, - parent_tree.diff_stream(&tree, &EverythingMatcher), + parent_tree.diff_stream(&tree, matcher.as_ref()), )?; } + // TODO: Conflicts should also be filtered by the `matcher`. See the related TODO on + // `MergedTree::conflicts()`. let conflicts = wc_commit.tree()?.conflicts().collect_vec(); if !conflicts.is_empty() { writeln!( diff --git a/cli/tests/cli-reference@.md.snap b/cli/tests/cli-reference@.md.snap index 4957f73fb41..8cae8a5d021 100644 --- a/cli/tests/cli-reference@.md.snap +++ b/cli/tests/cli-reference@.md.snap @@ -1741,7 +1741,11 @@ This includes: * Conflicted branches (see https://github.com/martinvonz/jj/blob/main/docs/branches.md) -**Usage:** `jj status` +**Usage:** `jj status [PATHS]...` + +###### **Arguments:** + +* `` — Restrict the status display to these paths diff --git a/cli/tests/test_status_command.rs b/cli/tests/test_status_command.rs index 574dda0712e..3bf22d6144a 100644 --- a/cli/tests/test_status_command.rs +++ b/cli/tests/test_status_command.rs @@ -62,3 +62,22 @@ fn test_status_ignored_gitignore() { Parent commit: zzzzzzzz 00000000 (empty) (no description set) "###); } + +#[test] +fn test_status_filtered() { + let test_env = TestEnvironment::default(); + test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); + let repo_path = test_env.env_root().join("repo"); + + std::fs::write(repo_path.join("file_1"), "file_1").unwrap(); + std::fs::write(repo_path.join("file_2"), "file_2").unwrap(); + + // The output filtered to file_1 should not list the addition of file_2. + let stdout = test_env.jj_cmd_success(&repo_path, &["status", "file_1"]); + insta::assert_snapshot!(stdout, @r###" + Working copy changes: + A file_1 + Working copy : qpvuntsm abcaaacd (no description set) + Parent commit: zzzzzzzz 00000000 (empty) (no description set) + "###); +}