File: t-pull.sh

package info (click to toggle)
git-lfs 3.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,808 kB
  • sloc: sh: 21,256; makefile: 507; ruby: 417
file content (461 lines) | stat: -rwxr-xr-x 11,001 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
#!/usr/bin/env bash

. "$(dirname "$0")/testlib.sh"

begin_test "pull"
(
  set -e

  reponame="$(basename "$0" ".sh")"
  setup_remote_repo "$reponame"

  clone_repo "$reponame" clone
  clone_repo "$reponame" repo

  git lfs track "*.dat" 2>&1 | tee track.log
  grep "Tracking \"\*.dat\"" track.log

  contents="a"
  contents_oid=$(calc_oid "$contents")
  contents2="A"
  contents2_oid=$(calc_oid "$contents2")
  contents3="dir"
  contents3_oid=$(calc_oid "$contents3")

  mkdir dir
  echo "*.log" > .gitignore
  printf "%s" "$contents" > a.dat
  printf "%s" "$contents2" > á.dat
  printf "%s" "$contents3" > dir/dir.dat
  git add .
  git commit -m "add files" 2>&1 | tee commit.log
  grep "main (root-commit)" commit.log
  grep "5 files changed" commit.log
  grep "create mode 100644 a.dat" commit.log
  grep "create mode 100644 .gitattributes" commit.log

  ls -al
  [ "a" = "$(cat a.dat)" ]
  [ "A" = "$(cat "á.dat")" ]
  [ "dir" = "$(cat "dir/dir.dat")" ]

  assert_pointer "main" "a.dat" "$contents_oid" 1
  assert_pointer "main" "á.dat" "$contents2_oid" 1
  assert_pointer "main" "dir/dir.dat" "$contents3_oid" 3

  refute_server_object "$reponame" "$contents_oid"
  refute_server_object "$reponame" "$contents2_oid"
  refute_server_object "$reponame" "$contents33oid"

  echo "initial push"
  git push origin main 2>&1 | tee push.log
  grep "Uploading LFS objects: 100% (3/3), 5 B" push.log
  grep "main -> main" push.log

  assert_server_object "$reponame" "$contents_oid"
  assert_server_object "$reponame" "$contents2_oid"
  assert_server_object "$reponame" "$contents3_oid"

  # change to the clone's working directory
  cd ../clone

  echo "normal pull"
  git config branch.main.remote origin
  git config branch.main.merge refs/heads/main
  git pull 2>&1

  [ "a" = "$(cat a.dat)" ]
  [ "A" = "$(cat "á.dat")" ]

  assert_local_object "$contents_oid" 1
  assert_local_object "$contents2_oid" 1
  assert_clean_status

  echo "lfs pull"
  rm -r a.dat á.dat dir # removing files makes the status dirty
  rm -rf .git/lfs/objects
  git lfs pull
  ls -al
  [ "a" = "$(cat a.dat)" ]
  [ "A" = "$(cat "á.dat")" ]
  assert_local_object "$contents_oid" 1
  assert_local_object "$contents2_oid" 1
  git lfs fsck

  echo "lfs pull with remote"
  rm -r a.dat á.dat dir
  rm -rf .git/lfs/objects
  git lfs pull origin
  [ "a" = "$(cat a.dat)" ]
  [ "A" = "$(cat "á.dat")" ]
  assert_local_object "$contents_oid" 1
  assert_local_object "$contents2_oid" 1
  assert_clean_status
  git lfs fsck

  echo "lfs pull with local storage"
  rm a.dat á.dat
  git lfs pull
  [ "a" = "$(cat a.dat)" ]
  [ "A" = "$(cat "á.dat")" ]
  assert_clean_status

  echo "lfs pull with include/exclude filters in gitconfig"
  rm -rf .git/lfs/objects
  git config "lfs.fetchinclude" "a*"
  git lfs pull
  assert_local_object "$contents_oid" 1
  assert_clean_status

  rm -rf .git/lfs/objects
  git config --unset "lfs.fetchinclude"
  git config "lfs.fetchexclude" "a*"
  git lfs pull
  refute_local_object "$contents_oid"
  assert_clean_status

  echo "lfs pull with include/exclude filters in command line"
  git config --unset "lfs.fetchexclude"
  rm -rf .git/lfs/objects
  git lfs pull --include="a*"
  assert_local_object "$contents_oid" 1
  assert_clean_status

  rm -rf .git/lfs/objects
  git lfs pull --exclude="a*"
  refute_local_object "$contents_oid"
  assert_clean_status

  echo "resetting to test status"
  git reset --hard
  assert_clean_status

  echo "lfs pull clean status"
  git lfs pull
  assert_clean_status

  echo "lfs pull with -I"
  git lfs pull -I "*.dat"
  assert_clean_status

  echo "lfs pull with empty file"
  touch empty.dat
  git add empty.dat
  git commit -m 'empty'
  git lfs pull
  [ -z "$(cat empty.dat)" ]
  assert_clean_status

  echo "lfs pull in subdir"
  cd dir
  git lfs pull
  assert_clean_status

  echo "lfs pull in subdir with -I"
  git lfs pull -I "*.dat"
  assert_clean_status
)
end_test

begin_test "pull without clean filter"
(
  set -e

  GIT_LFS_SKIP_SMUDGE=1 git clone $GITSERVER/t-pull no-clean
  cd no-clean
  git lfs uninstall
  git config --list > config.txt
  grep "filter.lfs.clean" config.txt && {
    echo "clean filter still configured:"
    cat config.txt
    exit 1
  }

  contents="a"
  contents_oid=$(calc_oid "$contents")

  # LFS object not downloaded, pointer in working directory
  grep "$contents_oid" a.dat || {
    echo "a.dat not $contents_oid"
    ls -al
    cat a.dat
    exit 1
  }
  assert_local_object "$contents_oid"

  git lfs pull | tee pull.txt
  if [ "0" -ne "${PIPESTATUS[0]}" ]; then
    echo >&2 "fatal: expected pull to succeed ..."
    exit 1
  fi
  grep "Git LFS is not installed" pull.txt
  echo "pulled!"

  # LFS object downloaded, pointer unchanged
  grep "$contents_oid" a.dat || {
    echo "a.dat not $contents_oid"
    ls -al
    cat a.dat
    exit 1
  }
  assert_local_object "$contents_oid" 1
)
end_test

begin_test "pull with raw remote url"
(
  set -e
  mkdir raw
  cd raw
  git init
  git lfs install --local --skip-smudge

  git remote add origin $GITSERVER/t-pull
  git pull origin main

  contents="a"
  contents_oid=$(calc_oid "$contents")

  # LFS object not downloaded, pointer in working directory
  refute_local_object "$contents_oid"
  grep "$contents_oid" a.dat

  git lfs pull "$GITSERVER/t-pull"
  echo "pulled!"

  # LFS object downloaded and in working directory
  assert_local_object "$contents_oid" 1
  [ "0" = "$(grep -c "$contents_oid" a.dat)" ]
  [ "a" = "$(cat a.dat)" ]
)
end_test

begin_test "pull with multiple remotes"
(
  set -e
  mkdir multiple
  cd multiple
  git init
  git lfs install --local --skip-smudge

  git remote add origin "$GITSERVER/t-pull"
  git remote add bad-remote "invalid-url"
  git pull origin main

  contents="a"
  contents_oid=$(calc_oid "$contents")

  # LFS object not downloaded, pointer in working directory
  refute_local_object "$contents_oid"
  grep "$contents_oid" a.dat

  # pull should default to origin instead of bad-remote
  git lfs pull
  echo "pulled!"

  # LFS object downloaded and in working directory
  assert_local_object "$contents_oid" 1
  [ "0" = "$(grep -c "$contents_oid" a.dat)" ]
  [ "a" = "$(cat a.dat)" ]
)
end_test

begin_test "pull with invalid insteadof"
(
  set -e
  mkdir insteadof
  cd insteadof
  git init
  git lfs install --local --skip-smudge

  git remote add origin "$GITSERVER/t-pull"
  git pull origin main

  # set insteadOf to rewrite the href of downloading LFS object.
  git config url."$GITSERVER/storage/invalid".insteadOf "$GITSERVER/storage/"
  # Enable href rewriting explicitly.
  git config lfs.transfer.enablehrefrewrite true

  set +e
  git lfs pull > pull.log 2>&1
  res=$?

  set -e
  [ "$res" = "2" ]

  # check rewritten href is used to download LFS object.
  grep "LFS: Repository or object not found: $GITSERVER/storage/invalid" pull.log

  # lfs-pull succeed after unsetting enableHrefRewrite config
  git config --unset lfs.transfer.enablehrefrewrite
  git lfs pull
)
end_test

begin_test "pull with merge conflict"
(
  set -e
  git init pull-merge-conflict
  cd pull-merge-conflict

  git lfs track "*.bin"
  git add .
  git commit -m 'gitattributes'
  printf abc > abc.bin
  git add .
  git commit -m 'abc'

  git checkout -b def
  printf def > abc.bin
  git add .
  git commit -m 'def'

  git checkout main
  printf ghi > abc.bin
  git add .
  git commit -m 'ghi'

  # This will exit nonzero because of the merge conflict.
  GIT_LFS_SKIP_SMUDGE=1 git merge def || true
  git lfs pull > pull.log 2>&1
  [ ! -s pull.log ]
)
end_test

begin_test "pull: with missing object"
(
  set -e

  # this clone is setup in the first test in this file
  cd clone
  rm -rf .git/lfs/objects

  contents_oid=$(calc_oid "a")
  reponame="$(basename "$0" ".sh")"
  delete_server_object "$reponame" "$contents_oid"
  refute_server_object "$reponame" "$contents_oid"

  # should return non-zero, but should also download all the other valid files too
  git config branch.main.remote origin
  git config branch.main.merge refs/heads/main
  git lfs pull 2>&1 | tee pull.log
  pull_exit="${PIPESTATUS[0]}"
  [ "$pull_exit" != "0" ]

  grep "$contents_oid" pull.log

  contents2_oid=$(calc_oid "A")
  assert_local_object "$contents2_oid" 1
  refute_local_object "$contents_oid"
)
end_test

begin_test "pull: outside git repository"
(
  set +e
  git lfs pull 2>&1 > pull.log
  res=$?

  set -e
  if [ "$res" = "0" ]; then
    echo "Passes because $GIT_LFS_TEST_DIR is unset."
    exit 0
  fi
  [ "$res" = "128" ]
  grep "Not in a Git repository" pull.log
)
end_test

begin_test "pull with empty file doesn't modify mtime"
(
  set -e
  git init pull-empty-file
  cd pull-empty-file

  git lfs track "*.bin"
  git add .
  git commit -m 'gitattributes'
  printf abc > abc.bin
  git add .
  git commit -m 'abc'

  touch foo.bin
  lfstest-nanomtime foo.bin >foo.mtime

  # This isn't necessary, but it takes a few cycles to make sure that our
  # timestamp changes.
  git add foo.bin
  git commit -m 'foo'

  git lfs pull
  lfstest-nanomtime foo.bin >foo.mtime2
  diff -u foo.mtime foo.mtime2
)
end_test

begin_test "pull with partial clone and sparse checkout and index"
(
  set -e

  # Only test with Git version 2.42.0 as it introduced support for the
  # "objecttype" format option to the "git ls-files" command, which our
  # code requires.
  ensure_git_version_isnt "$VERSION_LOWER" "2.42.0"

  reponame="pull-sparse"
  setup_remote_repo "$reponame"
  clone_repo "$reponame" "$reponame"

  git lfs track "*.dat"

  contents1="a"
  contents1_oid=$(calc_oid "$contents1")
  contents2="b"
  contents2_oid=$(calc_oid "$contents2")
  contents3="c"
  contents3_oid=$(calc_oid "$contents3")

  mkdir in-dir out-dir
  printf "%s" "$contents1" >a.dat
  printf "%s" "$contents2" >in-dir/b.dat
  printf "%s" "$contents3" >out-dir/c.dat
  git add .
  git commit -m "add files"

  git push origin main

  assert_server_object "$reponame" "$contents1_oid"
  assert_server_object "$reponame" "$contents2_oid"
  assert_server_object "$reponame" "$contents3_oid"

  # Create a partial clone with a cone-mode sparse checkout of one directory
  # and a sparse index, which is important because otherwise the "git ls-files"
  # command ignores the --sparse option and lists all Git LFS files.
  cd ..
  git clone --filter=tree:0 --depth=1 --no-checkout \
    "$GITSERVER/$reponame" "${reponame}-partial"

  cd "${reponame}-partial"
  git sparse-checkout init --cone --sparse-index
  git sparse-checkout set "in-dir"
  git checkout main

  [ -d "in-dir" ]
  [ ! -e "out-dir" ]

  assert_local_object "$contents1_oid" 1
  assert_local_object "$contents2_oid" 1
  refute_local_object "$contents3_oid"

  # Git LFS objects associated with files outside of the sparse cone
  # should not be pulled.
  git lfs pull 2>&1 | tee pull.log
  if [ "0" -ne "${PIPESTATUS[0]}" ]; then
    echo >&2 "fatal: expected pull to succeed ..."
    exit 1
  fi
  grep -q "Downloading LFS objects" pull.log && exit 1

  refute_local_object "$contents3_oid"
)
end_test