github.com/git-lfs/git-lfs@v2.5.2+incompatible/t/t-prune.sh (about)

     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