Skip to content

Commit cd8ae20

Browse files
torvaldsspearce
authored andcommitted
git-blame shouldn't crash if run in an unmerged tree
If we are in the middle of resolving a merge conflict there may be one or more files whose entries in the index represent an unmerged state (index entries in the higher-order stages). Attempting to run git-blame on any file in such a working directory resulted in "fatal: internal error: ce_mode is 0" as we use the magic marker for an unmerged entry is 0 (set up by things like diff-lib.c's do_diff_cache() and builtin-read-tree.c's read_tree_unmerged()) and the ce_match_stat_basic() function gets upset about this. I'm not entirely sure that the whole "ce_mode = 0" case is a good idea to begin with, and maybe the right thing to do is to remove that horrid freakish special case, but removing the internal error seems to be the simplest fix for now. Linus [sp: Thanks to Björn Steinbrink for the test case] Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
1 parent 93a56c2 commit cd8ae20

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

read-cache.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
149149
else if (ce_compare_gitlink(ce))
150150
changed |= DATA_CHANGED;
151151
return changed;
152+
case 0: /* Special case: unmerged file in index */
153+
return MODE_CHANGED | DATA_CHANGED | TYPE_CHANGED;
152154
default:
153155
die("internal error: ce_mode is %o", ntohl(ce->ce_mode));
154156
}

t/t8004-blame.sh

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/bin/sh
2+
3+
# Based on a test case submitted by Björn Steinbrink.
4+
5+
test_description='git blame on conflicted files'
6+
. ./test-lib.sh
7+
8+
test_expect_success 'setup first case' '
9+
# Create the old file
10+
echo "Old line" > file1 &&
11+
git add file1 &&
12+
git commit --author "Old Line <ol@localhost>" -m file1.a &&
13+
14+
# Branch
15+
git checkout -b foo &&
16+
17+
# Do an ugly move and change
18+
git rm file1 &&
19+
echo "New line ..." > file2 &&
20+
echo "... and more" >> file2 &&
21+
git add file2 &&
22+
git commit --author "U Gly <ug@localhost>" -m ugly &&
23+
24+
# Back to master and change something
25+
git checkout master &&
26+
echo "
27+
28+
bla" >> file1 &&
29+
git commit --author "Old Line <ol@localhost>" -a -m file1.b &&
30+
31+
# Back to foo and merge master
32+
git checkout foo &&
33+
if git merge master; then
34+
echo needed conflict here
35+
exit 1
36+
else
37+
echo merge failed - resolving automatically
38+
fi &&
39+
echo "New line ...
40+
... and more
41+
42+
bla
43+
Even more" > file2 &&
44+
git rm file1 &&
45+
git commit --author "M Result <mr@localhost>" -a -m merged &&
46+
47+
# Back to master and change file1 again
48+
git checkout master &&
49+
sed s/bla/foo/ <file1 >X &&
50+
rm file1 &&
51+
mv X file1 &&
52+
git commit --author "No Bla <nb@localhost>" -a -m replace &&
53+
54+
# Try to merge into foo again
55+
git checkout foo &&
56+
if git merge master; then
57+
echo needed conflict here
58+
exit 1
59+
else
60+
echo merge failed - test is setup
61+
fi
62+
'
63+
64+
test_expect_success \
65+
'blame runs on unconflicted file while other file has conflicts' '
66+
git blame file2
67+
'
68+
69+
test_expect_success 'blame runs on conflicted file in stages 1,3' '
70+
git blame file1
71+
'
72+
73+
test_done

0 commit comments

Comments
 (0)