(CommandList
  children: [
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:test_description)
          op: Equal
          rhs: {(SQ <prune>)}
          spids: [13]
        )
      ]
      spids: [13]
    )
    (C {(.)} {(./test-lib.sh)})
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:day)
          op: Equal
          rhs: 
            {
              (ArithSubPart
                anode: 
                  (ArithBinary
                    op_id: Arith_Star
                    left: 
                      (ArithBinary
                        op_id: Arith_Star
                        left: (ArithWord w:{(Lit_Digits 60)})
                        right: (ArithWord w:{(Lit_Digits 60)})
                      )
                    right: (ArithWord w:{(Lit_Digits 24)})
                  )
                spids: [24 31]
              )
            }
          spids: [23]
        )
      ]
      spids: [23]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:week)
          op: Equal
          rhs: 
            {
              (ArithSubPart
                anode: 
                  (ArithBinary
                    op_id: Arith_Star
                    left: (ArithWord w:{($ VSub_Name "$day")})
                    right: (ArithWord w:{(Lit_Digits 7)})
                  )
                spids: [34 39]
              )
            }
          spids: [33]
        )
      ]
      spids: [33]
    )
    (FuncDef
      name: add_blob
      body: 
        (BraceGroup
          children: [
            (AndOr
              children: [
                (Assignment
                  keyword: Assign_None
                  pairs: [
                    (assign_pair
                      lhs: (LhsName name:before)
                      op: Equal
                      rhs: 
                        {
                          (CommandSubPart
                            command_list: 
                              (CommandList
                                children: [
                                  (Pipeline
                                    children: [
                                      (C {(git)} {(count-objects)})
                                      (C {(sed)} {(DQ ("s/ .*//"))})
                                    ]
                                    negated: False
                                  )
                                ]
                              )
                            left_token: <Left_CommandSub "$(">
                            spids: [50 62]
                          )
                        }
                      spids: [49]
                    )
                  ]
                  spids: [49]
                )
                (AndOr
                  children: [
                    (Assignment
                      keyword: Assign_None
                      pairs: [
                        (assign_pair
                          lhs: (LhsName name:BLOB)
                          op: Equal
                          rhs: 
                            {
                              (CommandSubPart
                                command_list: 
                                  (CommandList
                                    children: [
                                      (Pipeline
                                        children: [
                                          (C {(echo)} {(aleph_0)})
                                          (C {(git)} {(hash-object)} {(-w)} {(--stdin)})
                                        ]
                                        negated: False
                                      )
                                    ]
                                  )
                                left_token: <Left_CommandSub "$(">
                                spids: [68 82]
                              )
                            }
                          spids: [67]
                        )
                      ]
                      spids: [67]
                    )
                    (AndOr
                      children: [
                        (Assignment
                          keyword: Assign_None
                          pairs: [
                            (assign_pair
                              lhs: (LhsName name:BLOB_FILE)
                              op: Equal
                              rhs: 
                                {(.git/objects/) 
                                  (CommandSubPart
                                    command_list: 
                                      (CommandList
                                        children: [
                                          (Pipeline
                                            children: [
                                              (C {(echo)} {($ VSub_Name "$BLOB")})
                                              (C {(sed)} 
                                                {
                                                  (DQ ("s/^../&") 
                                                    (EscapedLiteralPart
                                                      token: <Lit_EscapedChar "\\/">
                                                    ) (/)
                                                  )
                                                }
                                              )
                                            ]
                                            negated: False
                                          )
                                        ]
                                      )
                                    left_token: <Left_CommandSub "$(">
                                    spids: [89 103]
                                  )
                                }
                              spids: [87]
                            )
                          ]
                          spids: [87]
                        )
                        (AndOr
                          children: [
                            (C {(verbose)} {(test)} 
                              {
                                (ArithSubPart
                                  anode: 
                                    (ArithBinary
                                      op_id: Arith_Plus
                                      left: (ArithWord w:{(Lit_Digits 1)})
                                      right: (ArithWord w:{($ VSub_Name "$before")})
                                    )
                                  spids: [112 119]
                                )
                              } {(Lit_Other "=")} 
                              {
                                (CommandSubPart
                                  command_list: 
                                    (CommandList
                                      children: [
                                        (Pipeline
                                          children: [
                                            (C {(git)} {(count-objects)})
                                            (C {(sed)} {(DQ ("s/ .*//"))})
                                          ]
                                          negated: False
                                        )
                                      ]
                                    )
                                  left_token: <Left_CommandSub "$(">
                                  spids: [123 135]
                                )
                              }
                            )
                            (AndOr
                              children: [
                                (C {(test_path_is_file)} {($ VSub_Name "$BLOB_FILE")})
                                (C {(test-chmtime)} {(Lit_Other "=") (Lit_Other "+") (0)} 
                                  {($ VSub_Name "$BLOB_FILE")}
                                )
                              ]
                              op_id: Op_DAmp
                            )
                          ]
                          op_id: Op_DAmp
                        )
                      ]
                      op_id: Op_DAmp
                    )
                  ]
                  op_id: Op_DAmp
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [46]
        )
      spids: [42 45]
    )
    (C {(test_expect_success)} {(setup)} 
      {
        (SQ <"\n"> <"\n"> <"\t: > file &&\n"> <"\tgit add file &&\n"> <"\ttest_tick &&\n"> 
          <"\tgit commit -m initial &&\n"> <"\tgit gc\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prune stale packs">)} 
      {
        (SQ <"\n"> <"\n"> <"\torig_pack=$(echo .git/objects/pack/*.pack) &&\n"> 
          <"\t: > .git/objects/tmp_1.pack &&\n"> <"\t: > .git/objects/tmp_2.pack &&\n"> <"\ttest-chmtime =-86501 .git/objects/tmp_1.pack &&\n"> 
          <"\tgit prune --expire 1.day &&\n"> <"\ttest_path_is_file $orig_pack &&\n"> <"\ttest_path_is_file .git/objects/tmp_2.pack &&\n"> 
          <"\ttest_path_is_missing .git/objects/tmp_1.pack\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prune --expire">)} 
      {
        (SQ <"\n"> <"\n"> <"\tadd_blob &&\n"> <"\tgit prune --expire=1.hour.ago &&\n"> 
          <"\tverbose test $((1 + $before)) = $(git count-objects | sed \"s/ .*//\") &&\n"> <"\ttest_path_is_file $BLOB_FILE &&\n"> <"\ttest-chmtime =-86500 $BLOB_FILE &&\n"> 
          <"\tgit prune --expire 1.day &&\n"> <"\tverbose test $before = $(git count-objects | sed \"s/ .*//\") &&\n"> 
          <"\ttest_path_is_missing $BLOB_FILE\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"gc: implicit prune --expire">)} 
      {
        (SQ <"\n"> <"\n"> <"\tadd_blob &&\n"> <"\ttest-chmtime =-$((2*$week-30)) $BLOB_FILE &&\n"> 
          <"\tgit gc &&\n"> <"\tverbose test $((1 + $before)) = $(git count-objects | sed \"s/ .*//\") &&\n"> 
          <"\ttest_path_is_file $BLOB_FILE &&\n"> <"\ttest-chmtime =-$((2*$week+1)) $BLOB_FILE &&\n"> <"\tgit gc &&\n"> 
          <"\tverbose test $before = $(git count-objects | sed \"s/ .*//\") &&\n"> <"\ttest_path_is_missing $BLOB_FILE\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"gc: refuse to start with invalid gc.pruneExpire">)} 
      {
        (SQ <"\n"> <"\n"> <"\tgit config gc.pruneExpire invalid &&\n"> <"\ttest_must_fail git gc\n"> 
          <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"gc: start with ok gc.pruneExpire">)} 
      {(SQ <"\n"> <"\n"> <"\tgit config gc.pruneExpire 2.days.ago &&\n"> <"\tgit gc\n"> <"\n">)}
    )
    (C {(test_expect_success)} {(SQ <"prune: prune nonsense parameters">)} 
      {
        (SQ <"\n"> <"\n"> <"\ttest_must_fail git prune garbage &&\n"> 
          <"\ttest_must_fail git prune --- &&\n"> <"\ttest_must_fail git prune --no-such-option\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prune: prune unreachable heads">)} 
      {
        (SQ <"\n"> <"\n"> <"\tgit config core.logAllRefUpdates false &&\n"> 
          <"\tmv .git/logs .git/logs.old &&\n"> <"\t: > file2 &&\n"> <"\tgit add file2 &&\n"> <"\tgit commit -m temporary &&\n"> 
          <"\ttmp_head=$(git rev-list -1 HEAD) &&\n"> <"\tgit reset HEAD^ &&\n"> <"\tgit prune &&\n"> <"\ttest_must_fail git reset $tmp_head --\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prune: do not prune detached HEAD with no reflog">)} 
      {
        (SQ <"\n"> <"\n"> <"\tgit checkout --detach --quiet &&\n"> 
          <"\tgit commit --allow-empty -m \"detached commit\" &&\n"> <"\t# verify that there is no reflogs\n"> <"\t# (should be removed and disabled by previous test)\n"> 
          <"\ttest_path_is_missing .git/logs &&\n"> <"\tgit prune -n >prune_actual &&\n"> <"\t: >prune_expected &&\n"> 
          <"\ttest_cmp prune_actual prune_expected\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prune: prune former HEAD after checking out branch">)} 
      {
        (SQ <"\n"> <"\n"> <"\thead_sha1=$(git rev-parse HEAD) &&\n"> 
          <"\tgit checkout --quiet master &&\n"> <"\tgit prune -v >prune_actual &&\n"> <"\tgrep \"$head_sha1\" prune_actual\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prune: do not prune heads listed as an argument">)} 
      {
        (SQ <"\n"> <"\n"> <"\t: > file2 &&\n"> <"\tgit add file2 &&\n"> 
          <"\tgit commit -m temporary &&\n"> <"\ttmp_head=$(git rev-list -1 HEAD) &&\n"> <"\tgit reset HEAD^ &&\n"> 
          <"\tgit prune -- $tmp_head &&\n"> <"\tgit reset $tmp_head --\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"gc --no-prune">)} 
      {
        (SQ <"\n"> <"\n"> <"\tadd_blob &&\n"> <"\ttest-chmtime =-$((5001*$day)) $BLOB_FILE &&\n"> 
          <"\tgit config gc.pruneExpire 2.days.ago &&\n"> <"\tgit gc --no-prune &&\n"> <"\tverbose test 1 = $(git count-objects | sed \"s/ .*//\") &&\n"> 
          <"\ttest_path_is_file $BLOB_FILE\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"gc respects gc.pruneExpire">)} 
      {
        (SQ <"\n"> <"\n"> <"\tgit config gc.pruneExpire 5002.days.ago &&\n"> <"\tgit gc &&\n"> 
          <"\ttest_path_is_file $BLOB_FILE &&\n"> <"\tgit config gc.pruneExpire 5000.days.ago &&\n"> <"\tgit gc &&\n"> 
          <"\ttest_path_is_missing $BLOB_FILE\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"gc --prune=<date>">)} 
      {
        (SQ <"\n"> <"\n"> <"\tadd_blob &&\n"> <"\ttest-chmtime =-$((5001*$day)) $BLOB_FILE &&\n"> 
          <"\tgit gc --prune=5002.days.ago &&\n"> <"\ttest_path_is_file $BLOB_FILE &&\n"> <"\tgit gc --prune=5000.days.ago &&\n"> 
          <"\ttest_path_is_missing $BLOB_FILE\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"gc --prune=never">)} 
      {
        (SQ <"\n"> <"\n"> <"\tadd_blob &&\n"> <"\tgit gc --prune=never &&\n"> 
          <"\ttest_path_is_file $BLOB_FILE &&\n"> <"\tgit gc --prune=now &&\n"> <"\ttest_path_is_missing $BLOB_FILE\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"gc respects gc.pruneExpire=never">)} 
      {
        (SQ <"\n"> <"\n"> <"\tgit config gc.pruneExpire never &&\n"> <"\tadd_blob &&\n"> 
          <"\tgit gc &&\n"> <"\ttest_path_is_file $BLOB_FILE &&\n"> <"\tgit config gc.pruneExpire now &&\n"> <"\tgit gc &&\n"> 
          <"\ttest_path_is_missing $BLOB_FILE\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prune --expire=never">)} 
      {
        (SQ <"\n"> <"\n"> <"\tadd_blob &&\n"> <"\tgit prune --expire=never &&\n"> 
          <"\ttest_path_is_file $BLOB_FILE &&\n"> <"\tgit prune &&\n"> <"\ttest_path_is_missing $BLOB_FILE\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"gc: prune old objects after local clone">)} 
      {
        (SQ <"\n"> <"\tadd_blob &&\n"> <"\ttest-chmtime =-$((2*$week+1)) $BLOB_FILE &&\n"> 
          <"\tgit clone --no-hardlinks . aclone &&\n"> <"\t(\n"> <"\t\tcd aclone &&\n"> <"\t\tverbose test 1 = $(git count-objects | sed \"s/ .*//\") &&\n"> 
          <"\t\ttest_path_is_file $BLOB_FILE &&\n"> <"\t\tgit gc --prune &&\n"> <"\t\tverbose test 0 = $(git count-objects | sed \"s/ .*//\") &&\n"> 
          <"\t\ttest_path_is_missing $BLOB_FILE\n"> <"\t)\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"garbage report in count-objects -v">)} 
      {
        (SQ <"\n"> <"\ttest_when_finished \"rm -f .git/objects/pack/fake*\" &&\n"> 
          <"\ttest_when_finished \"rm -f .git/objects/pack/foo*\" &&\n"> <"\t: >.git/objects/pack/foo &&\n"> <"\t: >.git/objects/pack/foo.bar &&\n"> 
          <"\t: >.git/objects/pack/foo.keep &&\n"> <"\t: >.git/objects/pack/foo.pack &&\n"> <"\t: >.git/objects/pack/fake.bar &&\n"> 
          <"\t: >.git/objects/pack/fake.keep &&\n"> <"\t: >.git/objects/pack/fake.pack &&\n"> <"\t: >.git/objects/pack/fake.idx &&\n"> 
          <"\t: >.git/objects/pack/fake2.keep &&\n"> <"\t: >.git/objects/pack/fake3.idx &&\n"> <"\tgit count-objects -v 2>stderr &&\n"> 
          <"\tgrep \"index file .git/objects/pack/fake.idx is too small\" stderr &&\n"> <"\tgrep \"^warning:\" stderr | sort >actual &&\n"> <"\tcat >expected <<\\EOF &&\n"> 
          <"warning: garbage found: .git/objects/pack/fake.bar\n"> <"warning: garbage found: .git/objects/pack/foo\n"> 
          <"warning: garbage found: .git/objects/pack/foo.bar\n"> <"warning: no corresponding .idx or .pack: .git/objects/pack/fake2.keep\n"> 
          <"warning: no corresponding .idx: .git/objects/pack/foo.keep\n"> <"warning: no corresponding .idx: .git/objects/pack/foo.pack\n"> 
          <"warning: no corresponding .pack: .git/objects/pack/fake3.idx\n"> <"EOF\n"> <"\ttest_cmp expected actual\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"clean pack garbage with gc">)} 
      {
        (SQ <"\n"> <"\ttest_when_finished \"rm -f .git/objects/pack/fake*\" &&\n"> 
          <"\ttest_when_finished \"rm -f .git/objects/pack/foo*\" &&\n"> <"\t: >.git/objects/pack/foo.keep &&\n"> <"\t: >.git/objects/pack/foo.pack &&\n"> 
          <"\t: >.git/objects/pack/fake.idx &&\n"> <"\t: >.git/objects/pack/fake2.keep &&\n"> <"\t: >.git/objects/pack/fake2.idx &&\n"> 
          <"\t: >.git/objects/pack/fake3.keep &&\n"> <"\tgit gc &&\n"> <"\tgit count-objects -v 2>stderr &&\n"> 
          <"\tgrep \"^warning:\" stderr | sort >actual &&\n"> <"\tcat >expected <<\\EOF &&\n"> 
          <"warning: no corresponding .idx or .pack: .git/objects/pack/fake3.keep\n"> <"warning: no corresponding .idx: .git/objects/pack/foo.keep\n"> 
          <"warning: no corresponding .idx: .git/objects/pack/foo.pack\n"> <"EOF\n"> <"\ttest_cmp expected actual\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prune .git/shallow">)} 
      {
        (SQ <"\n"> <"\tSHA1=$(echo hi|git commit-tree HEAD^{tree}) &&\n"> 
          <"\techo $SHA1 >.git/shallow &&\n"> <"\tgit prune --dry-run >out &&\n"> <"\tgrep $SHA1 .git/shallow &&\n"> <"\tgrep $SHA1 out &&\n"> 
          <"\tgit prune &&\n"> <"\ttest_path_is_missing .git/shallow\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prune: handle alternate object database">)} 
      {
        (SQ <"\n"> <"\ttest_create_repo A &&\n"> 
          <"\tgit -C A commit --allow-empty -m \"initial commit\" &&\n"> <"\tgit clone --shared A B &&\n"> <"\tgit -C B commit --allow-empty -m \"next commit\" &&\n"> 
          <"\tgit -C B prune\n">
        )
      }
    )
    (C {(test_done)})
  ]
)