(command.CommandList
  children: [
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:test_description)
          op: assign_op.Equal
          rhs: {(SQ <'push with --set-upstream'>)}
          spids: [4]
        )
      ]
    )
    (C {<.>} {<'./test-lib.sh'>})
    (C {<.>} {(DQ ($ Id.VSub_DollarName '$TEST_DIRECTORY')) <'/lib-terminal.sh'>})
    (command.ShFunction
      name: ensure_fresh_upstream
      body: 
        (BraceGroup
          children: [
            (command.AndOr
              ops: [Id.Op_DAmp]
              children: [(C {<rm>} {<-rf>} {<parent>}) (C {<git>} {<init>} {<--bare>} {<parent>})]
            )
          ]
        )
    )
    (C {<test_expect_success>} {(SQ <'setup bare parent'>)} 
      {(SQ <'\n'> <'\tensure_fresh_upstream &&\n'> <'\tgit remote add upstream parent\n'>)}
    )
    (C {<test_expect_success>} {(SQ <'setup local commit'>)} 
      {(SQ <'\n'> <'\techo content >file &&\n'> <'\tgit add file &&\n'> <'\tgit commit -m one\n'>)}
    )
    (command.ShFunction
      name: check_config
      body: 
        (BraceGroup
          children: [
            (command.Subshell
              child: 
                (command.CommandList
                  children: [
                    (command.Sentence
                      child: (C {<echo>} {($ Id.VSub_Number '$2')})
                      terminator: <Id.Op_Semi _>
                    )
                    (C {<echo>} {($ Id.VSub_Number '$3')})
                  ]
                )
              redirects: [
                (redir
                  op: <Id.Redir_Great '>'>
                  loc: (redir_loc.Fd fd:1)
                  arg: {<expect.> ($ Id.VSub_Number '$1')}
                )
              ]
            )
            (command.Subshell
              child: 
                (command.CommandList
                  children: [
                    (C {<git>} {<config>} {<branch.> ($ Id.VSub_Number '$1') <.remote>})
                    (C {<git>} {<config>} {<branch.> ($ Id.VSub_Number '$1') <.merge>})
                  ]
                )
              redirects: [
                (redir
                  op: <Id.Redir_Great '>'>
                  loc: (redir_loc.Fd fd:1)
                  arg: {<actual.> ($ Id.VSub_Number '$1')}
                )
              ]
            )
            (C {<test_cmp>} {<expect.> ($ Id.VSub_Number '$1')} {<actual.> ($ Id.VSub_Number '$1')})
          ]
        )
    )
    (C {<test_expect_success>} {(SQ <'push -u master:master'>)} 
      {
        (SQ <'\n'> <'\tgit push -u upstream master:master &&\n'> 
          <'\tcheck_config master upstream refs/heads/master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push -u master:other'>)} 
      {
        (SQ <'\n'> <'\tgit push -u upstream master:other &&\n'> 
          <'\tcheck_config master upstream refs/heads/other\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push -u --dry-run master:otherX'>)} 
      {
        (SQ <'\n'> <'\tgit push -u --dry-run upstream master:otherX &&\n'> 
          <'\tcheck_config master upstream refs/heads/other\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push -u master2:master2'>)} 
      {
        (SQ <'\n'> <'\tgit branch master2 &&\n'> <'\tgit push -u upstream master2:master2 &&\n'> 
          <'\tcheck_config master2 upstream refs/heads/master2\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push -u master2:other2'>)} 
      {
        (SQ <'\n'> <'\tgit push -u upstream master2:other2 &&\n'> 
          <'\tcheck_config master2 upstream refs/heads/other2\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push -u :master2'>)} 
      {
        (SQ <'\n'> <'\tgit push -u upstream :master2 &&\n'> 
          <'\tcheck_config master2 upstream refs/heads/other2\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push -u --all'>)} 
      {
        (SQ <'\n'> <'\tgit branch all1 &&\n'> <'\tgit branch all2 &&\n'> <'\tgit push -u --all &&\n'> 
          <'\tcheck_config all1 upstream refs/heads/all1 &&\n'> <'\tcheck_config all2 upstream refs/heads/all2\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push -u HEAD'>)} 
      {
        (SQ <'\n'> <'\tgit checkout -b headbranch &&\n'> <'\tgit push -u upstream HEAD &&\n'> 
          <'\tcheck_config headbranch upstream refs/heads/headbranch\n'>
        )
      }
    )
    (C {<test_expect_success>} {<TTY>} {(SQ <'progress messages go to tty'>)} 
      {
        (SQ <'\n'> <'\tensure_fresh_upstream &&\n'> <'\n'> 
          <'\ttest_terminal git push -u upstream master >out 2>err &&\n'> <'\ttest_i18ngrep "Writing objects" err\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'progress messages do not go to non-tty'>)} 
      {
        (SQ <'\n'> <'\tensure_fresh_upstream &&\n'> <'\n'> 
          <'\t# skip progress messages, since stderr is non-tty\n'> <'\tgit push -u upstream master >out 2>err &&\n'> <'\ttest_i18ngrep ! "Writing objects" err\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'progress messages go to non-tty (forced)'>)} 
      {
        (SQ <'\n'> <'\tensure_fresh_upstream &&\n'> <'\n'> 
          <'\t# force progress messages to stderr, even though it is non-tty\n'> <'\tgit push -u --progress upstream master >out 2>err &&\n'> 
          <'\ttest_i18ngrep "Writing objects" err\n'>
        )
      }
    )
    (C {<test_expect_success>} {<TTY>} {(SQ <'push -q suppresses progress'>)} 
      {
        (SQ <'\n'> <'\tensure_fresh_upstream &&\n'> <'\n'> 
          <'\ttest_terminal git push -u -q upstream master >out 2>err &&\n'> <'\ttest_i18ngrep ! "Writing objects" err\n'>
        )
      }
    )
    (C {<test_expect_success>} {<TTY>} {(SQ <'push --no-progress suppresses progress'>)} 
      {
        (SQ <'\n'> <'\tensure_fresh_upstream &&\n'> <'\n'> 
          <'\ttest_terminal git push -u --no-progress upstream master >out 2>err &&\n'> <'\ttest_i18ngrep ! "Unpacking objects" err &&\n'> <'\ttest_i18ngrep ! "Writing objects" err\n'>
        )
      }
    )
    (C {<test_expect_success>} {<TTY>} {(SQ <'quiet push'>)} 
      {
        (SQ <'\n'> <'\tensure_fresh_upstream &&\n'> <'\n'> 
          <'\ttest_terminal git push --quiet --no-progress upstream master 2>&1 | tee output &&\n'> <'\ttest_cmp /dev/null output\n'>
        )
      }
    )
    (C {<test_done>})
  ]
)