revert: plug memory leak in "cherry-pick root commit" codepath

The empty tree passed as common ancestor to merge_trees() when cherry-picking a parentless commit is allocated on the heap and never freed. Leaking such a small one-time allocation is not a very big problem, but now that "git cherry-pick" can cherry-pick multiple commits it can start to add up. Avoid the leak by storing the fake tree exactly once in the BSS section (i.e., use a static). While at it, let's add a test to make sure cherry-picking multiple parentless commits continues to work. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Nieder committed Aug 14, 2011 at 10:22 UTC 127f04522292fc62152762405c92d6acca4dbcb5
2 files changed +27 -7
builtin/revert.c
+1 -6
@@ -273,12 +273,7 @@ static void write_message(struct strbuf *msgbuf, const char *filename)
273
274 static struct tree *empty_tree(void)
275 {
276 - struct tree *tree = xcalloc(1, sizeof(struct tree));
277 -
278 - tree->object.parsed = 1;
279 - tree->object.type = OBJ_TREE;
280 - pretend_sha1_file(NULL, 0, OBJ_TREE, tree->object.sha1);
281 - return tree;
276 + return lookup_tree((const unsigned char *)EMPTY_TREE_SHA1_BIN);
277 }
278
279 static NORETURN void die_dirty_index(const char *me)
t/t3503-cherry-pick-root.sh
+26 -1
@@ -16,15 +16,40 @@ test_expect_success setup '
16 echo second > file2 &&
17 git add file2 &&
18 test_tick &&
19 - git commit -m "second"
19 + git commit -m "second" &&
20 +
21 + git symbolic-ref HEAD refs/heads/third &&
22 + rm .git/index file2 &&
23 + echo third > file3 &&
24 + git add file3 &&
25 + test_tick &&
26 + git commit -m "third"
27
28 '
29
30 test_expect_success 'cherry-pick a root commit' '
31
32 + git checkout second^0 &&
33 git cherry-pick master &&
34 test first = $(cat file1)
35
36 '
37
38 +test_expect_success 'cherry-pick two root commits' '
39 +
40 + echo first >expect.file1 &&
41 + echo second >expect.file2 &&
42 + echo third >expect.file3 &&
43 +
44 + git checkout second^0 &&
45 + git cherry-pick master third &&
46 +
47 + test_cmp expect.file1 file1 &&
48 + test_cmp expect.file2 file2 &&
49 + test_cmp expect.file3 file3 &&
50 + git rev-parse --verify HEAD^^ &&
51 + test_must_fail git rev-parse --verify HEAD^^^
52 +
53 +'
54 +
55 test_done