Imported Upstream version 2.4.2
[scm/test.git] / t / t-prune.sh
1 #!/usr/bin/env bash
2
3 . "$(dirname "$0")/testlib.sh"
4
5 begin_test "prune unreferenced and old"
6 (
7   set -e
8
9   reponame="prune_unref_old"
10   setup_remote_repo "remote_$reponame"
11
12   clone_repo "remote_$reponame" "clone_$reponame"
13
14   git lfs track "*.dat" 2>&1 | tee track.log
15   grep "Tracking \"\*.dat\"" track.log
16
17   # generate content we'll use
18   content_unreferenced="To delete: unreferenced"
19   content_oldandpushed="To delete: pushed and too old"
20   content_oldandunchanged="Keep: pushed and created a while ago, but still current"
21   oid_unreferenced=$(calc_oid "$content_unreferenced")
22   oid_oldandpushed=$(calc_oid "$content_oldandpushed")
23   oid_oldandunchanged=$(calc_oid "$content_oldandunchanged")
24   content_retain1="Retained content 1"
25   content_retain2="Retained content 2"
26   oid_retain1=$(calc_oid "$content_retain1")
27   oid_retain2=$(calc_oid "$content_retain2")
28
29
30   # Remember for something to be 'too old' it has to appear on the MINUS side
31   # of the diff outside the prune window, i.e. it's not when it was introduced
32   # but when it disappeared from relevance. That's why changes to file1.dat on master
33   # from 7d ago are included even though the commit itself is outside of the window,
34   # that content of file1.dat was relevant until it was removed with a commit, inside the window
35   # think of it as windows of relevance that overlap until the content is replaced
36
37   # we also make sure we commit today on master so that the recent commits measured
38   # from latest commit on master tracks back from there
39   echo "[
40   {
41     \"CommitDate\":\"$(get_date -20d)\",
42     \"Files\":[
43       {\"Filename\":\"old.dat\",\"Size\":${#content_oldandpushed}, \"Data\":\"$content_oldandpushed\"},
44       {\"Filename\":\"stillcurrent.dat\",\"Size\":${#content_oldandunchanged}, \"Data\":\"$content_oldandunchanged\"}]
45   },
46   {
47     \"CommitDate\":\"$(get_date -7d)\",
48     \"Files\":[
49       {\"Filename\":\"old.dat\",\"Size\":${#content_retain1}, \"Data\":\"$content_retain1\"}]
50   },
51   {
52     \"CommitDate\":\"$(get_date -4d)\",
53     \"NewBranch\":\"branch_to_delete\",
54     \"Files\":[
55       {\"Filename\":\"unreferenced.dat\",\"Size\":${#content_unreferenced}, \"Data\":\"$content_unreferenced\"}]
56   },
57   {
58     \"ParentBranches\":[\"master\"],
59     \"Files\":[
60       {\"Filename\":\"old.dat\",\"Size\":${#content_retain2}, \"Data\":\"$content_retain2\"}]
61   }
62   ]" | lfstest-testutils addcommits
63
64   git push origin master
65   git branch -D branch_to_delete
66
67   git config lfs.fetchrecentrefsdays 5
68   git config lfs.fetchrecentremoterefs true
69   git config lfs.fetchrecentcommitsdays 3
70   git config lfs.pruneoffsetdays 2
71
72   git lfs prune --dry-run --verbose 2>&1 | tee prune.log
73
74   grep "prune: 5 local object(s), 3 retained" prune.log
75   grep "prune: 2 file(s) would be pruned" prune.log
76   grep "$oid_oldandpushed" prune.log
77   grep "$oid_unreferenced" prune.log
78
79   assert_local_object "$oid_oldandpushed" "${#content_oldandpushed}"
80   assert_local_object "$oid_unreferenced" "${#content_unreferenced}"
81   git lfs prune
82   refute_local_object "$oid_oldandpushed" "${#content_oldandpushed}"
83   refute_local_object "$oid_unreferenced" "${#content_unreferenced}"
84   assert_local_object "$oid_retain1" "${#content_retain1}"
85   assert_local_object "$oid_retain2" "${#content_retain2}"
86
87   # now only keep AT refs, no recents
88   git config lfs.fetchrecentcommitsdays 0
89
90   git lfs prune --verbose 2>&1 | tee prune.log
91   grep "prune: 3 local object(s), 2 retained" prune.log
92   grep "prune: Deleting objects: 100% (1/1), done" prune.log
93   grep "$oid_retain1" prune.log
94   refute_local_object "$oid_retain1"
95   assert_local_object "$oid_retain2" "${#content_retain2}"
96 )
97 end_test
98
99 begin_test "prune keep unpushed"
100 (
101   set -e
102
103   # need to set up many commits on each branch with old data so that would
104   # get deleted if it were not for unpushed status (heads would never be pruned but old changes would)
105   reponame="prune_keep_unpushed"
106   setup_remote_repo "remote_$reponame"
107
108   clone_repo "remote_$reponame" "clone_$reponame"
109
110   git lfs track "*.dat" 2>&1 | tee track.log
111   grep "Tracking \"\*.dat\"" track.log
112
113
114   content_keepunpushedhead1="Keep: unpushed HEAD 1"
115   content_keepunpushedhead2="Keep: unpushed HEAD 2"
116   content_keepunpushedhead3="Keep: unpushed HEAD 3"
117   content_keepunpushedbranch1="Keep: unpushed second branch 1"
118   content_keepunpushedbranch2="Keep: unpushed second branch 2"
119   content_keepunpushedbranch3="Keep: unpushed second branch 3"
120   oid_keepunpushedhead1=$(calc_oid "$content_keepunpushedhead1")
121   oid_keepunpushedhead2=$(calc_oid "$content_keepunpushedhead2")
122   oid_keepunpushedhead3=$(calc_oid "$content_keepunpushedhead3")
123   oid_keepunpushedbranch1=$(calc_oid "$content_keepunpushedbranch1")
124   oid_keepunpushedbranch2=$(calc_oid "$content_keepunpushedbranch2")
125   oid_keepunpushedbranch3=$(calc_oid "$content_keepunpushedbranch3")
126   oid_keepunpushedtagged1=$(calc_oid "$content_keepunpushedtagged1")
127   oid_keepunpushedtagged2=$(calc_oid "$content_keepunpushedtagged1")
128
129   echo "[
130   {
131     \"CommitDate\":\"$(get_date -40d)\",
132     \"Files\":[
133       {\"Filename\":\"file.dat\",\"Size\":${#content_keepunpushedhead1}, \"Data\":\"$content_keepunpushedhead1\"}]
134   },
135   {
136     \"CommitDate\":\"$(get_date -31d)\",
137     \"ParentBranches\":[\"master\"],
138     \"NewBranch\":\"branch_unpushed\",
139     \"Files\":[
140       {\"Filename\":\"file.dat\",\"Size\":${#content_keepunpushedbranch1}, \"Data\":\"$content_keepunpushedbranch1\"}]
141   },
142   {
143     \"CommitDate\":\"$(get_date -16d)\",
144     \"Files\":[
145       {\"Filename\":\"file.dat\",\"Size\":${#content_keepunpushedbranch2}, \"Data\":\"$content_keepunpushedbranch2\"}]
146   },
147   {
148     \"CommitDate\":\"$(get_date -2d)\",
149     \"Files\":[
150       {\"Filename\":\"file.dat\",\"Size\":${#content_keepunpushedbranch3}, \"Data\":\"$content_keepunpushedbranch3\"}]
151   },
152   {
153     \"CommitDate\":\"$(get_date -21d)\",
154     \"ParentBranches\":[\"master\"],
155     \"Files\":[
156       {\"Filename\":\"file.dat\",\"Size\":${#content_keepunpushedhead2}, \"Data\":\"$content_keepunpushedhead2\"}]
157   },
158   {
159     \"CommitDate\":\"$(get_date -0d)\",
160     \"Files\":[
161       {\"Filename\":\"file.dat\",\"Size\":${#content_keepunpushedhead3}, \"Data\":\"$content_keepunpushedhead3\"}]
162   }
163   ]" | lfstest-testutils addcommits
164
165   git config lfs.fetchrecentrefsdays 5
166   git config lfs.fetchrecentremoterefs true
167   git config lfs.fetchrecentcommitsdays 0 # only keep AT refs, no recents
168   git config lfs.pruneoffsetdays 2
169
170   git lfs prune
171
172   # Now push master and show that older versions on master will be removed
173   git push origin master
174
175   git lfs prune --verbose 2>&1 | tee prune.log
176   grep "prune: 6 local object(s), 4 retained" prune.log
177   grep "prune: Deleting objects: 100% (2/2), done" prune.log
178   grep "$oid_keepunpushedhead1" prune.log
179   grep "$oid_keepunpushedhead2" prune.log
180   refute_local_object "$oid_keepunpushedhead1"
181   refute_local_object "$oid_keepunpushedhead2"
182
183   # MERGE the secondary branch, delete the branch then push master, then make sure
184   # we delete the intermediate commits but also make sure they're on server
185   # resolve conflicts by taking other branch
186   git merge -Xtheirs branch_unpushed
187   git branch -D branch_unpushed
188   git lfs prune --dry-run
189   git push origin master
190
191   git lfs prune --verbose 2>&1 | tee prune.log
192   grep "prune: 4 local object(s), 1 retained" prune.log
193   grep "prune: Deleting objects: 100% (3/3), done" prune.log
194   grep "$oid_keepunpushedbranch1" prune.log
195   grep "$oid_keepunpushedbranch2" prune.log
196   grep "$oid_keepunpushedhead3" prune.log
197   refute_local_object "$oid_keepunpushedbranch1"
198   refute_local_object "$oid_keepunpushedbranch2"
199   # we used -Xtheirs so old head state is now obsolete, is the last state on branch
200   refute_local_object "$oid_keepunpushedhead3"
201   assert_server_object "remote_$reponame" "$oid_keepunpushedbranch1"
202   assert_server_object "remote_$reponame" "$oid_keepunpushedbranch2"
203   assert_server_object "remote_$reponame" "$oid_keepunpushedhead3"
204
205 )
206 end_test
207
208 begin_test "prune keep recent"
209 (
210   set -e
211
212   reponame="prune_recent"
213   setup_remote_repo "remote_$reponame"
214
215   clone_repo "remote_$reponame" "clone_$reponame"
216
217   git lfs track "*.dat" 2>&1 | tee track.log
218   grep "Tracking \"\*.dat\"" track.log
219
220   content_keephead="Keep: HEAD"
221   content_keeprecentbranch1tip="Keep: Recent branch 1 tip"
222   content_keeprecentbranch2tip="Keep: Recent branch 2 tip"
223   content_keeprecentcommithead="Keep: Recent commit on HEAD"
224   content_keeprecentcommitbranch1="Keep: Recent commit on recent branch 1"
225   content_keeprecentcommitbranch2="Keep: Recent commit on recent branch 2"
226   content_prunecommitoldbranch1="Prune: old commit on old branch"
227   content_prunecommitoldbranch2="Prune: old branch tip"
228   content_prunecommitbranch1="Prune: old commit on recent branch 1"
229   content_prunecommitbranch2="Prune: old commit on recent branch 2"
230   content_prunecommithead="Prune: old commit on HEAD"
231   oid_keephead=$(calc_oid "$content_keephead")
232   oid_keeprecentbranch1tip=$(calc_oid "$content_keeprecentbranch1tip")
233   oid_keeprecentbranch2tip=$(calc_oid "$content_keeprecentbranch2tip")
234   oid_keeprecentcommithead=$(calc_oid "$content_keeprecentcommithead")
235   oid_keeprecentcommitbranch1=$(calc_oid "$content_keeprecentcommitbranch1")
236   oid_keeprecentcommitbranch2=$(calc_oid "$content_keeprecentcommitbranch2")
237   oid_prunecommitoldbranch=$(calc_oid "$content_prunecommitoldbranch1")
238   oid_prunecommitoldbranch2=$(calc_oid "$content_prunecommitoldbranch2")
239   oid_prunecommitbranch1=$(calc_oid "$content_prunecommitbranch1")
240   oid_prunecommitbranch2=$(calc_oid "$content_prunecommitbranch2")
241   oid_prunecommithead=$(calc_oid "$content_prunecommithead")
242
243
244   # use a single file so each commit supercedes the last, if different files
245   # then history becomes harder to track
246   # Also note that when considering 'recent' when editing a single file, it means
247   # that the snapshot state overlapped; so the latest commit *before* the day
248   # that you're looking at, not just the commits on/after.
249   echo "[
250   {
251     \"CommitDate\":\"$(get_date -50d)\",
252     \"Files\":[
253       {\"Filename\":\"file.dat\",\"Size\":${#content_prunecommithead}, \"Data\":\"$content_prunecommithead\"}]
254   },
255   {
256     \"CommitDate\":\"$(get_date -30d)\",
257     \"Files\":[
258       {\"Filename\":\"file.dat\",\"Size\":${#content_keeprecentcommithead}, \"Data\":\"$content_keeprecentcommithead\"}]
259   },
260   {
261     \"CommitDate\":\"$(get_date -8d)\",
262     \"NewBranch\":\"branch_old\",
263     \"Files\":[
264       {\"Filename\":\"file.dat\",\"Size\":${#content_prunecommitoldbranch1}, \"Data\":\"$content_prunecommitoldbranch1\"}]
265   },
266   {
267     \"CommitDate\":\"$(get_date -7d)\",
268     \"Files\":[
269       {\"Filename\":\"file.dat\",\"Size\":${#content_prunecommitoldbranch2}, \"Data\":\"$content_prunecommitoldbranch2\"}]
270   },
271   {
272     \"CommitDate\":\"$(get_date -9d)\",
273     \"ParentBranches\":[\"master\"],
274     \"NewBranch\":\"branch1\",
275     \"Files\":[
276       {\"Filename\":\"file.dat\",\"Size\":${#content_prunecommitbranch1}, \"Data\":\"$content_prunecommitbranch1\"}]
277   },
278   {
279     \"CommitDate\":\"$(get_date -8d)\",
280     \"Files\":[
281       {\"Filename\":\"file.dat\",\"Size\":${#content_keeprecentcommitbranch1}, \"Data\":\"$content_keeprecentcommitbranch1\"}]
282   },
283   {
284     \"CommitDate\":\"$(get_date -5d)\",
285     \"Files\":[
286       {\"Filename\":\"file.dat\",\"Size\":${#content_keeprecentbranch1tip}, \"Data\":\"$content_keeprecentbranch1tip\"}]
287   },
288   {
289     \"CommitDate\":\"$(get_date -17d)\",
290     \"ParentBranches\":[\"master\"],
291     \"NewBranch\":\"branch2\",
292     \"Files\":[
293       {\"Filename\":\"file.dat\",\"Size\":${#content_prunecommitbranch2}, \"Data\":\"$content_prunecommitbranch2\"}]
294   },
295   {
296     \"CommitDate\":\"$(get_date -10d)\",
297     \"Files\":[
298       {\"Filename\":\"file.dat\",\"Size\":${#content_keeprecentcommitbranch2}, \"Data\":\"$content_keeprecentcommitbranch2\"}]
299   },
300   {
301     \"CommitDate\":\"$(get_date -2d)\",
302     \"Files\":[
303       {\"Filename\":\"file.dat\",\"Size\":${#content_keeprecentbranch2tip}, \"Data\":\"$content_keeprecentbranch2tip\"}]
304   },
305   {
306     \"CommitDate\":\"$(get_date -1d)\",
307     \"ParentBranches\":[\"master\"],
308     \"Files\":[
309       {\"Filename\":\"file.dat\",\"Size\":${#content_keephead}, \"Data\":\"$content_keephead\"}]
310   }
311   ]" | lfstest-testutils addcommits
312
313   # keep refs for 6 days & any prev commit that overlaps 2 days before tip (recent + offset)
314   git config lfs.fetchrecentrefsdays 5
315   git config lfs.fetchrecentremoterefs true
316   git config lfs.fetchrecentcommitsdays 1
317   git config lfs.pruneoffsetdays 1
318
319   # push everything so that's not a reason to retain
320   git push origin master:master branch_old:branch_old branch1:branch1 branch2:branch2
321
322
323   git lfs prune --verbose 2>&1 | tee prune.log
324   grep "prune: 11 local object(s), 6 retained, done" prune.log
325   grep "prune: Deleting objects: 100% (5/5), done" prune.log
326   grep "$oid_prunecommitoldbranch" prune.log
327   grep "$oid_prunecommitoldbranch2" prune.log
328   grep "$oid_prunecommitbranch1" prune.log
329   grep "$oid_prunecommitbranch2" prune.log
330   grep "$oid_prunecommithead" prune.log
331
332   refute_local_object "$oid_prunecommitoldbranch"
333   refute_local_object "$oid_prunecommitoldbranch2"
334   refute_local_object "$oid_prunecommitbranch1"
335   refute_local_object "$oid_prunecommitbranch2"
336   refute_local_object "$oid_prunecommithead"
337   assert_local_object "$oid_keephead" "${#content_keephead}"
338   assert_local_object "$oid_keeprecentbranch1tip" "${#content_keeprecentbranch1tip}"
339   assert_local_object "$oid_keeprecentbranch2tip" "${#content_keeprecentbranch2tip}"
340   assert_local_object "$oid_keeprecentcommithead" "${#content_keeprecentcommithead}"
341   assert_local_object "$oid_keeprecentcommitbranch1" "${#content_keeprecentcommitbranch1}"
342   assert_local_object "$oid_keeprecentcommitbranch2" "${#content_keeprecentcommitbranch2}"
343
344   # now don't include any recent commits in fetch & hence don't retain
345   # still retain tips of branches
346   git config lfs.fetchrecentcommitsdays 0
347   git lfs prune --verbose 2>&1 | tee prune.log
348   grep "prune: 6 local object(s), 3 retained, done" prune.log
349   grep "prune: Deleting objects: 100% (3/3), done" prune.log
350   assert_local_object "$oid_keephead" "${#content_keephead}"
351   assert_local_object "$oid_keeprecentbranch1tip" "${#content_keeprecentbranch1tip}"
352   assert_local_object "$oid_keeprecentbranch2tip" "${#content_keeprecentbranch2tip}"
353   refute_local_object "$oid_keeprecentcommithead"
354   refute_local_object "$oid_keeprecentcommitbranch1"
355   refute_local_object "$oid_keeprecentcommitbranch2"
356
357   # now don't include any recent refs at all, only keep HEAD
358   git config lfs.fetchrecentrefsdays 0
359   git lfs prune --verbose 2>&1 | tee prune.log
360   grep "prune: 3 local object(s), 1 retained, done" prune.log
361   grep "prune: Deleting objects: 100% (2/2), done" prune.log
362   assert_local_object "$oid_keephead" "${#content_keephead}"
363   refute_local_object "$oid_keeprecentbranch1tip"
364   refute_local_object "$oid_keeprecentbranch2tip"
365
366 )
367 end_test
368
369 begin_test "prune remote tests"
370 (
371   set -e
372
373   reponame="prune_no_or_nonorigin_remote"
374   git init "$reponame"
375   cd "$reponame"
376
377   git lfs track "*.dat" 2>&1 | tee track.log
378   grep "Tracking \"\*.dat\"" track.log
379
380   echo "[
381   {
382     \"CommitDate\":\"$(get_date -50d)\",
383     \"Files\":[
384       {\"Filename\":\"file.dat\",\"Size\":30}]
385   },
386   {
387     \"CommitDate\":\"$(get_date -40d)\",
388     \"Files\":[
389       {\"Filename\":\"file.dat\",\"Size\":28}]
390   },
391   {
392     \"CommitDate\":\"$(get_date -35d)\",
393     \"Files\":[
394       {\"Filename\":\"file.dat\",\"Size\":37}]
395   },
396   {
397     \"CommitDate\":\"$(get_date -25d)\",
398     \"Files\":[
399       {\"Filename\":\"file.dat\",\"Size\":42}]
400   }
401   ]" | lfstest-testutils addcommits
402
403   # set no recents so max ability to prune normally
404   git config lfs.fetchrecentrefsdays 0
405   git config lfs.fetchrecentremoterefs true
406   git config lfs.fetchrecentcommitsdays 0
407   git config lfs.pruneoffsetdays 1
408
409   # can never prune with no remote
410   git lfs prune --verbose 2>&1 | tee prune.log
411   grep "prune: 4 local object(s), 4 retained, done" prune.log
412
413
414   # also make sure nothing is pruned when remote is not origin
415   # create 2 remotes, neither of which is called origin & push to both
416   setup_remote_repo "remote1_$reponame"
417   setup_remote_repo "remote2_$reponame"
418   cd "$TRASHDIR/$reponame"
419   git remote add not_origin "$GITSERVER/remote1_$reponame"
420   git push not_origin master
421
422   git lfs prune --verbose 2>&1 | tee prune.log
423   grep "prune: 4 local object(s), 4 retained, done" prune.log
424
425   # now set the prune remote to be not_origin, should now prune
426   # do a dry run so we can also verify
427   git config lfs.pruneremotetocheck not_origin
428
429   git lfs prune --verbose --dry-run 2>&1 | tee prune.log
430   grep "prune: 4 local object(s), 1 retained, done" prune.log
431   grep "prune: 3 file(s) would be pruned" prune.log
432
433
434
435 )
436 end_test
437
438 begin_test "prune verify"
439 (
440   set -e
441
442   reponame="prune_verify"
443   setup_remote_repo "remote_$reponame"
444
445   clone_repo "remote_$reponame" "clone_$reponame"
446
447   git lfs track "*.dat" 2>&1 | tee track.log
448   grep "Tracking \"\*.dat\"" track.log
449
450   content_head="HEAD content"
451   content_commit3="Content for commit 3 (prune)"
452   content_commit2_failverify="Content for commit 2 (prune - fail verify)"
453   content_commit1="Content for commit 1 (prune)"
454   oid_head=$(calc_oid "$content_head")
455   oid_commit3=$(calc_oid "$content_commit3")
456   oid_commit2_failverify=$(calc_oid "$content_commit2_failverify")
457   oid_commit1=$(calc_oid "$content_commit1")
458
459   echo "[
460   {
461     \"CommitDate\":\"$(get_date -50d)\",
462     \"Files\":[
463       {\"Filename\":\"file.dat\",\"Size\":${#content_commit1}, \"Data\":\"$content_commit1\"}]
464   },
465   {
466     \"CommitDate\":\"$(get_date -40d)\",
467     \"Files\":[
468       {\"Filename\":\"file.dat\",\"Size\":${#content_commit2_failverify}, \"Data\":\"$content_commit2_failverify\"}]
469   },
470   {
471     \"CommitDate\":\"$(get_date -35d)\",
472     \"Files\":[
473       {\"Filename\":\"file.dat\",\"Size\":${#content_commit3}, \"Data\":\"$content_commit3\"}]
474   },
475   {
476     \"CommitDate\":\"$(get_date -25d)\",
477     \"Files\":[
478       {\"Filename\":\"file.dat\",\"Size\":${#content_head}, \"Data\":\"$content_head\"}]
479   }
480   ]" | lfstest-testutils addcommits
481
482   # push all so no unpushed reason to not prune
483   git push origin master
484
485   # set no recents so max ability to prune normally
486   git config lfs.fetchrecentrefsdays 0
487   git config lfs.fetchrecentremoterefs true
488   git config lfs.fetchrecentcommitsdays 0
489   git config lfs.pruneoffsetdays 1
490
491   # confirm that it would prune with verify when no issues
492   git lfs prune --dry-run --verify-remote --verbose 2>&1 | tee prune.log
493   grep "prune: 4 local object(s), 1 retained, 3 verified with remote, done" prune.log
494   grep "prune: 3 file(s) would be pruned" prune.log
495   grep "$oid_commit3" prune.log
496   grep "$oid_commit2_failverify" prune.log
497   grep "$oid_commit1" prune.log
498
499   # delete one file on the server to make the verify fail
500   delete_server_object "remote_$reponame" "$oid_commit2_failverify"
501   # this should now fail
502   git lfs prune --verify-remote 2>&1 | tee prune.log
503   grep "prune: 4 local object(s), 1 retained, 2 verified with remote, done" prune.log
504   grep "missing on remote:" prune.log
505   grep "$oid_commit2_failverify" prune.log
506   # Nothing should have been deleted
507   assert_local_object "$oid_commit1" "${#content_commit1}"
508   assert_local_object "$oid_commit2_failverify" "${#content_commit2_failverify}"
509   assert_local_object "$oid_commit3" "${#content_commit3}"
510
511   # Now test with the global option
512   git config lfs.pruneverifyremotealways true
513   # no verify arg but should be pulled from global
514   git lfs prune 2>&1 | tee prune.log
515   grep "prune: 4 local object(s), 1 retained, 2 verified with remote, done" prune.log
516   grep "missing on remote:" prune.log
517   grep "$oid_commit2_failverify" prune.log
518   # Nothing should have been deleted
519   assert_local_object "$oid_commit1" "${#content_commit1}"
520   assert_local_object "$oid_commit2_failverify" "${#content_commit2_failverify}"
521   assert_local_object "$oid_commit3" "${#content_commit3}"
522
523   # now try overriding the global option
524   git lfs prune --no-verify-remote 2>&1 | tee prune.log
525   grep "prune: 4 local object(s), 1 retained, done" prune.log
526   grep "prune: Deleting objects: 100% (3/3), done" prune.log
527   # should now have been deleted
528   refute_local_object "$oid_commit1"
529   refute_local_object "$oid_commit2_failverify"
530   refute_local_object "$oid_commit3"
531
532 )
533 end_test
534
535 begin_test "prune verify large numbers of refs"
536 (
537   set -e
538
539   reponame="prune_verify_large"
540   setup_remote_repo "remote_$reponame"
541
542   clone_repo "remote_$reponame" "clone_$reponame"
543
544   git lfs track "*.dat" 2>&1 | tee track.log
545   grep "Tracking \"\*.dat\"" track.log
546
547   content_head="HEAD content"
548   content_commit1="Recent commit"
549   content_oldcommit="Old content"
550   oid_head=$(calc_oid "$content_head")
551
552   # Add two recent commits that should not be pruned
553   echo "[
554   {
555     \"CommitDate\":\"$(get_date -50d)\",
556     \"Files\":[
557       {\"Filename\":\"file.dat\",\"Size\":${#content_oldcommit}, \"Data\":\"$(uuidgen)\"}]
558   },
559   {
560     \"CommitDate\":\"$(get_date -45d)\",
561     \"Files\":[
562       {\"Filename\":\"file.dat\",\"Size\":${#content_oldcommit}, \"Data\":\"$(uuidgen)\"}]
563   },
564   {
565     \"CommitDate\":\"$(get_date -2d)\",
566     \"Files\":[
567       {\"Filename\":\"file.dat\",\"Size\":${#content_commit1}, \"Data\":\"$content_commit1\"}]
568   },
569   {
570     \"CommitDate\":\"$(get_date -1d)\",
571     \"Files\":[
572       {\"Filename\":\"file.dat\",\"Size\":${#content_head}, \"Data\":\"$content_head\"}]
573   }
574   ]" | lfstest-testutils addcommits
575
576   # Generate a large number of refs to old commits make sure prune has a lot of data to read
577   git checkout $(git log --pretty=oneline  master | tail -2 | awk '{print $1}' | head -1)
578   for i in $(seq 0 1000); do
579     git tag v$i
580   done
581   git checkout master
582
583   # push all so no unpushed reason to not prune
584   # git push origin master
585
586   # set no recents so max ability to prune normally
587   git config lfs.fetchrecentrefsdays 3
588   git config lfs.fetchrecentremoterefs true
589   git config lfs.fetchrecentcommitsdays 3
590   git config lfs.pruneoffsetdays 3
591
592   # confirm that prune does not hang
593   git lfs prune --dry-run --verify-remote --verbose 2>&1 | tee prune.log
594
595 )
596 end_test