Matheus Tavares | d0e5d35 | 2021-05-04 13:27:31 -0300 | [diff] [blame] | 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' ' |
Taylor Blau | ef374dd | 2022-09-30 16:48:56 -0400 | [diff] [blame] | 44 | test_config_global protocol.file.allow always && |
| 45 | |
Matheus Tavares | d0e5d35 | 2021-05-04 13:27:31 -0300 | [diff] [blame] | 46 | git init sub && |
| 47 | ( |
| 48 | cd sub && |
| 49 | git checkout -b B2 && |
| 50 | echo B2 >file && |
| 51 | git add file && |
| 52 | git commit -m file && |
| 53 | |
| 54 | git checkout -b B1 && |
| 55 | echo B1 >file && |
| 56 | git add file && |
| 57 | git commit -m file |
| 58 | ) && |
| 59 | |
| 60 | git init various && |
| 61 | ( |
| 62 | cd various && |
| 63 | |
| 64 | git checkout -b B1 && |
| 65 | mkdir a c e && |
| 66 | echo a/a >a/a && |
| 67 | echo b >b && |
| 68 | echo c/c >c/c && |
| 69 | test_ln_s_add c d && |
| 70 | echo e/e >e/e && |
| 71 | git submodule add ../sub f && |
| 72 | git submodule add ../sub g && |
| 73 | test_ln_s_add c h && |
| 74 | |
| 75 | echo "B1 i" >i && |
| 76 | test_ln_s_add c j && |
| 77 | git submodule add -b B1 ../sub k && |
| 78 | mkdir l && |
| 79 | echo l/l >l/l && |
| 80 | |
| 81 | git add . && |
| 82 | git commit -m B1 && |
| 83 | |
| 84 | git checkout -b B2 && |
| 85 | git rm -rf :^.gitmodules :^k && |
| 86 | mkdir b d f && |
| 87 | echo a >a && |
| 88 | echo b/b >b/b && |
| 89 | test_ln_s_add b c && |
| 90 | echo d/d >d/d && |
| 91 | git submodule add ../sub e && |
| 92 | echo f/f >f/f && |
| 93 | test_ln_s_add b g && |
| 94 | git submodule add ../sub h && |
| 95 | |
| 96 | echo "B2 i" >i && |
| 97 | test_ln_s_add b j && |
| 98 | git -C k checkout B2 && |
| 99 | mkdir m && |
| 100 | echo m/m >m/m && |
| 101 | |
| 102 | git add . && |
| 103 | git commit -m B2 && |
| 104 | |
| 105 | git checkout --recurse-submodules B1 |
| 106 | ) |
| 107 | ' |
| 108 | |
| 109 | for mode in sequential parallel sequential-fallback |
| 110 | do |
| 111 | case $mode in |
| 112 | sequential) workers=1 threshold=0 expected_workers=0 ;; |
| 113 | parallel) workers=2 threshold=0 expected_workers=2 ;; |
| 114 | sequential-fallback) workers=2 threshold=100 expected_workers=0 ;; |
| 115 | esac |
| 116 | |
| 117 | test_expect_success "$mode checkout" ' |
| 118 | repo=various_$mode && |
Matheus Tavares | ea08db7 | 2021-05-26 20:58:56 -0300 | [diff] [blame] | 119 | cp -R -P various $repo && |
Matheus Tavares | d0e5d35 | 2021-05-04 13:27:31 -0300 | [diff] [blame] | 120 | |
| 121 | # The just copied files have more recent timestamps than their |
| 122 | # associated index entries. So refresh the cached timestamps |
| 123 | # to avoid an "entry not up-to-date" error from `git checkout`. |
| 124 | # We only have to do this for the submodules as `git checkout` |
| 125 | # will already refresh the superproject index before performing |
| 126 | # the up-to-date check. |
| 127 | # |
| 128 | git -C $repo submodule foreach "git update-index --refresh" && |
| 129 | |
| 130 | set_checkout_config $workers $threshold && |
| 131 | test_checkout_workers $expected_workers \ |
| 132 | git -C $repo checkout --recurse-submodules B2 && |
| 133 | verify_checkout $repo |
| 134 | ' |
| 135 | done |
| 136 | |
| 137 | for mode in parallel sequential-fallback |
| 138 | do |
| 139 | case $mode in |
| 140 | parallel) workers=2 threshold=0 expected_workers=2 ;; |
| 141 | sequential-fallback) workers=2 threshold=100 expected_workers=0 ;; |
| 142 | esac |
| 143 | |
| 144 | test_expect_success "$mode checkout on clone" ' |
Taylor Blau | ef374dd | 2022-09-30 16:48:56 -0400 | [diff] [blame] | 145 | test_config_global protocol.file.allow always && |
Matheus Tavares | d0e5d35 | 2021-05-04 13:27:31 -0300 | [diff] [blame] | 146 | repo=various_${mode}_clone && |
| 147 | set_checkout_config $workers $threshold && |
| 148 | test_checkout_workers $expected_workers \ |
| 149 | git clone --recurse-submodules --branch B2 various $repo && |
| 150 | verify_checkout $repo |
| 151 | ' |
| 152 | done |
| 153 | |
| 154 | # Just to be paranoid, actually compare the working trees' contents directly. |
| 155 | test_expect_success 'compare the working trees' ' |
| 156 | rm -rf various_*/.git && |
| 157 | rm -rf various_*/*/.git && |
| 158 | |
| 159 | # We use `git diff` instead of `diff -r` because the latter would |
| 160 | # follow symlinks, and not all `diff` implementations support the |
| 161 | # `--no-dereference` option. |
| 162 | # |
| 163 | git diff --no-index various_sequential various_parallel && |
| 164 | git diff --no-index various_sequential various_parallel_clone && |
| 165 | git diff --no-index various_sequential various_sequential-fallback && |
| 166 | git diff --no-index various_sequential various_sequential-fallback_clone |
| 167 | ' |
| 168 | |
| 169 | # Currently, each submodule is checked out in a separated child process, but |
| 170 | # these subprocesses must also be able to use parallel checkout workers to |
| 171 | # write the submodules' entries. |
| 172 | test_expect_success 'submodules can use parallel checkout' ' |
| 173 | set_checkout_config 2 0 && |
| 174 | git init super && |
| 175 | ( |
| 176 | cd super && |
| 177 | git init sub && |
| 178 | test_commit -C sub A && |
| 179 | test_commit -C sub B && |
| 180 | git submodule add ./sub && |
| 181 | git commit -m sub && |
| 182 | rm sub/* && |
| 183 | test_checkout_workers 2 git checkout --recurse-submodules . |
| 184 | ) |
| 185 | ' |
| 186 | |
| 187 | test_expect_success 'parallel checkout respects --[no]-force' ' |
| 188 | set_checkout_config 2 0 && |
| 189 | git init dirty && |
| 190 | ( |
| 191 | cd dirty && |
| 192 | mkdir D && |
| 193 | test_commit D/F && |
| 194 | test_commit F && |
| 195 | |
| 196 | rm -rf D && |
| 197 | echo changed >D && |
| 198 | echo changed >F.t && |
| 199 | |
| 200 | # We expect 0 workers because there is nothing to be done |
| 201 | test_checkout_workers 0 git checkout HEAD && |
| 202 | test_path_is_file D && |
| 203 | grep changed D && |
| 204 | grep changed F.t && |
| 205 | |
| 206 | test_checkout_workers 2 git checkout --force HEAD && |
| 207 | test_path_is_dir D && |
| 208 | grep D/F D/F.t && |
| 209 | grep F F.t |
| 210 | ) |
| 211 | ' |
| 212 | |
| 213 | test_expect_success SYMLINKS 'parallel checkout checks for symlinks in leading dirs' ' |
| 214 | set_checkout_config 2 0 && |
| 215 | git init symlinks && |
| 216 | ( |
| 217 | cd symlinks && |
| 218 | mkdir D untracked && |
| 219 | # Commit 2 files to have enough work for 2 parallel workers |
| 220 | test_commit D/A && |
| 221 | test_commit D/B && |
| 222 | rm -rf D && |
| 223 | ln -s untracked D && |
| 224 | |
| 225 | test_checkout_workers 2 git checkout --force HEAD && |
| 226 | ! test -h D && |
| 227 | grep D/A D/A.t && |
| 228 | grep D/B D/B.t |
| 229 | ) |
| 230 | ' |
| 231 | |
Matheus Tavares | 11d14de | 2022-07-14 08:49:11 -0300 | [diff] [blame] | 232 | # This test is here (and not in e.g. t2022-checkout-paths.sh), because we |
| 233 | # check the final report including sequential, parallel, and delayed entries |
| 234 | # all at the same time. So we must have finer control of the parallel checkout |
| 235 | # variables. |
Matheus Tavares | 4d1d843 | 2022-08-14 22:06:38 -0300 | [diff] [blame] | 236 | test_expect_success '"git checkout ." report should not include failed entries' ' |
Matheus Tavares | 11d14de | 2022-07-14 08:49:11 -0300 | [diff] [blame] | 237 | test_config_global filter.delay.process \ |
Matheus Tavares | 4d1d843 | 2022-08-14 22:06:38 -0300 | [diff] [blame] | 238 | "test-tool rot13-filter --always-delay --log=delayed.log clean smudge delay" && |
Matheus Tavares | 11d14de | 2022-07-14 08:49:11 -0300 | [diff] [blame] | 239 | test_config_global filter.delay.required true && |
| 240 | test_config_global filter.cat.clean cat && |
| 241 | test_config_global filter.cat.smudge cat && |
| 242 | test_config_global filter.cat.required true && |
| 243 | |
| 244 | set_checkout_config 2 0 && |
| 245 | git init failed_entries && |
| 246 | ( |
| 247 | cd failed_entries && |
| 248 | cat >.gitattributes <<-EOF && |
| 249 | *delay* filter=delay |
| 250 | parallel-ineligible* filter=cat |
| 251 | EOF |
| 252 | echo a >missing-delay.a && |
| 253 | echo a >parallel-ineligible.a && |
| 254 | echo a >parallel-eligible.a && |
| 255 | echo b >success-delay.b && |
| 256 | echo b >parallel-ineligible.b && |
| 257 | echo b >parallel-eligible.b && |
| 258 | git add -A && |
| 259 | git commit -m files && |
| 260 | |
| 261 | a_blob="$(git rev-parse :parallel-ineligible.a)" && |
| 262 | rm .git/objects/$(test_oid_to_path $a_blob) && |
| 263 | rm *.a *.b && |
| 264 | |
| 265 | test_checkout_workers 2 test_must_fail git checkout . 2>err && |
| 266 | |
| 267 | # All *.b entries should succeed and all *.a entries should fail: |
| 268 | # - missing-delay.a: the delay filter will drop this path |
| 269 | # - parallel-*.a: the blob will be missing |
| 270 | # |
| 271 | grep "Updated 3 paths from the index" err && |
| 272 | test_stdout_line_count = 3 ls *.b && |
| 273 | ! ls *.a |
| 274 | ) |
| 275 | ' |
| 276 | |
Matheus Tavares | d0e5d35 | 2021-05-04 13:27:31 -0300 | [diff] [blame] | 277 | test_done |