t / t5324-split-commit-graph.shon commit Merge branch 'dl/use-sq-from-test-lib' (d693345)
   1#!/bin/sh
   2
   3test_description='split commit graph'
   4. ./test-lib.sh
   5
   6GIT_TEST_COMMIT_GRAPH=0
   7
   8test_expect_success 'setup repo' '
   9        git init &&
  10        git config core.commitGraph true &&
  11        git config gc.writeCommitGraph false &&
  12        infodir=".git/objects/info" &&
  13        graphdir="$infodir/commit-graphs" &&
  14        test_oid_init
  15'
  16
  17graph_read_expect() {
  18        NUM_BASE=0
  19        if test ! -z $2
  20        then
  21                NUM_BASE=$2
  22        fi
  23        cat >expect <<- EOF
  24        header: 43475048 1 1 3 $NUM_BASE
  25        num_commits: $1
  26        chunks: oid_fanout oid_lookup commit_metadata
  27        EOF
  28        git commit-graph read >output &&
  29        test_cmp expect output
  30}
  31
  32test_expect_success 'create commits and write commit-graph' '
  33        for i in $(test_seq 3)
  34        do
  35                test_commit $i &&
  36                git branch commits/$i || return 1
  37        done &&
  38        git commit-graph write --reachable &&
  39        test_path_is_file $infodir/commit-graph &&
  40        graph_read_expect 3
  41'
  42
  43graph_git_two_modes() {
  44        git -c core.commitGraph=true $1 >output
  45        git -c core.commitGraph=false $1 >expect
  46        test_cmp expect output
  47}
  48
  49graph_git_behavior() {
  50        MSG=$1
  51        BRANCH=$2
  52        COMPARE=$3
  53        test_expect_success "check normal git operations: $MSG" '
  54                graph_git_two_modes "log --oneline $BRANCH" &&
  55                graph_git_two_modes "log --topo-order $BRANCH" &&
  56                graph_git_two_modes "log --graph $COMPARE..$BRANCH" &&
  57                graph_git_two_modes "branch -vv" &&
  58                graph_git_two_modes "merge-base -a $BRANCH $COMPARE"
  59        '
  60}
  61
  62graph_git_behavior 'graph exists' commits/3 commits/1
  63
  64verify_chain_files_exist() {
  65        for hash in $(cat $1/commit-graph-chain)
  66        do
  67                test_path_is_file $1/graph-$hash.graph || return 1
  68        done
  69}
  70
  71test_expect_success 'add more commits, and write a new base graph' '
  72        git reset --hard commits/1 &&
  73        for i in $(test_seq 4 5)
  74        do
  75                test_commit $i &&
  76                git branch commits/$i || return 1
  77        done &&
  78        git reset --hard commits/2 &&
  79        for i in $(test_seq 6 10)
  80        do
  81                test_commit $i &&
  82                git branch commits/$i || return 1
  83        done &&
  84        git reset --hard commits/2 &&
  85        git merge commits/4 &&
  86        git branch merge/1 &&
  87        git reset --hard commits/4 &&
  88        git merge commits/6 &&
  89        git branch merge/2 &&
  90        git commit-graph write --reachable &&
  91        graph_read_expect 12
  92'
  93
  94test_expect_success 'fork and fail to base a chain on a commit-graph file' '
  95        test_when_finished rm -rf fork &&
  96        git clone . fork &&
  97        (
  98                cd fork &&
  99                rm .git/objects/info/commit-graph &&
 100                echo "$(pwd)/../.git/objects" >.git/objects/info/alternates &&
 101                test_commit new-commit &&
 102                git commit-graph write --reachable --split &&
 103                test_path_is_file $graphdir/commit-graph-chain &&
 104                test_line_count = 1 $graphdir/commit-graph-chain &&
 105                verify_chain_files_exist $graphdir
 106        )
 107'
 108
 109test_expect_success 'add three more commits, write a tip graph' '
 110        git reset --hard commits/3 &&
 111        git merge merge/1 &&
 112        git merge commits/5 &&
 113        git merge merge/2 &&
 114        git branch merge/3 &&
 115        git commit-graph write --reachable --split &&
 116        test_path_is_missing $infodir/commit-graph &&
 117        test_path_is_file $graphdir/commit-graph-chain &&
 118        ls $graphdir/graph-*.graph >graph-files &&
 119        test_line_count = 2 graph-files &&
 120        verify_chain_files_exist $graphdir
 121'
 122
 123graph_git_behavior 'split commit-graph: merge 3 vs 2' merge/3 merge/2
 124
 125test_expect_success 'add one commit, write a tip graph' '
 126        test_commit 11 &&
 127        git branch commits/11 &&
 128        git commit-graph write --reachable --split &&
 129        test_path_is_missing $infodir/commit-graph &&
 130        test_path_is_file $graphdir/commit-graph-chain &&
 131        ls $graphdir/graph-*.graph >graph-files &&
 132        test_line_count = 3 graph-files &&
 133        verify_chain_files_exist $graphdir
 134'
 135
 136graph_git_behavior 'three-layer commit-graph: commit 11 vs 6' commits/11 commits/6
 137
 138test_expect_success 'add one commit, write a merged graph' '
 139        test_commit 12 &&
 140        git branch commits/12 &&
 141        git commit-graph write --reachable --split &&
 142        test_path_is_file $graphdir/commit-graph-chain &&
 143        test_line_count = 2 $graphdir/commit-graph-chain &&
 144        ls $graphdir/graph-*.graph >graph-files &&
 145        test_line_count = 2 graph-files &&
 146        verify_chain_files_exist $graphdir
 147'
 148
 149graph_git_behavior 'merged commit-graph: commit 12 vs 6' commits/12 commits/6
 150
 151test_expect_success 'create fork and chain across alternate' '
 152        git clone . fork &&
 153        (
 154                cd fork &&
 155                git config core.commitGraph true &&
 156                rm -rf $graphdir &&
 157                echo "$(pwd)/../.git/objects" >.git/objects/info/alternates &&
 158                test_commit 13 &&
 159                git branch commits/13 &&
 160                git commit-graph write --reachable --split &&
 161                test_path_is_file $graphdir/commit-graph-chain &&
 162                test_line_count = 3 $graphdir/commit-graph-chain &&
 163                ls $graphdir/graph-*.graph >graph-files &&
 164                test_line_count = 1 graph-files &&
 165                git -c core.commitGraph=true  rev-list HEAD >expect &&
 166                git -c core.commitGraph=false rev-list HEAD >actual &&
 167                test_cmp expect actual &&
 168                test_commit 14 &&
 169                git commit-graph write --reachable --split --object-dir=.git/objects/ &&
 170                test_line_count = 3 $graphdir/commit-graph-chain &&
 171                ls $graphdir/graph-*.graph >graph-files &&
 172                test_line_count = 1 graph-files
 173        )
 174'
 175
 176graph_git_behavior 'alternate: commit 13 vs 6' commits/13 commits/6
 177
 178test_expect_success 'test merge stragety constants' '
 179        git clone . merge-2 &&
 180        (
 181                cd merge-2 &&
 182                git config core.commitGraph true &&
 183                test_line_count = 2 $graphdir/commit-graph-chain &&
 184                test_commit 14 &&
 185                git commit-graph write --reachable --split --size-multiple=2 &&
 186                test_line_count = 3 $graphdir/commit-graph-chain
 187
 188        ) &&
 189        git clone . merge-10 &&
 190        (
 191                cd merge-10 &&
 192                git config core.commitGraph true &&
 193                test_line_count = 2 $graphdir/commit-graph-chain &&
 194                test_commit 14 &&
 195                git commit-graph write --reachable --split --size-multiple=10 &&
 196                test_line_count = 1 $graphdir/commit-graph-chain &&
 197                ls $graphdir/graph-*.graph >graph-files &&
 198                test_line_count = 1 graph-files
 199        ) &&
 200        git clone . merge-10-expire &&
 201        (
 202                cd merge-10-expire &&
 203                git config core.commitGraph true &&
 204                test_line_count = 2 $graphdir/commit-graph-chain &&
 205                test_commit 15 &&
 206                git commit-graph write --reachable --split --size-multiple=10 --expire-time=1980-01-01 &&
 207                test_line_count = 1 $graphdir/commit-graph-chain &&
 208                ls $graphdir/graph-*.graph >graph-files &&
 209                test_line_count = 3 graph-files
 210        ) &&
 211        git clone --no-hardlinks . max-commits &&
 212        (
 213                cd max-commits &&
 214                git config core.commitGraph true &&
 215                test_line_count = 2 $graphdir/commit-graph-chain &&
 216                test_commit 16 &&
 217                test_commit 17 &&
 218                git commit-graph write --reachable --split --max-commits=1 &&
 219                test_line_count = 1 $graphdir/commit-graph-chain &&
 220                ls $graphdir/graph-*.graph >graph-files &&
 221                test_line_count = 1 graph-files
 222        )
 223'
 224
 225test_expect_success 'remove commit-graph-chain file after flattening' '
 226        git clone . flatten &&
 227        (
 228                cd flatten &&
 229                test_line_count = 2 $graphdir/commit-graph-chain &&
 230                git commit-graph write --reachable &&
 231                test_path_is_missing $graphdir/commit-graph-chain &&
 232                ls $graphdir >graph-files &&
 233                test_line_count = 0 graph-files
 234        )
 235'
 236
 237corrupt_file() {
 238        file=$1
 239        pos=$2
 240        data="${3:-\0}"
 241        chmod a+w "$file" &&
 242        printf "$data" | dd of="$file" bs=1 seek="$pos" conv=notrunc
 243}
 244
 245test_expect_success 'verify hashes along chain, even in shallow' '
 246        git clone --no-hardlinks . verify &&
 247        (
 248                cd verify &&
 249                git commit-graph verify &&
 250                base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph &&
 251                corrupt_file "$base_file" 1760 "\01" &&
 252                test_must_fail git commit-graph verify --shallow 2>test_err &&
 253                grep -v "^+" test_err >err &&
 254                test_i18ngrep "incorrect checksum" err
 255        )
 256'
 257
 258test_expect_success 'verify --shallow does not check base contents' '
 259        git clone --no-hardlinks . verify-shallow &&
 260        (
 261                cd verify-shallow &&
 262                git commit-graph verify &&
 263                base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph &&
 264                corrupt_file "$base_file" 1000 "\01" &&
 265                git commit-graph verify --shallow &&
 266                test_must_fail git commit-graph verify 2>test_err &&
 267                grep -v "^+" test_err >err &&
 268                test_i18ngrep "incorrect checksum" err
 269        )
 270'
 271
 272test_expect_success 'warn on base graph chunk incorrect' '
 273        git clone --no-hardlinks . base-chunk &&
 274        (
 275                cd base-chunk &&
 276                git commit-graph verify &&
 277                base_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph &&
 278                corrupt_file "$base_file" 1376 "\01" &&
 279                git commit-graph verify --shallow 2>test_err &&
 280                grep -v "^+" test_err >err &&
 281                test_i18ngrep "commit-graph chain does not match" err
 282        )
 283'
 284
 285test_expect_success 'verify after commit-graph-chain corruption' '
 286        git clone --no-hardlinks . verify-chain &&
 287        (
 288                cd verify-chain &&
 289                corrupt_file "$graphdir/commit-graph-chain" 60 "G" &&
 290                git commit-graph verify 2>test_err &&
 291                grep -v "^+" test_err >err &&
 292                test_i18ngrep "invalid commit-graph chain" err &&
 293                corrupt_file "$graphdir/commit-graph-chain" 60 "A" &&
 294                git commit-graph verify 2>test_err &&
 295                grep -v "^+" test_err >err &&
 296                test_i18ngrep "unable to find all commit-graph files" err
 297        )
 298'
 299
 300test_expect_success 'verify across alternates' '
 301        git clone --no-hardlinks . verify-alt &&
 302        (
 303                cd verify-alt &&
 304                rm -rf $graphdir &&
 305                altdir="$(pwd)/../.git/objects" &&
 306                echo "$altdir" >.git/objects/info/alternates &&
 307                git commit-graph verify --object-dir="$altdir/" &&
 308                test_commit extra &&
 309                git commit-graph write --reachable --split &&
 310                tip_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph &&
 311                corrupt_file "$tip_file" 100 "\01" &&
 312                test_must_fail git commit-graph verify --shallow 2>test_err &&
 313                grep -v "^+" test_err >err &&
 314                test_i18ngrep "commit-graph has incorrect fanout value" err
 315        )
 316'
 317
 318test_expect_success 'add octopus merge' '
 319        git reset --hard commits/10 &&
 320        git merge commits/3 commits/4 &&
 321        git branch merge/octopus &&
 322        git commit-graph write --reachable --split &&
 323        git commit-graph verify 2>err &&
 324        test_line_count = 3 err &&
 325        test_i18ngrep ! warning err &&
 326        test_line_count = 3 $graphdir/commit-graph-chain
 327'
 328
 329graph_git_behavior 'graph exists' merge/octopus commits/12
 330
 331test_expect_success 'split across alternate where alternate is not split' '
 332        git commit-graph write --reachable &&
 333        test_path_is_file .git/objects/info/commit-graph &&
 334        cp .git/objects/info/commit-graph . &&
 335        git clone --no-hardlinks . alt-split &&
 336        (
 337                cd alt-split &&
 338                rm -f .git/objects/info/commit-graph &&
 339                echo "$(pwd)"/../.git/objects >.git/objects/info/alternates &&
 340                test_commit 18 &&
 341                git commit-graph write --reachable --split &&
 342                test_line_count = 1 $graphdir/commit-graph-chain
 343        ) &&
 344        test_cmp commit-graph .git/objects/info/commit-graph
 345'
 346
 347test_done