From 24cd079307a4e7f52d4b85f17a666683de3e6d90 Mon Sep 17 00:00:00 2001 From: Siva Mahadevan Date: Fri, 28 Mar 2025 15:01:38 -0400 Subject: [PATCH] templates: create new git_format_patch_email_headers template With this template, a 'git format-patch' compatible email message can be generated using something like: jj show --git --template git_format_patch_email_headers --- cli/src/config/templates.toml | 18 ++++++++++++ cli/tests/test_commit_template.rs | 46 +++++++++++++++++++++++++++++++ cli/tests/test_completion.rs | 1 + cli/tests/test_evolog_command.rs | 1 + cli/tests/test_log_command.rs | 1 + cli/tests/test_operations.rs | 1 + cli/tests/test_show_command.rs | 1 + demos/demo_git_compat.sh | 3 ++ 8 files changed, 72 insertions(+) diff --git a/cli/src/config/templates.toml b/cli/src/config/templates.toml index 2689e7f6f..9de622365 100644 --- a/cli/src/config/templates.toml +++ b/cli/src/config/templates.toml @@ -402,3 +402,21 @@ coalesce( "o", ) ''' + +# The first line is a fixed magic date string used by +# programs like file(1) to identify that this is output from +# 'git format-patch'. +# See https://git-scm.com/docs/git-format-patch#_description +git_format_patch_email_headers = ''' + concat( + "From " ++ commit_id ++ " Mon Sep 17 00:00:00 2001\n", + "From: " ++ author ++ "\n", + "Date: " ++ author.timestamp().format("%a, %-e %b %Y %T %z") ++ "\n", + "Subject: [PATCH] " ++ description.first_line() ++ "\n", + "\n", + description.remove_prefix(description.first_line()).trim_start(), + "---\n", + indent(" ", diff.stat()), + "\n" + ) +''' diff --git a/cli/tests/test_commit_template.rs b/cli/tests/test_commit_template.rs index 5ced5630d..e433148ab 100644 --- a/cli/tests/test_commit_template.rs +++ b/cli/tests/test_commit_template.rs @@ -1609,3 +1609,49 @@ fn test_signature_templates() { [EOF] "); } + +#[test] +fn test_log_git_format_patch_template() { + let test_env = TestEnvironment::default(); + test_env.run_jj_in(".", ["git", "init", "repo"]).success(); + let work_dir = test_env.work_dir("repo"); + + work_dir.write_file("file1", "foo\n"); + work_dir.write_file("file2", "bar\n"); + work_dir + .run_jj([ + "new", + "-m", + "some change\n\nmultiline desc\nsecond line\n\nwith blanks\n", + ]) + .success(); + work_dir.remove_file("file1"); + work_dir.write_file("file2", "modified\n"); + work_dir.write_file("file3", "new\n"); + + let output = work_dir.run_jj([ + "log", + "--no-graph", + "-T", + "git_format_patch_email_headers", + "-r@", + ]); + insta::assert_snapshot!(output, @r" + From 993219c0b219b5eeac6303b5cb2bf943ea719672 Mon Sep 17 00:00:00 2001 + From: Test User + Date: Sat, 3 Feb 2001 04:05:08 +0700 + Subject: [PATCH] some change + + multiline desc + second line + + with blanks + --- + file1 | 1 - + file2 | 2 +- + file3 | 1 + + 3 files changed, 2 insertions(+), 2 deletions(-) + + [EOF] + "); +} diff --git a/cli/tests/test_completion.rs b/cli/tests/test_completion.rs index a1b800fb0..4fbad45ae 100644 --- a/cli/tests/test_completion.rs +++ b/cli/tests/test_completion.rs @@ -766,6 +766,7 @@ fn test_template_alias() { commit_summary_separator description_placeholder email_placeholder + git_format_patch_email_headers name_placeholder [EOF] "); diff --git a/cli/tests/test_evolog_command.rs b/cli/tests/test_evolog_command.rs index d390b554f..db5795ff6 100644 --- a/cli/tests/test_evolog_command.rs +++ b/cli/tests/test_evolog_command.rs @@ -361,6 +361,7 @@ fn test_evolog_with_no_template() { - commit_summary_separator - description_placeholder - email_placeholder + - git_format_patch_email_headers - name_placeholder [EOF] [exit status: 2] diff --git a/cli/tests/test_log_command.rs b/cli/tests/test_log_command.rs index 9677faac3..6fdb1e229 100644 --- a/cli/tests/test_log_command.rs +++ b/cli/tests/test_log_command.rs @@ -63,6 +63,7 @@ fn test_log_with_no_template() { - commit_summary_separator - description_placeholder - email_placeholder + - git_format_patch_email_headers - name_placeholder [EOF] [exit status: 2] diff --git a/cli/tests/test_operations.rs b/cli/tests/test_operations.rs index d5feec04a..4a65bda25 100644 --- a/cli/tests/test_operations.rs +++ b/cli/tests/test_operations.rs @@ -182,6 +182,7 @@ fn test_op_log_with_no_template() { - commit_summary_separator - description_placeholder - email_placeholder + - git_format_patch_email_headers - name_placeholder [EOF] [exit status: 2] diff --git a/cli/tests/test_show_command.rs b/cli/tests/test_show_command.rs index 1d6114dc3..e36f639c9 100644 --- a/cli/tests/test_show_command.rs +++ b/cli/tests/test_show_command.rs @@ -288,6 +288,7 @@ fn test_show_with_no_template() { - commit_summary_separator - description_placeholder - email_placeholder + - git_format_patch_email_headers - name_placeholder [EOF] [exit status: 2] diff --git a/demos/demo_git_compat.sh b/demos/demo_git_compat.sh index c4ac517b1..8d9e55bb1 100755 --- a/demos/demo_git_compat.sh +++ b/demos/demo_git_compat.sh @@ -29,6 +29,9 @@ run_command "jj diff -r b1" blank run_command "jj diff -r b3" +comment "We can generate a 'git format-patch' compatible diff" +run_command "jj show --git --template git_format_patch_email_headers" + comment "The repo is backed by the actual Git repo:" run_command "git --git-dir=.jj/repo/store/git log --graph --all --decorate --oneline"