(command.CommandList
  children: [
    (command.ShAssignment
      left: <Id.Lit_VarLike 'test_description='>
      pairs: [
        (AssignPair
          left: <Id.Lit_VarLike 'test_description='>
          lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'test_description='> name:test_description)
          op: assign_op.Equal
          rhs: {(SQ <'git p4 preserve users'>)}
        )
      ]
      redirects: []
    )
    (command.Simple
      blame_tok: <.>
      more_env: []
      words: [{<.>} {<'./lib-git-p4.sh'>}]
      redirects: []
      do_fork: T
    )
    (command.Simple
      blame_tok: <test_expect_success>
      more_env: []
      words: [{<test_expect_success>} {(SQ <'start p4d'>)} {(SQ <'\n'> <'\tstart_p4d\n'>)}]
      redirects: []
      do_fork: T
    )
    (command.Simple
      blame_tok: <test_expect_success>
      more_env: []
      words: [
        {<test_expect_success>}
        {(SQ <'create files'>)}
        {
          (SQ <'\n'> <'\t(\n'> <'\t\tcd "$cli" &&\n'> 
            <'\t\tp4 client -o | sed "/LineEnd/s/:.*/:unix/" | p4 client -i &&\n'> <'\t\techo file1 >file1 &&\n'> <'\t\techo file2 >file2 &&\n'> <'\t\tp4 add file1 file2 &&\n'> 
            <'\t\tp4 submit -d "add files"\n'> <'\t)\n'>
          )
        }
      ]
      redirects: []
      do_fork: T
    )
    (command.ShFunction
      name_tok: <p4_grant_admin>
      name: p4_grant_admin
      body: 
        (BraceGroup
          left: <Id.Lit_LBrace '{'>
          children: [
            (command.AndOr
              children: [
                (command.ShAssignment
                  left: <Id.Lit_VarLike 'name='>
                  pairs: [
                    (AssignPair
                      left: <Id.Lit_VarLike 'name='>
                      lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'name='> name:name)
                      op: assign_op.Equal
                      rhs: {($ Id.VSub_Number 1)}
                    )
                  ]
                  redirects: []
                )
                (command.Pipeline
                  children: [
                    (BraceGroup
                      left: <Id.Lit_LBrace '{'>
                      children: [
                        (command.AndOr
                          children: [
                            (command.Simple
                              blame_tok: <p4>
                              more_env: []
                              words: [{<p4>} {<protect>} {<-o>}]
                              redirects: []
                              do_fork: T
                            )
                            (command.Simple
                              blame_tok: <echo>
                              more_env: []
                              words: [
                                {<echo>}
                                {
                                  (DQ <'    admin user '> ($ Id.VSub_DollarName name) 
                                    <' * //depot/...'>
                                  )
                                }
                              ]
                              redirects: []
                              do_fork: T
                            )
                          ]
                          ops: [<Id.Op_DAmp _>]
                        )
                      ]
                      redirects: []
                      right: <Id.Lit_RBrace '}'>
                    )
                    (command.Simple
                      blame_tok: <p4>
                      more_env: []
                      words: [{<p4>} {<protect>} {<-i>}]
                      redirects: []
                      do_fork: T
                    )
                  ]
                  ops: [<Id.Op_Pipe _>]
                )
              ]
              ops: [<Id.Op_DAmp _>]
            )
          ]
          redirects: []
          right: <Id.Lit_RBrace '}'>
        )
    )
    (command.ShFunction
      name_tok: <p4_check_commit_author>
      name: p4_check_commit_author
      body: 
        (BraceGroup
          left: <Id.Lit_LBrace '{'>
          children: [
            (command.AndOr
              children: [
                (command.ShAssignment
                  left: <Id.Lit_VarLike 'file='>
                  pairs: [
                    (AssignPair
                      left: <Id.Lit_VarLike 'file='>
                      lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'file='> name:file)
                      op: assign_op.Equal
                      rhs: {($ Id.VSub_Number 1)}
                    )
                    (AssignPair
                      left: <Id.Lit_VarLike 'user='>
                      lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'user='> name:user)
                      op: assign_op.Equal
                      rhs: {($ Id.VSub_Number 2)}
                    )
                  ]
                  redirects: []
                )
                (command.Pipeline
                  children: [
                    (command.Simple
                      blame_tok: <p4>
                      more_env: []
                      words: [{<p4>} {<changes>} {<-m>} {<1>} {<'//depot/'> ($ Id.VSub_DollarName file)}]
                      redirects: []
                      do_fork: T
                    )
                    (command.Simple
                      blame_tok: <grep>
                      more_env: []
                      words: [{<grep>} {<-q>} {($ Id.VSub_DollarName user)}]
                      redirects: []
                      do_fork: T
                    )
                  ]
                  ops: [<Id.Op_Pipe _>]
                )
              ]
              ops: [<Id.Op_DAmp _>]
            )
          ]
          redirects: []
          right: <Id.Lit_RBrace '}'>
        )
    )
    (command.ShFunction
      name_tok: <make_change_by_user>
      name: make_change_by_user
      body: 
        (BraceGroup
          left: <Id.Lit_LBrace '{'>
          children: [
            (command.AndOr
              children: [
                (command.ShAssignment
                  left: <Id.Lit_VarLike 'file='>
                  pairs: [
                    (AssignPair
                      left: <Id.Lit_VarLike 'file='>
                      lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'file='> name:file)
                      op: assign_op.Equal
                      rhs: {($ Id.VSub_Number 1)}
                    )
                    (AssignPair
                      left: <Id.Lit_VarLike 'name='>
                      lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'name='> name:name)
                      op: assign_op.Equal
                      rhs: {($ Id.VSub_Number 2)}
                    )
                    (AssignPair
                      left: <Id.Lit_VarLike 'email='>
                      lhs: (sh_lhs_expr.Name left:<Id.Lit_VarLike 'email='> name:email)
                      op: assign_op.Equal
                      rhs: {($ Id.VSub_Number 3)}
                    )
                  ]
                  redirects: []
                )
                (command.Simple
                  blame_tok: <echo>
                  more_env: []
                  words: [{<echo>} {(DQ <'username: a change by '> ($ Id.VSub_DollarName name))}]
                  redirects: [
                    (Redir
                      op: <Id.Redir_DGreat '>>'>
                      loc: (redir_loc.Fd fd:1)
                      arg: {(DQ ($ Id.VSub_DollarName file))}
                    )
                  ]
                  do_fork: T
                )
                (command.Simple
                  blame_tok: <git>
                  more_env: []
                  words: [{<git>} {<add>} {(DQ ($ Id.VSub_DollarName file))}]
                  redirects: []
                  do_fork: T
                )
                (command.Simple
                  blame_tok: <git>
                  more_env: []
                  words: [
                    {<git>}
                    {<commit>}
                    {<--author>}
                    {(DQ ($ Id.VSub_DollarName name) <' <'> ($ Id.VSub_DollarName email) <'>'>)}
                    {<-m>}
                    {(DQ <'a change by '> ($ Id.VSub_DollarName name))}
                  ]
                  redirects: []
                  do_fork: T
                )
              ]
              ops: [<Id.Op_DAmp _> <Id.Op_DAmp _> <Id.Op_DAmp _>]
            )
          ]
          redirects: []
          right: <Id.Lit_RBrace '}'>
        )
    )
    (command.Simple
      blame_tok: <test_expect_success>
      more_env: []
      words: [
        {<test_expect_success>}
        {(SQ <'preserve users'>)}
        {
          (SQ <'\n'> <'\tp4_add_user alice &&\n'> <'\tp4_add_user bob &&\n'> 
            <'\tp4_grant_admin alice &&\n'> <'\tgit p4 clone --dest="$git" //depot &&\n'> <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> 
            <'\t\tcd "$git" &&\n'> <'\t\techo "username: a change by alice" >>file1 &&\n'> 
            <'\t\techo "username: a change by bob" >>file2 &&\n'> <'\t\tgit commit --author "Alice <alice@example.com>" -m "a change by alice" file1 &&\n'> 
            <'\t\tgit commit --author "Bob <bob@example.com>" -m "a change by bob" file2 &&\n'> <'\t\tgit config git-p4.skipSubmitEditCheck true &&\n'> 
            <'\t\tP4EDITOR="test-chmtime +5" P4USER=alice P4PASSWD=secret &&\n'> <'\t\texport P4EDITOR P4USER P4PASSWD &&\n'> <'\t\tgit p4 commit --preserve-user &&\n'> 
            <'\t\tp4_check_commit_author file1 alice &&\n'> <'\t\tp4_check_commit_author file2 bob\n'> <'\t)\n'>
          )
        }
      ]
      redirects: []
      do_fork: T
    )
    (command.Simple
      blame_tok: <test_expect_success>
      more_env: []
      words: [
        {<test_expect_success>}
        {(SQ <'refuse to preserve users without perms'>)}
        {
          (SQ <'\n'> <'\tgit p4 clone --dest="$git" //depot &&\n'> 
            <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit config git-p4.skipSubmitEditCheck true &&\n'> 
            <'\t\techo "username-noperms: a change by alice" >>file1 &&\n'> <'\t\tgit commit --author "Alice <alice@example.com>" -m "perms: a change by alice" file1 &&\n'> 
            <'\t\tP4EDITOR="test-chmtime +5" P4USER=bob P4PASSWD=secret &&\n'> <'\t\texport P4EDITOR P4USER P4PASSWD &&\n'> <'\t\ttest_must_fail git p4 commit --preserve-user &&\n'> 
            <'\t\t! git diff --exit-code HEAD..p4/master\n'> <'\t)\n'>
          )
        }
      ]
      redirects: []
      do_fork: T
    )
    (command.Simple
      blame_tok: <test_expect_success>
      more_env: []
      words: [
        {<test_expect_success>}
        {(SQ <'preserve user where author is unknown to p4'>)}
        {
          (SQ <'\n'> <'\tgit p4 clone --dest="$git" //depot &&\n'> 
            <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit config git-p4.skipSubmitEditCheck true &&\n'> 
            <'\t\techo "username-bob: a change by bob" >>file1 &&\n'> <'\t\tgit commit --author "Bob <bob@example.com>" -m "preserve: a change by bob" file1 &&\n'> 
            <'\t\techo "username-unknown: a change by charlie" >>file1 &&\n'> 
            <
'\t\tgit commit --author "Charlie <charlie@example.com>" -m "preserve: a change by charlie" file1 &&\n'
            > <'\t\tP4EDITOR="test-chmtime +5" P4USER=alice P4PASSWD=secret &&\n'> 
            <'\t\texport P4EDITOR P4USER P4PASSWD &&\n'> <'\t\ttest_must_fail git p4 commit --preserve-user &&\n'> 
            <'\t\t! git diff --exit-code HEAD..p4/master &&\n'> <'\n'> <'\t\techo "$0: repeat with allowMissingP4Users enabled" &&\n'> 
            <'\t\tgit config git-p4.allowMissingP4Users true &&\n'> <'\t\tgit config git-p4.preserveUser true &&\n'> <'\t\tgit p4 commit &&\n'> 
            <'\t\tgit diff --exit-code HEAD..p4/master &&\n'> <'\t\tp4_check_commit_author file1 alice\n'> <'\t)\n'>
          )
        }
      ]
      redirects: []
      do_fork: T
    )
    (command.Simple
      blame_tok: <test_expect_success>
      more_env: []
      words: [
        {<test_expect_success>}
        {(SQ <'not preserving user with mixed authorship'>)}
        {
          (SQ <'\n'> <'\tgit p4 clone --dest="$git" //depot &&\n'> 
            <'\ttest_when_finished cleanup_git &&\n'> <'\t(\n'> <'\t\tcd "$git" &&\n'> <'\t\tgit config git-p4.skipSubmitEditCheck true &&\n'> 
            <'\t\tp4_add_user derek &&\n'> <'\n'> <'\t\tmake_change_by_user usernamefile3 Derek derek@example.com &&\n'> 
            <'\t\tP4EDITOR=cat P4USER=alice P4PASSWD=secret &&\n'> <'\t\texport P4EDITOR P4USER P4PASSWD &&\n'> <'\t\tgit p4 commit |\\\n'> 
            <'\t\tgrep "git author derek@example.com does not match" &&\n'> <'\n'> <'\t\tmake_change_by_user usernamefile3 Charlie charlie@example.com &&\n'> 
            <'\t\tgit p4 commit |\\\n'> <'\t\tgrep "git author charlie@example.com does not match" &&\n'> <'\n'> 
            <'\t\tmake_change_by_user usernamefile3 alice alice@example.com &&\n'> <'\t\tgit p4 commit |\\\n'> <'\t\ttest_must_fail grep "git author.*does not match" &&\n'> <'\n'> 
            <'\t\tgit config git-p4.skipUserNameCheck true &&\n'> <'\t\tmake_change_by_user usernamefile3 Charlie charlie@example.com &&\n'> <'\t\tgit p4 commit |\\\n'> 
            <'\t\ttest_must_fail grep "git author.*does not match" &&\n'> <'\n'> <'\t\tp4_check_commit_author usernamefile3 alice\n'> <'\t)\n'>
          )
        }
      ]
      redirects: []
      do_fork: T
    )
    (command.Simple
      blame_tok: <test_expect_success>
      more_env: []
      words: [{<test_expect_success>} {(SQ <'kill p4d'>)} {(SQ <'\n'> <'\tkill_p4d\n'>)}]
      redirects: []
      do_fork: T
    )
    (command.Simple
      blame_tok: <test_done>
      more_env: []
      words: [{<test_done>}]
      redirects: []
      do_fork: T
    )
  ]
)