2.36 format-patch regression fix

e900d494dc (diff: add an API for deferred freeing, 2021-02-11) added a way to allow reusing diffopts: the no_free bit. 244c27242f (diff.[ch]: have diff_free() call clear_pathspec(opts.pathspec), 2022-02-16) made that mechanism mandatory. git format-patch only sets no_free when --output is given, causing it to forget pathspecs after the first commit. Set no_free unconditionally instead. The existing test was unable to detect this breakage because it checks stderr for the absence of a certain string, but format-patch writes to stdout. Also the test was not checking the case of one commit modifying multiple files and a pathspec limiting the diff. Replace it with a more thorough one. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Apr 30, 2022 at 12:32 UTC 91f8f7e46fd86f2d20e93e00af451bf75febfe18
2 files changed +33 -9
builtin/log.c
+2 -7
@@ -1883,6 +1883,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
1883 rev.diff = 1;
1884 rev.max_parents = 1;
1885 rev.diffopt.flags.recursive = 1;
1886 + rev.diffopt.no_free = 1;
1887 rev.subject_prefix = fmt_patch_subject_prefix;
1888 memset(&s_r_opt, 0, sizeof(s_r_opt));
1889 s_r_opt.def = "HEAD";
@@ -2008,13 +2009,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
2009
2010 if (use_stdout) {
2011 setup_pager();
2011 - } else if (rev.diffopt.close_file) {
2012 - /*
2013 - * The diff code parsed --output; it has already opened the
2014 - * file, but we must instruct it not to close after each diff.
2015 - */
2016 - rev.diffopt.no_free = 1;
2017 - } else {
2012 + } else if (!rev.diffopt.close_file) {
2013 int saved;
2014
2015 if (!output_directory)
t/t4014-format-patch.sh
+31 -2
@@ -926,11 +926,40 @@ test_expect_success 'format-patch --numstat should produce a patch' '
926 '
927
928 test_expect_success 'format-patch -- <path>' '
929 - git format-patch main..side -- file 2>error &&
930 - ! grep "Use .--" error
929 + rm -f *.patch &&
930 + git checkout -b pathspec main &&
931 +
932 + echo file_a 1 >file_a &&
933 + echo file_b 1 >file_b &&
934 + git add file_a file_b &&
935 + git commit -m pathspec_initial &&
936 +
937 + echo file_a 2 >>file_a &&
938 + git add file_a &&
939 + git commit -m pathspec_a &&
940 +
941 + echo file_b 2 >>file_b &&
942 + git add file_b &&
943 + git commit -m pathspec_b &&
944 +
945 + echo file_a 3 >>file_a &&
946 + echo file_b 3 >>file_b &&
947 + git add file_a file_b &&
948 + git commit -m pathspec_ab &&
949 +
950 + cat >expect <<-\EOF &&
951 + 0001-pathspec_initial.patch
952 + 0002-pathspec_a.patch
953 + 0003-pathspec_ab.patch
954 + EOF
955 +
956 + git format-patch main..pathspec -- file_a >output &&
957 + test_cmp expect output &&
958 + ! grep file_b *.patch
959 '
960
961 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
962 + git checkout side &&
963 git format-patch --ignore-if-in-upstream HEAD
964 '
965