From c9c3735fafea1e5631d9b508551c0b292e17a5be Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Tue, 13 Sep 2022 16:26:23 +0900 Subject: [PATCH] cli: add basic support for 'jj log PATH' In the current implementation, tree is diffed twice if both PATH and -p are specified. If this adds significant cost, we'll need to reimplement it without using a revset abstraction (or maybe adjust revset/graph API.) --- CHANGELOG.md | 2 ++ README.md | 2 +- src/commands.rs | 14 +++++++++---- tests/test_log_command.rs | 43 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccbda5389..43d424bf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,6 +138,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * `jj log` now accepts a `--reversed` option, which will show older commits first. +* `jj log` now accepts file paths. + * `jj obslog` now accepts `-p`/`--patch` option, which will show the diff compared to the previous version of the change. diff --git a/README.md b/README.md index a17f2461c..48bf102d5 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ commit to any other commit using `jj move`. ## Status The tool is quite feature-complete, but some important features like (the -equivalent of) `git blame` and `git log ` are not yet supported. There +equivalent of) `git blame` are not yet supported. There are also several performance bugs. It's also likely that workflows and setups different from what I personally use are not well supported. For example, pull-request workflows currently require too many manual steps. diff --git a/src/commands.rs b/src/commands.rs index a8f48e7d6..11f59f391 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1319,6 +1319,8 @@ struct LogArgs { default_value = "remote_branches().. | (remote_branches()..)-" )] revisions: String, + /// Show commits modifying the given paths + paths: Vec, /// Show revisions in the opposite order (older revisions first) #[clap(long)] reversed: bool, @@ -3114,8 +3116,12 @@ fn cmd_log(ui: &mut Ui, command: &CommandHelper, args: &LogArgs) -> Result<(), C let repo = workspace_command.repo(); let workspace_id = workspace_command.workspace_id(); let checkout_id = repo.view().get_checkout(&workspace_id); - let matcher = EverythingMatcher; - let revset = revset_expression.evaluate(repo.as_repo_ref(), Some(&workspace_id))?; + let matcher = matcher_from_values(ui, workspace_command.workspace_root(), &args.paths)?; + let mut revset = revset_expression.evaluate(repo.as_repo_ref(), Some(&workspace_id))?; + if !args.paths.is_empty() { + revset = revset::filter_by_diff(repo.as_repo_ref(), matcher.as_ref(), revset); + } + let store = repo.store(); let diff_format = (args.patch || args.diff_format.git || args.diff_format.summary) .then(|| diff_format_for(ui, &args.diff_format)); @@ -3190,7 +3196,7 @@ fn cmd_log(ui: &mut Ui, command: &CommandHelper, args: &LogArgs) -> Result<(), C formatter.as_mut(), &workspace_command, &commit, - &matcher, + matcher.as_ref(), diff_format, )?; } @@ -3216,7 +3222,7 @@ fn cmd_log(ui: &mut Ui, command: &CommandHelper, args: &LogArgs) -> Result<(), C formatter, &workspace_command, &commit, - &matcher, + matcher.as_ref(), diff_format, )?; } diff --git a/tests/test_log_command.rs b/tests/test_log_command.rs index fc78223df..8dbccbf0f 100644 --- a/tests/test_log_command.rs +++ b/tests/test_log_command.rs @@ -155,3 +155,46 @@ fn test_log_reversed() { second "###); } + +#[test] +fn test_log_filtered_by_path() { + let test_env = TestEnvironment::default(); + test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); + let repo_path = test_env.env_root().join("repo"); + + std::fs::write(repo_path.join("file1"), "foo\n").unwrap(); + test_env.jj_cmd_success(&repo_path, &["describe", "-m", "first"]); + test_env.jj_cmd_success(&repo_path, &["new", "-m", "second"]); + std::fs::write(repo_path.join("file1"), "foo\nbar\n").unwrap(); + std::fs::write(repo_path.join("file2"), "baz\n").unwrap(); + + let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", "description", "file1"]); + insta::assert_snapshot!(stdout, @r###" + @ second + o first + ~ + "###); + + let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", "description", "file2"]); + insta::assert_snapshot!(stdout, @r###" + @ second + ~ + "###); + + let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", "description", "-s", "file1"]); + insta::assert_snapshot!(stdout, @r###" + @ second + | M file1 + o first + ~ A file1 + "###); + + let stdout = test_env.jj_cmd_success( + &repo_path, + &["log", "-T", "description", "-s", "file2", "--no-graph"], + ); + insta::assert_snapshot!(stdout, @r###" + second + A file2 + "###); +}