Skip to content

Commit a77554e

Browse files
blanetgitster
authored andcommitted
diff-tree: fix crash when used with --remerge-diff
When using "git-diff-tree" to get the tree diff for merge commits with the diff format set to `remerge`, a bug is triggered as shown below: $ git diff-tree -r --remerge-diff 363337e 363337e BUG: log-tree.c:1006: did a remerge diff without remerge_objdir?!? This bug is reported by `log-tree.c:do_remerge_diff`, where a bug check added in commit 7b90ab4 (log: clean unneeded objects during log --remerge-diff, 2022-02-02) detects the absence of `remerge_objdir` when attempting to clean up temporary objects generated during the remerge process. After some further digging, I find that the remerge-related diff options were introduced in db757e8 (show, log: provide a --remerge-diff capability, 2022-02-02), which also affect the setup of `rev_info` for "git-diff-tree", but were not accounted for in the original implementation (inferred from the commit message). Elijah Newren, the author of the remerge diff feature, notes that other callers of `log-tree.c:log_tree_commit` (the only caller of `log-tree.c:do_remerge_diff`) also exist, but: `builtin/am.c`: manually sets all flags; remerge_diff is not among them `sequencer.c`: manually sets all flags; remerge_diff is not among them so `builtin/diff-tree.c` really is the only caller that was overlooked when remerge-diff functionality was added. This commit resolves the crash by adding `remerge_objdir` setup logic to `builtin/diff-tree.c`, mirroring `builtin/log.c:cmd_log_walk_no_free`. It also includes the necessary cleanup for `remerge_objdir`. Reviewed-by: Elijah Newren <[email protected]> Signed-off-by: Xing Xin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 337b4d4 commit a77554e

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

builtin/diff-tree.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "read-cache-ll.h"
1010
#include "repository.h"
1111
#include "revision.h"
12+
#include "tmp-objdir.h"
1213
#include "tree.h"
1314

1415
static struct rev_info log_tree_opt;
@@ -167,6 +168,13 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
167168

168169
opt->diffopt.rotate_to_strict = 1;
169170

171+
if (opt->remerge_diff) {
172+
opt->remerge_objdir = tmp_objdir_create("remerge-diff");
173+
if (!opt->remerge_objdir)
174+
die(_("unable to create temporary object directory"));
175+
tmp_objdir_replace_primary_odb(opt->remerge_objdir, 1);
176+
}
177+
170178
/*
171179
* NOTE! We expect "a..b" to expand to "^a b" but it is
172180
* perfectly valid for revision range parser to yield "b ^a",
@@ -231,5 +239,10 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
231239
diff_free(&opt->diffopt);
232240
}
233241

242+
if (opt->remerge_diff) {
243+
tmp_objdir_destroy(opt->remerge_objdir);
244+
opt->remerge_objdir = NULL;
245+
}
246+
234247
return diff_result_code(&opt->diffopt);
235248
}

t/t4069-remerge-diff.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,41 @@ test_expect_success 'can filter out additional headers with pickaxe' '
110110
test_must_be_empty actual
111111
'
112112

113+
test_expect_success 'remerge-diff also works for git-diff-tree' '
114+
# With a clean merge
115+
git diff-tree -r -p --remerge-diff --no-commit-id bc_resolution >actual &&
116+
test_must_be_empty actual &&
117+
118+
# With both a resolved conflict and an unrelated change
119+
cat <<-EOF >tmp &&
120+
diff --git a/numbers b/numbers
121+
remerge CONFLICT (content): Merge conflict in numbers
122+
index a1fb731..6875544 100644
123+
--- a/numbers
124+
+++ b/numbers
125+
@@ -1,13 +1,9 @@
126+
1
127+
2
128+
-<<<<<<< b0ed5cb (change_a)
129+
-three
130+
-=======
131+
-tres
132+
->>>>>>> 6cd3f82 (change_b)
133+
+drei
134+
4
135+
5
136+
6
137+
7
138+
-eight
139+
+acht
140+
9
141+
EOF
142+
sed -e "s/[0-9a-f]\{7,\}/HASH/g" tmp >expect &&
143+
git diff-tree -r -p --remerge-diff --no-commit-id ab_resolution >tmp &&
144+
sed -e "s/[0-9a-f]\{7,\}/HASH/g" tmp >actual &&
145+
test_cmp expect actual
146+
'
147+
113148
test_expect_success 'setup non-content conflicts' '
114149
git switch --orphan base &&
115150

0 commit comments

Comments
 (0)