summaryrefslogtreecommitdiff
path: root/t/t5318-commit-graph.sh
diff options
context:
space:
mode:
Diffstat (limited to 't/t5318-commit-graph.sh')
-rwxr-xr-xt/t5318-commit-graph.sh325
1 files changed, 299 insertions, 26 deletions
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 3c1ffad491..2ed0c1544d 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -3,12 +3,23 @@
test_description='commit graph'
. ./test-lib.sh
+GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0
+
test_expect_success 'setup full repo' '
mkdir full &&
cd "$TRASH_DIRECTORY/full" &&
git init &&
git config core.commitGraph true &&
- objdir=".git/objects"
+ objdir=".git/objects" &&
+
+ test_oid_cache <<-EOF
+ oid_version sha1:1
+ oid_version sha256:2
+ EOF
+'
+
+test_expect_success POSIXPERM 'tweak umask for modebit tests' '
+ umask 022
'
test_expect_success 'verify graph with no graph file' '
@@ -18,8 +29,15 @@ test_expect_success 'verify graph with no graph file' '
test_expect_success 'write graph with no packs' '
cd "$TRASH_DIRECTORY/full" &&
- git commit-graph write --object-dir . &&
- test_path_is_file info/commit-graph
+ git commit-graph write --object-dir $objdir &&
+ test_path_is_missing $objdir/info/commit-graph
+'
+
+test_expect_success 'exit with correct error on bad input to --stdin-packs' '
+ cd "$TRASH_DIRECTORY/full" &&
+ echo doesnotexist >in &&
+ test_expect_code 1 git commit-graph write --stdin-packs <in 2>stderr &&
+ test_i18ngrep "error adding pack" stderr
'
test_expect_success 'create commits and repack' '
@@ -35,7 +53,7 @@ test_expect_success 'create commits and repack' '
graph_git_two_modes() {
git -c core.commitGraph=true $1 >output
git -c core.commitGraph=false $1 >expect
- test_cmp output expect
+ test_cmp expect output
}
graph_git_behavior() {
@@ -64,21 +82,44 @@ graph_read_expect() {
NUM_CHUNKS=$((3 + $(echo "$2" | wc -w)))
fi
cat >expect <<- EOF
- header: 43475048 1 1 $NUM_CHUNKS 0
+ header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
num_commits: $1
chunks: oid_fanout oid_lookup commit_metadata$OPTIONAL
EOF
- git commit-graph read >output &&
+ test-tool read-graph >output &&
test_cmp expect output
}
+test_expect_success 'exit with correct error on bad input to --stdin-commits' '
+ cd "$TRASH_DIRECTORY/full" &&
+ # invalid, non-hex OID
+ echo HEAD >in &&
+ test_expect_code 1 git commit-graph write --stdin-commits <in 2>stderr &&
+ test_i18ngrep "unexpected non-hex object ID: HEAD" stderr &&
+ # non-existent OID
+ echo $ZERO_OID >in &&
+ test_expect_code 1 git commit-graph write --stdin-commits <in 2>stderr &&
+ test_i18ngrep "invalid object" stderr &&
+ # valid commit and tree OID
+ git rev-parse HEAD HEAD^{tree} >in &&
+ git commit-graph write --stdin-commits <in &&
+ graph_read_expect 3
+'
+
test_expect_success 'write graph' '
cd "$TRASH_DIRECTORY/full" &&
- graph1=$(git commit-graph write) &&
+ git commit-graph write &&
test_path_is_file $objdir/info/commit-graph &&
graph_read_expect "3"
'
+test_expect_success POSIXPERM 'write graph has correct permissions' '
+ test_path_is_file $objdir/info/commit-graph &&
+ echo "-r--r--r--" >expect &&
+ test_modebits $objdir/info/commit-graph >actual &&
+ test_cmp expect actual
+'
+
graph_git_behavior 'graph exists' full commits/3 commits/1
test_expect_success 'Add more commits' '
@@ -107,6 +148,63 @@ test_expect_success 'Add more commits' '
git repack
'
+test_expect_success 'commit-graph write progress off for redirected stderr' '
+ cd "$TRASH_DIRECTORY/full" &&
+ git commit-graph write 2>err &&
+ test_must_be_empty err
+'
+
+test_expect_success 'commit-graph write force progress on for stderr' '
+ cd "$TRASH_DIRECTORY/full" &&
+ GIT_PROGRESS_DELAY=0 git commit-graph write --progress 2>err &&
+ test_file_not_empty err
+'
+
+test_expect_success 'commit-graph write with the --no-progress option' '
+ cd "$TRASH_DIRECTORY/full" &&
+ git commit-graph write --no-progress 2>err &&
+ test_must_be_empty err
+'
+
+test_expect_success 'commit-graph write --stdin-commits progress off for redirected stderr' '
+ cd "$TRASH_DIRECTORY/full" &&
+ git rev-parse commits/5 >in &&
+ git commit-graph write --stdin-commits <in 2>err &&
+ test_must_be_empty err
+'
+
+test_expect_success 'commit-graph write --stdin-commits force progress on for stderr' '
+ cd "$TRASH_DIRECTORY/full" &&
+ git rev-parse commits/5 >in &&
+ GIT_PROGRESS_DELAY=0 git commit-graph write --stdin-commits --progress <in 2>err &&
+ test_i18ngrep "Collecting commits from input" err
+'
+
+test_expect_success 'commit-graph write --stdin-commits with the --no-progress option' '
+ cd "$TRASH_DIRECTORY/full" &&
+ git rev-parse commits/5 >in &&
+ git commit-graph write --stdin-commits --no-progress <in 2>err &&
+ test_must_be_empty err
+'
+
+test_expect_success 'commit-graph verify progress off for redirected stderr' '
+ cd "$TRASH_DIRECTORY/full" &&
+ git commit-graph verify 2>err &&
+ test_must_be_empty err
+'
+
+test_expect_success 'commit-graph verify force progress on for stderr' '
+ cd "$TRASH_DIRECTORY/full" &&
+ GIT_PROGRESS_DELAY=0 git commit-graph verify --progress 2>err &&
+ test_file_not_empty err
+'
+
+test_expect_success 'commit-graph verify with the --no-progress option' '
+ cd "$TRASH_DIRECTORY/full" &&
+ git commit-graph verify --no-progress 2>err &&
+ test_must_be_empty err
+'
+
# Current graph structure:
#
# __M3___
@@ -121,7 +219,7 @@ test_expect_success 'write graph with merges' '
cd "$TRASH_DIRECTORY/full" &&
git commit-graph write &&
test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "10" "large_edges"
+ graph_read_expect "10" "extra_edges"
'
graph_git_behavior 'merge 1 vs 2' full merge/1 merge/2
@@ -134,7 +232,7 @@ test_expect_success 'Add one more commit' '
git branch commits/8 &&
ls $objdir/pack | grep idx >existing-idx &&
git repack &&
- ls $objdir/pack| grep idx | grep -v --file=existing-idx >new-idx
+ ls $objdir/pack| grep idx | grep -v -f existing-idx >new-idx
'
# Current graph structure:
@@ -156,7 +254,7 @@ test_expect_success 'write graph with new commit' '
cd "$TRASH_DIRECTORY/full" &&
git commit-graph write &&
test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "11" "large_edges"
+ graph_read_expect "11" "extra_edges"
'
graph_git_behavior 'full graph, commit 8 vs merge 1' full commits/8 merge/1
@@ -166,7 +264,7 @@ test_expect_success 'write graph with nothing new' '
cd "$TRASH_DIRECTORY/full" &&
git commit-graph write &&
test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "11" "large_edges"
+ graph_read_expect "11" "extra_edges"
'
graph_git_behavior 'cleared graph, commit 8 vs merge 1' full commits/8 merge/1
@@ -176,7 +274,7 @@ test_expect_success 'build graph from latest pack with closure' '
cd "$TRASH_DIRECTORY/full" &&
cat new-idx | git commit-graph write --stdin-packs &&
test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "9" "large_edges"
+ graph_read_expect "9" "extra_edges"
'
graph_git_behavior 'graph from pack, commit 8 vs merge 1' full commits/8 merge/1
@@ -199,7 +297,7 @@ test_expect_success 'build graph from commits with append' '
cd "$TRASH_DIRECTORY/full" &&
git rev-parse merge/3 | git commit-graph write --stdin-commits --append &&
test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "10" "large_edges"
+ graph_read_expect "10" "extra_edges"
'
graph_git_behavior 'append graph, commit 8 vs merge 1' full commits/8 merge/1
@@ -209,7 +307,7 @@ test_expect_success 'build graph using --reachable' '
cd "$TRASH_DIRECTORY/full" &&
git commit-graph write --reachable &&
test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "11" "large_edges"
+ graph_read_expect "11" "extra_edges"
'
graph_git_behavior 'append graph, commit 8 vs merge 1' full commits/8 merge/1
@@ -230,7 +328,7 @@ test_expect_success 'write graph in bare repo' '
cd "$TRASH_DIRECTORY/bare" &&
git commit-graph write &&
test_path_is_file $baredir/info/commit-graph &&
- graph_read_expect "11" "large_edges"
+ graph_read_expect "11" "extra_edges"
'
graph_git_behavior 'bare repo with graph, commit 8 vs merge 1' bare commits/8 merge/1
@@ -259,6 +357,95 @@ test_expect_success 'check that gc computes commit-graph' '
test_cmp_bin commit-graph-after-gc $objdir/info/commit-graph
'
+test_expect_success 'replace-objects invalidates commit-graph' '
+ cd "$TRASH_DIRECTORY" &&
+ test_when_finished rm -rf replace &&
+ git clone full replace &&
+ (
+ cd replace &&
+ git commit-graph write --reachable &&
+ test_path_is_file .git/objects/info/commit-graph &&
+ git replace HEAD~1 HEAD~2 &&
+ git -c core.commitGraph=false log >expect &&
+ git -c core.commitGraph=true log >actual &&
+ test_cmp expect actual &&
+ git commit-graph write --reachable &&
+ git -c core.commitGraph=false --no-replace-objects log >expect &&
+ git -c core.commitGraph=true --no-replace-objects log >actual &&
+ test_cmp expect actual &&
+ rm -rf .git/objects/info/commit-graph &&
+ git commit-graph write --reachable &&
+ test_path_is_file .git/objects/info/commit-graph
+ )
+'
+
+test_expect_success 'commit grafts invalidate commit-graph' '
+ cd "$TRASH_DIRECTORY" &&
+ test_when_finished rm -rf graft &&
+ git clone full graft &&
+ (
+ cd graft &&
+ git commit-graph write --reachable &&
+ test_path_is_file .git/objects/info/commit-graph &&
+ H1=$(git rev-parse --verify HEAD~1) &&
+ H3=$(git rev-parse --verify HEAD~3) &&
+ echo "$H1 $H3" >.git/info/grafts &&
+ git -c core.commitGraph=false log >expect &&
+ git -c core.commitGraph=true log >actual &&
+ test_cmp expect actual &&
+ git commit-graph write --reachable &&
+ git -c core.commitGraph=false --no-replace-objects log >expect &&
+ git -c core.commitGraph=true --no-replace-objects log >actual &&
+ test_cmp expect actual &&
+ rm -rf .git/objects/info/commit-graph &&
+ git commit-graph write --reachable &&
+ test_path_is_missing .git/objects/info/commit-graph
+ )
+'
+
+test_expect_success 'replace-objects invalidates commit-graph' '
+ cd "$TRASH_DIRECTORY" &&
+ test_when_finished rm -rf shallow &&
+ git clone --depth 2 "file://$TRASH_DIRECTORY/full" shallow &&
+ (
+ cd shallow &&
+ git commit-graph write --reachable &&
+ test_path_is_missing .git/objects/info/commit-graph &&
+ git fetch origin --unshallow &&
+ git commit-graph write --reachable &&
+ test_path_is_file .git/objects/info/commit-graph
+ )
+'
+
+test_expect_success 'warn on improper hash version' '
+ git init --object-format=sha1 sha1 &&
+ (
+ cd sha1 &&
+ test_commit 1 &&
+ git commit-graph write --reachable &&
+ mv .git/objects/info/commit-graph ../cg-sha1
+ ) &&
+ git init --object-format=sha256 sha256 &&
+ (
+ cd sha256 &&
+ test_commit 1 &&
+ git commit-graph write --reachable &&
+ mv .git/objects/info/commit-graph ../cg-sha256
+ ) &&
+ (
+ cd sha1 &&
+ mv ../cg-sha256 .git/objects/info/commit-graph &&
+ git log -1 2>err &&
+ test_i18ngrep "commit-graph hash version 2 does not match version 1" err
+ ) &&
+ (
+ cd sha256 &&
+ mv ../cg-sha1 .git/objects/info/commit-graph &&
+ git log -1 2>err &&
+ test_i18ngrep "commit-graph hash version 1 does not match version 2" err
+ )
+'
+
# the verify tests below expect the commit-graph to contain
# exactly the commits reachable from the commits/8 branch.
# If the file changes the set of commits in the list, then the
@@ -273,7 +460,7 @@ test_expect_success 'git commit-graph verify' '
NUM_COMMITS=9
NUM_OCTOPUS_EDGES=2
-HASH_LEN=20
+HASH_LEN="$(test_oid rawsz)"
GRAPH_BYTE_VERSION=4
GRAPH_BYTE_HASH=5
GRAPH_BYTE_CHUNK_COUNT=6
@@ -305,24 +492,60 @@ GRAPH_OCTOPUS_DATA_OFFSET=$(($GRAPH_COMMIT_DATA_OFFSET + \
GRAPH_BYTE_OCTOPUS=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4))
GRAPH_BYTE_FOOTER=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4 * $NUM_OCTOPUS_EDGES))
-# usage: corrupt_graph_and_verify <position> <data> <string>
+corrupt_graph_setup() {
+ cd "$TRASH_DIRECTORY/full" &&
+ test_when_finished mv commit-graph-backup $objdir/info/commit-graph &&
+ cp $objdir/info/commit-graph commit-graph-backup &&
+ chmod u+w $objdir/info/commit-graph
+}
+
+corrupt_graph_verify() {
+ grepstr=$1
+ test_must_fail git commit-graph verify 2>test_err &&
+ grep -v "^+" test_err >err &&
+ test_i18ngrep "$grepstr" err &&
+ if test "$2" != "no-copy"
+ then
+ cp $objdir/info/commit-graph commit-graph-pre-write-test
+ fi &&
+ git status --short &&
+ GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE=true git commit-graph write &&
+ chmod u+w $objdir/info/commit-graph &&
+ git commit-graph verify
+}
+
+# usage: corrupt_graph_and_verify <position> <data> <string> [<zero_pos>]
# Manipulates the commit-graph file at the position
-# by inserting the data, then runs 'git commit-graph verify'
+# by inserting the data, optionally zeroing the file
+# starting at <zero_pos>, then runs 'git commit-graph verify'
# and places the output in the file 'err'. Test 'err' for
# the given string.
corrupt_graph_and_verify() {
pos=$1
data="${2:-\0}"
grepstr=$3
- cd "$TRASH_DIRECTORY/full" &&
- test_when_finished mv commit-graph-backup $objdir/info/commit-graph &&
- cp $objdir/info/commit-graph commit-graph-backup &&
+ corrupt_graph_setup &&
+ orig_size=$(wc -c < $objdir/info/commit-graph) &&
+ zero_pos=${4:-${orig_size}} &&
printf "$data" | dd of="$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc &&
- test_must_fail git commit-graph verify 2>test_err &&
- grep -v "^+" test_err >err
- test_i18ngrep "$grepstr" err
+ dd of="$objdir/info/commit-graph" bs=1 seek="$zero_pos" if=/dev/null &&
+ generate_zero_bytes $(($orig_size - $zero_pos)) >>"$objdir/info/commit-graph" &&
+ corrupt_graph_verify "$grepstr"
+
}
+test_expect_success POSIXPERM,SANITY 'detect permission problem' '
+ corrupt_graph_setup &&
+ chmod 000 $objdir/info/commit-graph &&
+ corrupt_graph_verify "Could not open" "no-copy"
+'
+
+test_expect_success 'detect too small' '
+ corrupt_graph_setup &&
+ echo "a small graph" >$objdir/info/commit-graph &&
+ corrupt_graph_verify "too small"
+'
+
test_expect_success 'detect bad signature' '
corrupt_graph_and_verify 0 "\0" \
"graph signature"
@@ -334,12 +557,12 @@ test_expect_success 'detect bad version' '
'
test_expect_success 'detect bad hash version' '
- corrupt_graph_and_verify $GRAPH_BYTE_HASH "\02" \
+ corrupt_graph_and_verify $GRAPH_BYTE_HASH "\03" \
"hash version"
'
test_expect_success 'detect low chunk count' '
- corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\02" \
+ corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\01" \
"missing the .* chunk"
'
@@ -423,11 +646,18 @@ test_expect_success 'detect invalid checksum hash' '
"incorrect checksum"
'
+test_expect_success 'detect incorrect chunk count' '
+ corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\377" \
+ "commit-graph file is too small to hold [0-9]* chunks" \
+ $GRAPH_CHUNK_LOOKUP_OFFSET
+'
+
test_expect_success 'git fsck (checks commit-graph)' '
cd "$TRASH_DIRECTORY/full" &&
git fsck &&
corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
"incorrect checksum" &&
+ cp commit-graph-pre-write-test $objdir/info/commit-graph &&
test_must_fail git fsck
'
@@ -468,4 +698,47 @@ test_expect_success 'get_commit_tree_in_graph works for non-the_repository' '
test_cmp expect actual
'
+test_expect_success 'corrupt commit-graph write (broken parent)' '
+ rm -rf repo &&
+ git init repo &&
+ (
+ cd repo &&
+ empty="$(git mktree </dev/null)" &&
+ cat >broken <<-EOF &&
+ tree $empty
+ parent $ZERO_OID
+ author whatever <whatever@example.com> 1234 -0000
+ committer whatever <whatever@example.com> 1234 -0000
+
+ broken commit
+ EOF
+ broken="$(git hash-object -w -t commit --literally broken)" &&
+ git commit-tree -p "$broken" -m "good commit" "$empty" >good &&
+ test_must_fail git commit-graph write --stdin-commits \
+ <good 2>test_err &&
+ test_i18ngrep "unable to parse commit" test_err
+ )
+'
+
+test_expect_success 'corrupt commit-graph write (missing tree)' '
+ rm -rf repo &&
+ git init repo &&
+ (
+ cd repo &&
+ tree="$(git mktree </dev/null)" &&
+ cat >broken <<-EOF &&
+ parent $ZERO_OID
+ author whatever <whatever@example.com> 1234 -0000
+ committer whatever <whatever@example.com> 1234 -0000
+
+ broken commit
+ EOF
+ broken="$(git hash-object -w -t commit --literally broken)" &&
+ git commit-tree -p "$broken" -m "good" "$tree" >good &&
+ test_must_fail git commit-graph write --stdin-commits \
+ <good 2>test_err &&
+ test_i18ngrep "unable to parse commit" test_err
+ )
+'
+
test_done