Skip to content

Commit 541dc4d

Browse files
committed
Merge branch 'jk/write-broken-index-with-nul-sha1'
Earlier we started rejecting an attempt to add 0{40} object name to the index and to tree objects, but it sometimes is necessary to allow so to be able to use tools like filter-branch to correct such broken tree objects. * jk/write-broken-index-with-nul-sha1: write_index: optionally allow broken null sha1s
2 parents 9b4aa47 + 83bd743 commit 541dc4d

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

git-filter-branch.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,12 @@ while read commit parents; do
283283

284284
case "$filter_subdir" in
285285
"")
286-
git read-tree -i -m $commit
286+
GIT_ALLOW_NULL_SHA1=1 git read-tree -i -m $commit
287287
;;
288288
*)
289289
# The commit may not have the subdirectory at all
290-
err=$(git read-tree -i -m $commit:"$filter_subdir" 2>&1) || {
290+
err=$(GIT_ALLOW_NULL_SHA1=1 \
291+
git read-tree -i -m $commit:"$filter_subdir" 2>&1) || {
291292
if ! git rev-parse -q --verify $commit:"$filter_subdir"
292293
then
293294
rm -f "$GIT_INDEX_FILE"

read-cache.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,8 +1818,17 @@ int write_index(struct index_state *istate, int newfd)
18181818
continue;
18191819
if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
18201820
ce_smudge_racily_clean_entry(ce);
1821-
if (is_null_sha1(ce->sha1))
1822-
return error("cache entry has null sha1: %s", ce->name);
1821+
if (is_null_sha1(ce->sha1)) {
1822+
static const char msg[] = "cache entry has null sha1: %s";
1823+
static int allow = -1;
1824+
1825+
if (allow < 0)
1826+
allow = git_env_bool("GIT_ALLOW_NULL_SHA1", 0);
1827+
if (allow)
1828+
warning(msg, ce->name);
1829+
else
1830+
return error(msg, ce->name);
1831+
}
18231832
if (ce_write_entry(&c, newfd, ce, previous_name) < 0)
18241833
return -1;
18251834
}

t/t7009-filter-branch-null-sha1.sh

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/sh
2+
3+
test_description='filter-branch removal of trees with null sha1'
4+
. ./test-lib.sh
5+
6+
test_expect_success 'setup: base commits' '
7+
test_commit one &&
8+
test_commit two &&
9+
test_commit three
10+
'
11+
12+
test_expect_success 'setup: a commit with a bogus null sha1 in the tree' '
13+
{
14+
git ls-tree HEAD &&
15+
printf "160000 commit $_z40\\tbroken\\n"
16+
} >broken-tree
17+
echo "add broken entry" >msg &&
18+
19+
tree=$(git mktree <broken-tree) &&
20+
test_tick &&
21+
commit=$(git commit-tree $tree -p HEAD <msg) &&
22+
git update-ref HEAD "$commit"
23+
'
24+
25+
# we have to make one more commit on top removing the broken
26+
# entry, since otherwise our index does not match HEAD (and filter-branch will
27+
# complain). We could make the index match HEAD, but doing so would involve
28+
# writing a null sha1 into the index.
29+
test_expect_success 'setup: bring HEAD and index in sync' '
30+
test_tick &&
31+
git commit -a -m "back to normal"
32+
'
33+
34+
test_expect_success 'filter commands are still checked' '
35+
test_must_fail git filter-branch \
36+
--force --prune-empty \
37+
--index-filter "git rm --cached --ignore-unmatch three.t"
38+
'
39+
40+
test_expect_success 'removing the broken entry works' '
41+
echo three >expect &&
42+
git filter-branch \
43+
--force --prune-empty \
44+
--index-filter "git rm --cached --ignore-unmatch broken" &&
45+
git log -1 --format=%s >actual &&
46+
test_cmp expect actual
47+
'
48+
49+
test_done

0 commit comments

Comments
 (0)