Skip to content

Commit ffcabcc

Browse files
committed
blame $path: avoid getting fooled by case insensitive filesystems
"git blame MAKEFILE" run in a history that has "Makefile" but not MAKEFILE can get confused on a case insensitive filesystem, because the check we run to see if there is a corresponding file in the working tree with lstat("MAKEFILE") succeeds. In addition to that check, we have to make sure that the given path also exists in the commit we start digging history from (i.e. "HEAD"). Note that this reveals the breakage in a test added in cd8ae20 (git-blame shouldn't crash if run in an unmerged tree, 2007-10-18), which expects the entire merge-in-progress path to be blamed to the working tree when it did not exist in our tree. As it is clear in the log message of that commit, the old breakage was that it was causing an internal error and the fix was about avoiding it. Just check that the command does not die an uncontrolled death. For this particular case, the blame should fail, as the history for the file in that contents has not been committed yet at the point in the test. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 785ee49 commit ffcabcc

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

builtin/blame.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,19 @@ static int git_blame_config(const char *var, const char *value, void *cb)
20442044
return git_default_config(var, value, cb);
20452045
}
20462046

2047+
static void verify_working_tree_path(unsigned char *head_sha1, const char *path)
2048+
{
2049+
unsigned char blob_sha1[20];
2050+
unsigned mode;
2051+
2052+
if (!resolve_ref_unsafe("HEAD", head_sha1, 1, NULL))
2053+
die("no such ref: HEAD");
2054+
if (get_tree_entry(head_sha1, path, blob_sha1, &mode))
2055+
die("no such path '%s' in HEAD", path);
2056+
if (sha1_object_info(blob_sha1, NULL) != OBJ_BLOB)
2057+
die("path '%s' in HEAD is not a blob", path);
2058+
}
2059+
20472060
/*
20482061
* Prepare a dummy commit that represents the work tree (or staged) item.
20492062
* Note that annotating work tree item never works in the reverse.
@@ -2062,8 +2075,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
20622075
struct cache_entry *ce;
20632076
unsigned mode;
20642077

2065-
if (get_sha1("HEAD", head_sha1))
2066-
die("No such ref: HEAD");
2078+
verify_working_tree_path(head_sha1, path);
20672079

20682080
time(&now);
20692081
commit = xcalloc(1, sizeof(*commit));

t/t8004-blame-with-conflicts.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ test_expect_success \
6666
git blame file2
6767
'
6868

69-
test_expect_success 'blame runs on conflicted file in stages 1,3' '
70-
git blame file1
69+
test_expect_success 'blame does not crash with conflicted file in stages 1,3' '
70+
test_must_fail git blame file1
7171
'
7272

7373
test_done

0 commit comments

Comments
 (0)