(CommandList
  children: [
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:test_description)
          op: Equal
          rhs: {(SQ <"git p4 preserve users">)}
          spids: [4]
        )
      ]
      spids: [4]
    )
    (C {(.)} {(./lib-git-p4.sh)})
    (C {(test_expect_success)} {(SQ <"start p4d">)} {(SQ <"\n"> <"\tstart_p4d\n">)})
    (C {(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">
        )
      }
    )
    (FuncDef
      name: p4_grant_admin
      body: 
        (BraceGroup
          children: [
            (AndOr
              children: [
                (Assignment
                  keyword: Assign_None
                  pairs: [
                    (assign_pair
                      lhs: (LhsName name:name)
                      op: Equal
                      rhs: {($ VSub_Number "$1")}
                      spids: [53]
                    )
                  ]
                  spids: [53]
                )
                (Pipeline
                  children: [
                    (BraceGroup
                      children: [
                        (AndOr
                          children: [
                            (C {(p4)} {(protect)} {(-o)})
                            (C {(echo)} 
                              {(DQ ("    admin user ") ($ VSub_Name "$name") (" * //depot/..."))}
                            )
                          ]
                          op_id: Op_DAmp
                        )
                      ]
                      spids: [59]
                    )
                    (C {(p4)} {(protect)} {(-i)})
                  ]
                  negated: False
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [50]
        )
      spids: [46 49]
    )
    (FuncDef
      name: p4_check_commit_author
      body: 
        (BraceGroup
          children: [
            (AndOr
              children: [
                (Assignment
                  keyword: Assign_None
                  pairs: [
                    (assign_pair
                      lhs: (LhsName name:file)
                      op: Equal
                      rhs: {($ VSub_Number "$1")}
                      spids: [100]
                    )
                    (assign_pair
                      lhs: (LhsName name:user)
                      op: Equal
                      rhs: {($ VSub_Number "$2")}
                      spids: [103]
                    )
                  ]
                  spids: [100]
                )
                (Pipeline
                  children: [
                    (C {(p4)} {(changes)} {(-m)} {(1)} {(//depot/) ($ VSub_Name "$file")})
                    (C {(grep)} {(-q)} {($ VSub_Name "$user")})
                  ]
                  negated: False
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [97]
        )
      spids: [93 96]
    )
    (FuncDef
      name: make_change_by_user
      body: 
        (BraceGroup
          children: [
            (AndOr
              children: [
                (Assignment
                  keyword: Assign_None
                  pairs: [
                    (assign_pair
                      lhs: (LhsName name:file)
                      op: Equal
                      rhs: {($ VSub_Number "$1")}
                      spids: [138]
                    )
                    (assign_pair
                      lhs: (LhsName name:name)
                      op: Equal
                      rhs: {($ VSub_Number "$2")}
                      spids: [141]
                    )
                    (assign_pair
                      lhs: (LhsName name:email)
                      op: Equal
                      rhs: {($ VSub_Number "$3")}
                      spids: [144]
                    )
                  ]
                  spids: [138]
                )
                (AndOr
                  children: [
                    (SimpleCommand
                      words: [{(echo)} {(DQ ("username: a change by ") ($ VSub_Name "$name"))}]
                      redirects: [
                        (Redir
                          op_id: Redir_DGreat
                          fd: -1
                          arg_word: {(DQ ($ VSub_Name "$file"))}
                          spids: [157]
                        )
                      ]
                    )
                    (AndOr
                      children: [
                        (C {(git)} {(add)} {(DQ ($ VSub_Name "$file"))})
                        (C {(git)} {(commit)} {(--author)} 
                          {(DQ ($ VSub_Name "$name") (" <") ($ VSub_Name "$email") (">"))} {(-m)} {(DQ ("a change by ") ($ VSub_Name "$name"))}
                        )
                      ]
                      op_id: Op_DAmp
                    )
                  ]
                  op_id: Op_DAmp
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [135]
        )
      spids: [131 134]
    )
    (C {(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">
        )
      }
    )
    (C {(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">
        )
      }
    )
    (C {(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">
        )
      }
    )
    (C {(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">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"kill p4d">)} {(SQ <"\n"> <"\tkill_p4d\n">)})
    (C {(test_done)})
  ]
)