diff --git a/cli/src/commands/operation.rs b/cli/src/commands/operation.rs index 24276ef95..261cc870c 100644 --- a/cli/src/commands/operation.rs +++ b/cli/src/commands/operation.rs @@ -164,7 +164,12 @@ fn cmd_op_log( None => command.settings().config().get_string("templates.op_log")?, }; let template_aliases = command.load_template_aliases(ui)?; - let template = operation_templater::parse(current_op_id, &template_string, &template_aliases)?; + let template = operation_templater::parse( + repo_loader.op_store().root_operation_id(), + current_op_id, + &template_string, + &template_aliases, + )?; let with_content_format = LogContentFormat::new(ui, command.settings())?; ui.request_pager(); diff --git a/cli/src/config/templates.toml b/cli/src/config/templates.toml index 459ae11f1..1a5355ee7 100644 --- a/cli/src/config/templates.toml +++ b/cli/src/config/templates.toml @@ -91,16 +91,19 @@ concat( ''' builtin_op_log_compact = ''' -label(if(current_operation, "current_operation"), - concat( - separate(" ", - id.short(), - user, - format_time_range(time), - ) ++ "\n", - description.first_line() ++ "\n", - if(tags, tags ++ "\n"), - ), +if(root, + builtin_op_log_root(id), + label(if(current_operation, "current_operation"), + concat( + separate(" ", + id.short(), + user, + format_time_range(time), + ) ++ "\n", + description.first_line() ++ "\n", + if(tags, tags ++ "\n"), + ), + ) ) ''' builtin_op_log_comfortable = 'builtin_op_log_compact ++ "\n"' @@ -114,6 +117,14 @@ separate(" ", ) ''' +'builtin_op_log_root(op_id)' = ''' +separate(" ", + op_id.short(), + label("root", "root()"), +) +''' + + description_placeholder = ''' label(if(empty, "empty ") ++ "description placeholder", "(no description set)")''' email_placeholder = 'label("email placeholder", "(no email set)")' diff --git a/cli/src/operation_templater.rs b/cli/src/operation_templater.rs index 56d32c723..0b1384f15 100644 --- a/cli/src/operation_templater.rs +++ b/cli/src/operation_templater.rs @@ -32,6 +32,7 @@ use crate::templater::{ }; struct OperationTemplateLanguage<'b> { + root_op_id: &'b OperationId, current_op_id: Option<&'b OperationId>, } @@ -148,6 +149,10 @@ fn build_operation_keyword( // TODO: introduce dedicated type and provide accessors? format!("{}@{}", metadata.username, metadata.hostname) })), + "root" => { + let root_op_id = language.root_op_id.clone(); + language.wrap_boolean(wrap_fn(move |op| op.id() == &root_op_id)) + } _ => return Err(TemplateParseError::no_such_keyword(name, span)), }; Ok(property) @@ -186,11 +191,15 @@ fn build_operation_id_method( } pub fn parse( + root_op_id: &OperationId, current_op_id: Option<&OperationId>, template_text: &str, aliases_map: &TemplateAliasesMap, ) -> TemplateParseResult>> { - let language = OperationTemplateLanguage { current_op_id }; + let language = OperationTemplateLanguage { + root_op_id, + current_op_id, + }; let node = template_parser::parse(template_text, aliases_map)?; template_builder::build(&language, &node) } diff --git a/cli/tests/test_concurrent_operations.rs b/cli/tests/test_concurrent_operations.rs index 0246f102b..b247e2e3a 100644 --- a/cli/tests/test_concurrent_operations.rs +++ b/cli/tests/test_concurrent_operations.rs @@ -45,8 +45,7 @@ fn test_concurrent_operation_divergence() { │ add workspace 'default' ◉ 0e8aee02e242 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 │ initialize repo - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); // We should be informed about the concurrent modification @@ -82,8 +81,7 @@ fn test_concurrent_operations_auto_rebase() { │ add workspace 'default' ◉ 0e8aee02e242 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 │ initialize repo - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); let op_id_hex = stdout[3..15].to_string(); diff --git a/cli/tests/test_operations.rs b/cli/tests/test_operations.rs index d1c309525..f2a13a0f3 100644 --- a/cli/tests/test_operations.rs +++ b/cli/tests/test_operations.rs @@ -45,8 +45,7 @@ fn test_op_log() { │ add workspace 'default' ◉ 0e8aee02e242 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 │ initialize repo - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); let op_log_lines = stdout.lines().collect_vec(); let add_workspace_id = op_log_lines[3].split(' ').nth(2).unwrap(); @@ -121,8 +120,7 @@ fn test_op_log_no_graph() { add workspace 'default' 0e8aee02e242 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 initialize repo - 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + 000000000000 root() "###); } @@ -191,8 +189,7 @@ fn test_op_log_template() { │ add workspace 'default' ◉ 0e8aee02e242 test-username@host.example.com NN years ago, lasted less than a microsecond │ initialize repo - ◉ 000000000000 @ NN years ago, lasted less than a microsecond - + ◉ 000000000000 root() "###); } @@ -212,8 +209,7 @@ fn test_op_log_builtin_templates() { │ add workspace 'default' ◉ 0e8aee02e242 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 │ initialize repo - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); insta::assert_snapshot!(render(r#"builtin_op_log_comfortable"#), @r###" @@ -227,9 +223,7 @@ fn test_op_log_builtin_templates() { ◉ 0e8aee02e242 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 │ initialize repo │ - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - - + ◉ 000000000000 root() "###); } @@ -258,8 +252,7 @@ fn test_op_log_word_wrap() { │ add workspace 'default' ◉ 0e8aee02e242 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 │ initialize repo - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); insta::assert_snapshot!(render(&["op", "log"], 40, true), @r###" @ 27143b59c690 @@ -272,10 +265,7 @@ fn test_op_log_word_wrap() { │ 2001-02-03 04:05:07.000 +07:00 - │ 2001-02-03 04:05:07.000 +07:00 │ initialize repo - ◉ 000000000000 @ 1970-01-01 - 00:00:00.000 +00:00 - 1970-01-01 - 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); } @@ -318,8 +308,7 @@ fn test_op_abandon_ancestors() { │ add workspace 'default' ◉ 0e8aee02e242 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 │ initialize repo - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); // Abandon old operations. The working-copy operation id should be updated. @@ -336,8 +325,7 @@ fn test_op_abandon_ancestors() { @ 1c88fada5b95 test-username@host.example.com 2001-02-03 04:05:09.000 +07:00 - 2001-02-03 04:05:09.000 +07:00 │ commit a8ac27b29a157ae7dabc0deb524df68823505730 │ args: jj commit -m 'commit 2' - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); // Abandon operation range. @@ -355,8 +343,7 @@ fn test_op_abandon_ancestors() { ◉ 1c88fada5b95 test-username@host.example.com 2001-02-03 04:05:09.000 +07:00 - 2001-02-03 04:05:09.000 +07:00 │ commit a8ac27b29a157ae7dabc0deb524df68823505730 │ args: jj commit -m 'commit 2' - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); // Can't abandon the current operation. @@ -390,8 +377,7 @@ fn test_op_abandon_ancestors() { ◉ 1c88fada5b95 test-username@host.example.com 2001-02-03 04:05:09.000 +07:00 - 2001-02-03 04:05:09.000 +07:00 │ commit a8ac27b29a157ae7dabc0deb524df68823505730 │ args: jj commit -m 'commit 2' - ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00 - 1970-01-01 00:00:00.000 +00:00 - + ◉ 000000000000 root() "###); // Abandon empty range. diff --git a/docs/templates.md b/docs/templates.md index f8c4825a2..b47c55b7f 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -50,6 +50,7 @@ The following keywords can be used in `jj op log` templates. * `tags: String` * `time: TimestampRange` * `user: String` +* `root: Boolean`: True if the commit is the root commit. ## Operators