(command.CommandList
  children: [
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:test_description)
          op: assign_op.Equal
          rhs: {(SQ <'Clone repositories and store files in Git LFS'>)}
          spids: [4]
        )
      ]
    )
    (C {<.>} {<'./lib-git-p4.sh'>})
    (command.AndOr
      ops: [Id.Op_DPipe]
      children: [
        (command.Simple
          words: [{<git>} {<lfs>} {<help>}]
          redirects: [
            (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<'/dev/null'>})
            (redir op:<Id.Redir_GreatAnd '2>&'> loc:(redir_loc.Fd fd:2) arg:{<1>})
          ]
          do_fork: T
        )
        (BraceGroup
          children: [
            (command.ShAssignment
              pairs: [
                (assign_pair
                  lhs: (sh_lhs_expr.Name name:skip_all)
                  op: assign_op.Equal
                  rhs: {(SQ <'skipping git p4 Git LFS tests; Git LFS not found'>)}
                  spids: [32]
                )
              ]
            )
            (C {<test_done>})
          ]
        )
      ]
    )
    (command.ShFunction
      name: test_file_in_lfs
      body: 
        (BraceGroup
          children: [
            (command.AndOr
              ops: [
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
                Id.Op_DAmp
              ]
              children: [
                (command.ShAssignment
                  pairs: [
                    (assign_pair
                      lhs: (sh_lhs_expr.Name name:FILE)
                      op: assign_op.Equal
                      rhs: {(DQ ($ Id.VSub_Number '$1'))}
                      spids: [51]
                    )
                  ]
                )
                (command.ShAssignment
                  pairs: [
                    (assign_pair
                      lhs: (sh_lhs_expr.Name name:SIZE)
                      op: assign_op.Equal
                      rhs: {(DQ ($ Id.VSub_Number '$2'))}
                      spids: [59]
                    )
                  ]
                )
                (command.ShAssignment
                  pairs: [
                    (assign_pair
                      lhs: (sh_lhs_expr.Name name:EXPECTED_CONTENT)
                      op: assign_op.Equal
                      rhs: {(DQ ($ Id.VSub_Number '$3'))}
                      spids: [67]
                    )
                  ]
                )
                (command.Pipeline
                  children: [
                    (C {<sed>} {<-n>} {(SQ <'1,1 p'>)} {(DQ ($ Id.VSub_DollarName '$FILE'))})
                    (C {<grep>} {(DQ <'^version '>)})
                  ]
                  negated: F
                )
                (command.Pipeline
                  children: [
                    (C {<sed>} {<-n>} {(SQ <'2,2 p'>)} {(DQ ($ Id.VSub_DollarName '$FILE'))})
                    (C {<grep>} {(DQ <'^oid '>)})
                  ]
                  negated: F
                )
                (command.Pipeline
                  children: [
                    (C {<sed>} {<-n>} {(SQ <'3,3 p'>)} {(DQ ($ Id.VSub_DollarName '$FILE'))})
                    (C {<grep>} {(DQ <'^size '>)})
                  ]
                  negated: F
                )
                (C {<test_line_count>} {<Id.Lit_Equals '='>} {<3>} {(DQ ($ Id.VSub_DollarName '$FILE'))})
                (command.Pipeline
                  children: [
                    (C {<cat>} {(DQ ($ Id.VSub_DollarName '$FILE'))})
                    (C {<grep>} {(DQ <'size '> ($ Id.VSub_DollarName '$SIZE'))})
                  ]
                  negated: F
                )
                (command.ShAssignment
                  pairs: [
                    (assign_pair
                      lhs: (sh_lhs_expr.Name name:HASH)
                      op: assign_op.Equal
                      rhs: 
                        {
                          (command_sub
                            left_token: <Id.Left_DollarParen '$('>
                            child: 
                              (command.Pipeline
                                children: [
                                  (C {<cat>} {(DQ ($ Id.VSub_DollarName '$FILE'))})
                                  (C {<grep>} {(DQ <'oid sha256:'>)})
                                  (C {<sed>} {<-e>} {(DQ <'s/oid sha256://g'>)})
                                ]
                                negated: F
                              )
                          )
                        }
                      spids: [175]
                    )
                  ]
                )
                (command.ShAssignment
                  pairs: [
                    (assign_pair
                      lhs: (sh_lhs_expr.Name name:LFS_FILE)
                      op: assign_op.Equal
                      rhs: 
                        {
                          (DQ <'.git/lfs/objects/'> 
                            (command_sub
                              left_token: <Id.Left_DollarParen '$('>
                              child: 
                                (command.Pipeline
                                  children: [
                                    (C {<echo>} {(DQ ($ Id.VSub_DollarName '$HASH'))})
                                    (C {<cut>} {<-c1-2>})
                                  ]
                                  negated: F
                                )
                            ) <'/'> 
                            (command_sub
                              left_token: <Id.Left_DollarParen '$('>
                              child: 
                                (command.Pipeline
                                  children: [
                                    (C {<echo>} {(DQ ($ Id.VSub_DollarName '$HASH'))})
                                    (C {<cut>} {<-c3-4>})
                                  ]
                                  negated: F
                                )
                            ) <'/'> ($ Id.VSub_DollarName '$HASH')
                          )
                        }
                      spids: [205]
                    )
                  ]
                )
                (command.Simple
                  words: [{<echo>} {($ Id.VSub_DollarName '$EXPECTED_CONTENT')}]
                  redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<expect>})]
                  do_fork: T
                )
                (C {<test_path_is_file>} {(DQ ($ Id.VSub_DollarName '$FILE'))})
                (C {<test_path_is_file>} {(DQ ($ Id.VSub_DollarName '$LFS_FILE'))})
                (C {<test_cmp>} {<expect>} {(DQ ($ Id.VSub_DollarName '$LFS_FILE'))})
              ]
            )
          ]
        )
    )
    (command.ShFunction
      name: test_file_count_in_dir
      body: 
        (BraceGroup
          children: [
            (command.AndOr
              ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp]
              children: [
                (command.ShAssignment
                  pairs: [
                    (assign_pair
                      lhs: (sh_lhs_expr.Name name:DIR)
                      op: assign_op.Equal
                      rhs: {(DQ ($ Id.VSub_Number '$1'))}
                      spids: [289]
                    )
                  ]
                )
                (command.ShAssignment
                  pairs: [
                    (assign_pair
                      lhs: (sh_lhs_expr.Name name:EXPECTED_COUNT)
                      op: assign_op.Equal
                      rhs: {(DQ ($ Id.VSub_Number '$2'))}
                      spids: [297]
                    )
                  ]
                )
                (command.Simple
                  words: [{<find>} {(DQ ($ Id.VSub_DollarName '$DIR'))} {<-type>} {<f>}]
                  redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<actual>})]
                  do_fork: T
                )
                (C {<test_line_count>} {<Id.Lit_Equals '='>} {($ Id.VSub_DollarName '$EXPECTED_COUNT')} 
                  {<actual>}
                )
              ]
            )
          ]
        )
    )
    (C {<test_expect_success>} {(SQ <'start p4d'>)} {(SQ <'\n'> <'\tstart_p4d\n'>)})
    (C {<test_expect_success>} {(SQ <'Create repo with binary files'>)} 
      {
        (SQ <'\n'> <'\tclient_view "//depot/... //client/..." &&\n'> <'\t(\n'> <'\t\tcd "$cli" &&\n'> 
          <'\n'> <'\t\techo "content 1 txt 23 bytes" >file1.txt &&\n'> <'\t\tp4 add file1.txt &&\n'> 
          <'\t\techo "content 2-3 bin 25 bytes" >file2.dat &&\n'> <'\t\tp4 add file2.dat &&\n'> <'\t\tp4 submit -d "Add text and binary file" &&\n'> <'\n'> 
          <'\t\tmkdir "path with spaces" &&\n'> <'\t\techo "content 2-3 bin 25 bytes" >"path with spaces/file3.bin" &&\n'> 
          <'\t\tp4 add "path with spaces/file3.bin" &&\n'> <'\t\tp4 submit -d "Add another binary file with same content and spaces in path" &&\n'> <'\n'> 
          <'\t\techo "content 4 bin 26 bytes XX" >file4.bin &&\n'> <'\t\tp4 add file4.bin &&\n'> <'\t\tp4 submit -d "Add another binary file with different content"\n'> 
          <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'Store files in LFS based on size (>24 bytes)'>)} 
      {
        (SQ <'\n'> <'\tclient_view "//depot/... //client/..." &&\n'> 
          <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit init . &&\n'> 
          <'\t\tgit config git-p4.useClientSpec true &&\n'> <'\t\tgit config git-p4.largeFileSystem GitLFS &&\n'> 
          <'\t\tgit config git-p4.largeFileThreshold 24 &&\n'> <'\t\tgit p4 clone --destination="$git" //depot@all &&\n'> <'\n'> 
          <'\t\ttest_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&\n'> <'\t\ttest_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" &&\n'> 
          <'\t\ttest_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" &&\n'> <'\n'> <'\t\ttest_file_count_in_dir ".git/lfs/objects" 2 &&\n'> <'\n'> <'\t\tcat >expect <<-\\EOF &&\n'> 
          <'\n'> <'\t\t#\n'> <'\t\t# Git LFS (see https://git-lfs.github.com/)\n'> <'\t\t#\n'> 
          <'\t\t/file2.dat filter=lfs -text\n'> <'\t\t/file4.bin filter=lfs -text\n'> 
          <'\t\t/path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text\n'> <'\t\tEOF\n'> <'\t\ttest_path_is_file .gitattributes &&\n'> <'\t\ttest_cmp expect .gitattributes\n'> 
          <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'Store files in LFS based on size (>25 bytes)'>)} 
      {
        (SQ <'\n'> <'\tclient_view "//depot/... //client/..." &&\n'> 
          <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit init . &&\n'> 
          <'\t\tgit config git-p4.useClientSpec true &&\n'> <'\t\tgit config git-p4.largeFileSystem GitLFS &&\n'> 
          <'\t\tgit config git-p4.largeFileThreshold 25 &&\n'> <'\t\tgit p4 clone --destination="$git" //depot@all &&\n'> <'\n'> 
          <'\t\ttest_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" &&\n'> <'\t\ttest_file_count_in_dir ".git/lfs/objects" 1 &&\n'> <'\n'> <'\t\tcat >expect <<-\\EOF &&\n'> <'\n'> 
          <'\t\t#\n'> <'\t\t# Git LFS (see https://git-lfs.github.com/)\n'> <'\t\t#\n'> <'\t\t/file4.bin filter=lfs -text\n'> 
          <'\t\tEOF\n'> <'\t\ttest_path_is_file .gitattributes &&\n'> <'\t\ttest_cmp expect .gitattributes\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'Store files in LFS based on extension (dat)'>)} 
      {
        (SQ <'\n'> <'\tclient_view "//depot/... //client/..." &&\n'> 
          <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit init . &&\n'> 
          <'\t\tgit config git-p4.useClientSpec true &&\n'> <'\t\tgit config git-p4.largeFileSystem GitLFS &&\n'> 
          <'\t\tgit config git-p4.largeFileExtensions dat &&\n'> <'\t\tgit p4 clone --destination="$git" //depot@all &&\n'> <'\n'> 
          <'\t\ttest_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&\n'> <'\t\ttest_file_count_in_dir ".git/lfs/objects" 1 &&\n'> <'\n'> <'\t\tcat >expect <<-\\EOF &&\n'> <'\n'> 
          <'\t\t#\n'> <'\t\t# Git LFS (see https://git-lfs.github.com/)\n'> <'\t\t#\n'> <'\t\t*.dat filter=lfs -text\n'> 
          <'\t\tEOF\n'> <'\t\ttest_path_is_file .gitattributes &&\n'> <'\t\ttest_cmp expect .gitattributes\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'Store files in LFS based on size (>25 bytes) and extension (dat)'>)} 
      {
        (SQ <'\n'> <'\tclient_view "//depot/... //client/..." &&\n'> 
          <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit init . &&\n'> 
          <'\t\tgit config git-p4.useClientSpec true &&\n'> <'\t\tgit config git-p4.largeFileSystem GitLFS &&\n'> 
          <'\t\tgit config git-p4.largeFileExtensions dat &&\n'> <'\t\tgit config git-p4.largeFileThreshold 25 &&\n'> 
          <'\t\tgit p4 clone --destination="$git" //depot@all &&\n'> <'\n'> <'\t\ttest_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&\n'> 
          <'\t\ttest_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" &&\n'> <'\t\ttest_file_count_in_dir ".git/lfs/objects" 2 &&\n'> <'\n'> <'\t\tcat >expect <<-\\EOF &&\n'> <'\n'> 
          <'\t\t#\n'> <'\t\t# Git LFS (see https://git-lfs.github.com/)\n'> <'\t\t#\n'> <'\t\t*.dat filter=lfs -text\n'> 
          <'\t\t/file4.bin filter=lfs -text\n'> <'\t\tEOF\n'> <'\t\ttest_path_is_file .gitattributes &&\n'> <'\t\ttest_cmp expect .gitattributes\n'> 
          <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'Remove file from repo and store files in LFS based on size (>24 bytes)'>)} 
      {
        (SQ <'\n'> <'\tclient_view "//depot/... //client/..." &&\n'> <'\t(\n'> <'\t\tcd "$cli" &&\n'> 
          <'\t\tp4 delete file4.bin &&\n'> <'\t\tp4 submit -d "Remove file"\n'> <'\t) &&\n'> <'\n'> 
          <'\tclient_view "//depot/... //client/..." &&\n'> <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit init . &&\n'> 
          <'\t\tgit config git-p4.useClientSpec true &&\n'> <'\t\tgit config git-p4.largeFileSystem GitLFS &&\n'> 
          <'\t\tgit config git-p4.largeFileThreshold 24 &&\n'> <'\t\tgit p4 clone --destination="$git" //depot@all &&\n'> <'\n'> 
          <'\t\ttest_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&\n'> <'\t\ttest_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" &&\n'> 
          <'\t\ttest_path_is_missing file4.bin &&\n'> <'\t\ttest_file_count_in_dir ".git/lfs/objects" 2 &&\n'> <'\n'> <'\t\tcat >expect <<-\\EOF &&\n'> <'\n'> 
          <'\t\t#\n'> <'\t\t# Git LFS (see https://git-lfs.github.com/)\n'> <'\t\t#\n'> <'\t\t/file2.dat filter=lfs -text\n'> 
          <'\t\t/path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text\n'> <'\t\tEOF\n'> <'\t\ttest_path_is_file .gitattributes &&\n'> <'\t\ttest_cmp expect .gitattributes\n'> 
          <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'Add .gitattributes and store files in LFS based on size (>24 bytes)'>)} 
      {
        (SQ <'\n'> <'\tclient_view "//depot/... //client/..." &&\n'> <'\t(\n'> <'\t\tcd "$cli" &&\n'> 
          <'\t\techo "*.txt text" >.gitattributes &&\n'> <'\t\tp4 add .gitattributes &&\n'> <'\t\tp4 submit -d "Add .gitattributes"\n'> <'\t) &&\n'> <'\n'> 
          <'\tclient_view "//depot/... //client/..." &&\n'> <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit init . &&\n'> 
          <'\t\tgit config git-p4.useClientSpec true &&\n'> <'\t\tgit config git-p4.largeFileSystem GitLFS &&\n'> 
          <'\t\tgit config git-p4.largeFileThreshold 24 &&\n'> <'\t\tgit p4 clone --destination="$git" //depot@all &&\n'> <'\n'> 
          <'\t\ttest_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" &&\n'> <'\t\ttest_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" &&\n'> 
          <'\t\ttest_path_is_missing file4.bin &&\n'> <'\t\ttest_file_count_in_dir ".git/lfs/objects" 2 &&\n'> <'\n'> <'\t\tcat >expect <<-\\EOF &&\n'> 
          <'\t\t*.txt text\n'> <'\n'> <'\t\t#\n'> <'\t\t# Git LFS (see https://git-lfs.github.com/)\n'> <'\t\t#\n'> 
          <'\t\t/file2.dat filter=lfs -text\n'> <'\t\t/path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text\n'> <'\t\tEOF\n'> 
          <'\t\ttest_path_is_file .gitattributes &&\n'> <'\t\ttest_cmp expect .gitattributes\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'Add big files to repo and store files in LFS based on compressed size (>28 bytes)'>)} 
      {
        (SQ <'\n'> <'\tclient_view "//depot/... //client/..." &&\n'> <'\t(\n'> <'\t\tcd "$cli" &&\n'> 
          <'\t\techo "content 5 bin 40 bytes XXXXXXXXXXXXXXXX" >file5.bin &&\n'> <'\t\tp4 add file5.bin &&\n'> 
          <'\t\tp4 submit -d "Add file with small footprint after compression" &&\n'> <'\n'> <'\t\techo "content 6 bin 39 bytes XXXXXYYYYYZZZZZ" >file6.bin &&\n'> 
          <'\t\tp4 add file6.bin &&\n'> <'\t\tp4 submit -d "Add file with large footprint after compression"\n'> <'\t) &&\n'> <'\n'> 
          <'\tclient_view "//depot/... //client/..." &&\n'> <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit init . &&\n'> 
          <'\t\tgit config git-p4.useClientSpec true &&\n'> <'\t\tgit config git-p4.largeFileSystem GitLFS &&\n'> 
          <'\t\tgit config git-p4.largeFileCompressedThreshold 28 &&\n'> <'\t\t# We only import HEAD here ("@all" is missing!)\n'> 
          <'\t\tgit p4 clone --destination="$git" //depot &&\n'> <'\n'> <'\t\ttest_file_in_lfs file6.bin 39 "content 6 bin 39 bytes XXXXXYYYYYZZZZZ" &&\n'> 
          <'\t\ttest_file_count_in_dir ".git/lfs/objects" 1 &&\n'> <'\n'> <'\t\tcat >expect <<-\\EOF &&\n'> <'\t\t*.txt text\n'> <'\n'> <'\t\t#\n'> 
          <'\t\t# Git LFS (see https://git-lfs.github.com/)\n'> <'\t\t#\n'> <'\t\t/file6.bin filter=lfs -text\n'> <'\t\tEOF\n'> 
          <'\t\ttest_path_is_file .gitattributes &&\n'> <'\t\ttest_cmp expect .gitattributes\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'kill p4d'>)} {(SQ <'\n'> <'\tkill_p4d\n'>)})
    (C {<test_done>})
  ]
)