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