diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 5826031e1..a9d8cc241 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -354,7 +354,7 @@ struct LogArgs { /// or `@ | (remote_branches() | tags()).. | ((remote_branches() | /// tags())..)-` if it is not set. #[arg(long, short)] - revisions: Option, + revisions: Vec, /// Show commits modifying the given paths #[arg(value_hint = clap::ValueHint::AnyPath)] paths: Vec, @@ -1541,9 +1541,16 @@ fn cmd_status( fn cmd_log(ui: &mut Ui, command: &CommandHelper, args: &LogArgs) -> Result<(), CommandError> { let workspace_command = command.workspace_helper(ui)?; - let default_revset = command.settings().default_revset(); - let revset_expression = - workspace_command.parse_revset(args.revisions.as_deref().unwrap_or(&default_revset))?; + let revset_expression = if args.revisions.is_empty() { + workspace_command.parse_revset(&command.settings().default_revset())? + } else { + let expressions: Vec<_> = args + .revisions + .iter() + .map(|revision_str| workspace_command.parse_revset(revision_str)) + .try_collect()?; + RevsetExpression::union_all(&expressions) + }; let repo = workspace_command.repo(); let wc_commit_id = workspace_command.get_wc_commit_id(); let revset_expression = if !args.paths.is_empty() { @@ -1668,7 +1675,7 @@ fn cmd_log(ui: &mut Ui, command: &CommandHelper, args: &LogArgs) -> Result<(), C // Check to see if the user might have specified a path when they intended // to specify a revset. - if let (None, [only_path]) = (&args.revisions, args.paths.as_slice()) { + if let ([], [only_path]) = (args.revisions.as_slice(), args.paths.as_slice()) { if only_path == "." && workspace_command.parse_file_path(only_path)?.is_root() { // For users of e.g. Mercurial, where `.` indicates the current commit. writeln!( diff --git a/tests/test_log_command.rs b/tests/test_log_command.rs index 2d09a14c1..4d3d5bdad 100644 --- a/tests/test_log_command.rs +++ b/tests/test_log_command.rs @@ -866,6 +866,44 @@ fn test_default_revset_per_repo() { ); } +#[test] +fn test_multiple_revsets() { + 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"); + for name in ["foo", "bar", "baz"] { + test_env.jj_cmd_success(&repo_path, &["new", "-m", name]); + test_env.jj_cmd_success(&repo_path, &["branch", "set", name]); + } + + // Default revset should be overridden if one or more -r options are specified. + test_env.add_config(r#"revsets.log = "root""#); + + insta::assert_snapshot!( + test_env.jj_cmd_success(&repo_path, &["log", "-T", "branches", "-rfoo"]), + @r###" + ◉ foo + │ + ~ + "###); + insta::assert_snapshot!( + test_env.jj_cmd_success(&repo_path, &["log", "-T", "branches", "-rfoo", "-rbar", "-rbaz"]), + @r###" + @ baz + ◉ bar + ◉ foo + │ + ~ + "###); + insta::assert_snapshot!( + test_env.jj_cmd_success(&repo_path, &["log", "-T", "branches", "-rfoo", "-rfoo"]), + @r###" + ◉ foo + │ + ~ + "###); +} + #[test] fn test_graph_template_color() { // Test that color codes from a multi-line template don't span the graph lines.