|
| 1 | +#!/bin/sh |
| 2 | + |
| 3 | +test_description='parallel-checkout basics |
| 4 | +
|
| 5 | +Ensure that parallel-checkout basically works on clone and checkout, spawning |
| 6 | +the required number of workers and correctly populating both the index and the |
| 7 | +working tree. |
| 8 | +' |
| 9 | + |
| 10 | +TEST_NO_CREATE_REPO=1 |
| 11 | +. ./test-lib.sh |
| 12 | +. "$TEST_DIRECTORY/lib-parallel-checkout.sh" |
| 13 | + |
| 14 | +# Test parallel-checkout with a branch switch containing a variety of file |
| 15 | +# creations, deletions, and modifications, involving different entry types. |
| 16 | +# The branches B1 and B2 have the following paths: |
| 17 | +# |
| 18 | +# B1 B2 |
| 19 | +# a/a (file) a (file) |
| 20 | +# b (file) b/b (file) |
| 21 | +# |
| 22 | +# c/c (file) c (symlink) |
| 23 | +# d (symlink) d/d (file) |
| 24 | +# |
| 25 | +# e/e (file) e (submodule) |
| 26 | +# f (submodule) f/f (file) |
| 27 | +# |
| 28 | +# g (submodule) g (symlink) |
| 29 | +# h (symlink) h (submodule) |
| 30 | +# |
| 31 | +# Additionally, the following paths are present on both branches, but with |
| 32 | +# different contents: |
| 33 | +# |
| 34 | +# i (file) i (file) |
| 35 | +# j (symlink) j (symlink) |
| 36 | +# k (submodule) k (submodule) |
| 37 | +# |
| 38 | +# And the following paths are only present in one of the branches: |
| 39 | +# |
| 40 | +# l/l (file) - |
| 41 | +# - m/m (file) |
| 42 | +# |
| 43 | +test_expect_success 'setup repo for checkout with various types of changes' ' |
| 44 | + git init sub && |
| 45 | + ( |
| 46 | + cd sub && |
| 47 | + git checkout -b B2 && |
| 48 | + echo B2 >file && |
| 49 | + git add file && |
| 50 | + git commit -m file && |
| 51 | +
|
| 52 | + git checkout -b B1 && |
| 53 | + echo B1 >file && |
| 54 | + git add file && |
| 55 | + git commit -m file |
| 56 | + ) && |
| 57 | +
|
| 58 | + git init various && |
| 59 | + ( |
| 60 | + cd various && |
| 61 | +
|
| 62 | + git checkout -b B1 && |
| 63 | + mkdir a c e && |
| 64 | + echo a/a >a/a && |
| 65 | + echo b >b && |
| 66 | + echo c/c >c/c && |
| 67 | + test_ln_s_add c d && |
| 68 | + echo e/e >e/e && |
| 69 | + git submodule add ../sub f && |
| 70 | + git submodule add ../sub g && |
| 71 | + test_ln_s_add c h && |
| 72 | +
|
| 73 | + echo "B1 i" >i && |
| 74 | + test_ln_s_add c j && |
| 75 | + git submodule add -b B1 ../sub k && |
| 76 | + mkdir l && |
| 77 | + echo l/l >l/l && |
| 78 | +
|
| 79 | + git add . && |
| 80 | + git commit -m B1 && |
| 81 | +
|
| 82 | + git checkout -b B2 && |
| 83 | + git rm -rf :^.gitmodules :^k && |
| 84 | + mkdir b d f && |
| 85 | + echo a >a && |
| 86 | + echo b/b >b/b && |
| 87 | + test_ln_s_add b c && |
| 88 | + echo d/d >d/d && |
| 89 | + git submodule add ../sub e && |
| 90 | + echo f/f >f/f && |
| 91 | + test_ln_s_add b g && |
| 92 | + git submodule add ../sub h && |
| 93 | +
|
| 94 | + echo "B2 i" >i && |
| 95 | + test_ln_s_add b j && |
| 96 | + git -C k checkout B2 && |
| 97 | + mkdir m && |
| 98 | + echo m/m >m/m && |
| 99 | +
|
| 100 | + git add . && |
| 101 | + git commit -m B2 && |
| 102 | +
|
| 103 | + git checkout --recurse-submodules B1 |
| 104 | + ) |
| 105 | +' |
| 106 | + |
| 107 | +for mode in sequential parallel sequential-fallback |
| 108 | +do |
| 109 | + case $mode in |
| 110 | + sequential) workers=1 threshold=0 expected_workers=0 ;; |
| 111 | + parallel) workers=2 threshold=0 expected_workers=2 ;; |
| 112 | + sequential-fallback) workers=2 threshold=100 expected_workers=0 ;; |
| 113 | + esac |
| 114 | + |
| 115 | + test_expect_success "$mode checkout" ' |
| 116 | + repo=various_$mode && |
| 117 | + cp -R various $repo && |
| 118 | +
|
| 119 | + # The just copied files have more recent timestamps than their |
| 120 | + # associated index entries. So refresh the cached timestamps |
| 121 | + # to avoid an "entry not up-to-date" error from `git checkout`. |
| 122 | + # We only have to do this for the submodules as `git checkout` |
| 123 | + # will already refresh the superproject index before performing |
| 124 | + # the up-to-date check. |
| 125 | + # |
| 126 | + git -C $repo submodule foreach "git update-index --refresh" && |
| 127 | +
|
| 128 | + set_checkout_config $workers $threshold && |
| 129 | + test_checkout_workers $expected_workers \ |
| 130 | + git -C $repo checkout --recurse-submodules B2 && |
| 131 | + verify_checkout $repo |
| 132 | + ' |
| 133 | +done |
| 134 | + |
| 135 | +for mode in parallel sequential-fallback |
| 136 | +do |
| 137 | + case $mode in |
| 138 | + parallel) workers=2 threshold=0 expected_workers=2 ;; |
| 139 | + sequential-fallback) workers=2 threshold=100 expected_workers=0 ;; |
| 140 | + esac |
| 141 | + |
| 142 | + test_expect_success "$mode checkout on clone" ' |
| 143 | + repo=various_${mode}_clone && |
| 144 | + set_checkout_config $workers $threshold && |
| 145 | + test_checkout_workers $expected_workers \ |
| 146 | + git clone --recurse-submodules --branch B2 various $repo && |
| 147 | + verify_checkout $repo |
| 148 | + ' |
| 149 | +done |
| 150 | + |
| 151 | +# Just to be paranoid, actually compare the working trees' contents directly. |
| 152 | +test_expect_success 'compare the working trees' ' |
| 153 | + rm -rf various_*/.git && |
| 154 | + rm -rf various_*/*/.git && |
| 155 | +
|
| 156 | + # We use `git diff` instead of `diff -r` because the latter would |
| 157 | + # follow symlinks, and not all `diff` implementations support the |
| 158 | + # `--no-dereference` option. |
| 159 | + # |
| 160 | + git diff --no-index various_sequential various_parallel && |
| 161 | + git diff --no-index various_sequential various_parallel_clone && |
| 162 | + git diff --no-index various_sequential various_sequential-fallback && |
| 163 | + git diff --no-index various_sequential various_sequential-fallback_clone |
| 164 | +' |
| 165 | + |
| 166 | +# Currently, each submodule is checked out in a separated child process, but |
| 167 | +# these subprocesses must also be able to use parallel checkout workers to |
| 168 | +# write the submodules' entries. |
| 169 | +test_expect_success 'submodules can use parallel checkout' ' |
| 170 | + set_checkout_config 2 0 && |
| 171 | + git init super && |
| 172 | + ( |
| 173 | + cd super && |
| 174 | + git init sub && |
| 175 | + test_commit -C sub A && |
| 176 | + test_commit -C sub B && |
| 177 | + git submodule add ./sub && |
| 178 | + git commit -m sub && |
| 179 | + rm sub/* && |
| 180 | + test_checkout_workers 2 git checkout --recurse-submodules . |
| 181 | + ) |
| 182 | +' |
| 183 | + |
| 184 | +test_expect_success 'parallel checkout respects --[no]-force' ' |
| 185 | + set_checkout_config 2 0 && |
| 186 | + git init dirty && |
| 187 | + ( |
| 188 | + cd dirty && |
| 189 | + mkdir D && |
| 190 | + test_commit D/F && |
| 191 | + test_commit F && |
| 192 | +
|
| 193 | + rm -rf D && |
| 194 | + echo changed >D && |
| 195 | + echo changed >F.t && |
| 196 | +
|
| 197 | + # We expect 0 workers because there is nothing to be done |
| 198 | + test_checkout_workers 0 git checkout HEAD && |
| 199 | + test_path_is_file D && |
| 200 | + grep changed D && |
| 201 | + grep changed F.t && |
| 202 | +
|
| 203 | + test_checkout_workers 2 git checkout --force HEAD && |
| 204 | + test_path_is_dir D && |
| 205 | + grep D/F D/F.t && |
| 206 | + grep F F.t |
| 207 | + ) |
| 208 | +' |
| 209 | + |
| 210 | +test_expect_success SYMLINKS 'parallel checkout checks for symlinks in leading dirs' ' |
| 211 | + set_checkout_config 2 0 && |
| 212 | + git init symlinks && |
| 213 | + ( |
| 214 | + cd symlinks && |
| 215 | + mkdir D untracked && |
| 216 | + # Commit 2 files to have enough work for 2 parallel workers |
| 217 | + test_commit D/A && |
| 218 | + test_commit D/B && |
| 219 | + rm -rf D && |
| 220 | + ln -s untracked D && |
| 221 | +
|
| 222 | + test_checkout_workers 2 git checkout --force HEAD && |
| 223 | + ! test -h D && |
| 224 | + grep D/A D/A.t && |
| 225 | + grep D/B D/B.t |
| 226 | + ) |
| 227 | +' |
| 228 | + |
| 229 | +test_done |
0 commit comments