diff --git a/CHANGELOG.md b/CHANGELOG.md index 6feac5031..7d78ff840 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * New command `jj parallelize` that rebases a set of revisions into siblings. +* `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.16.0] - 2024-04-03 diff --git a/cli/src/commands/status.rs b/cli/src/commands/status.rs index 5c190e6a6..a446d5176 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; @@ -33,13 +32,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(); @@ -47,6 +50,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(); @@ -61,10 +65,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 39638eaa5..6b0a01137 100644 --- a/cli/tests/cli-reference@.md.snap +++ b/cli/tests/cli-reference@.md.snap @@ -1779,7 +1779,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 574dda071..3bf22d614 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) + "###); +}