def SendUpstream(parser, args, cmd):
    'Common code for CMDland and CmdDCommit\n\n  In case of Gerrit, uses Gerrit REST api to "submit" the issue, which pushes\n  upstream and closes the issue automatically and atomically.\n\n  Otherwise (in case of Rietveld):\n    Squashes branch into a single commit.\n    Updates changelog with metadata (e.g. pointer to review).\n    Pushes/dcommits the code upstream.\n    Updates review and closes.\n  '
    parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', help='bypass upload presubmit hook')
    parser.add_option('-m', dest='message', help='override review description')
    parser.add_option('-f', action='store_true', dest='force', help="force yes to questions (don't prompt)")
    parser.add_option('-c', dest='contributor', help=(('external contributor for patch (appended to ' + 'description and used as author for git). Should be ') + "formatted as 'First Last <example@example.com>'"))
    add_git_similarity(parser)
    auth.add_auth_options(parser)
    (options, args) = parser.parse_args(args)
    auth_config = auth.extract_auth_config_from_options(options)
    cl = Changelist(auth_config=auth_config)
    if cl.IsGerrit():
        if options.message:
            parser.error('-m MESSAGE option is not supported for Gerrit.')
        if options.contributor:
            parser.error('-c CONTRIBUTOR option is not supported for Gerrit.\nBefore uploading a commit to Gerrit, ensure it\'s author field is the contributor\'s "name <email>". If you can\'t upload such a commit for review, contact your repository admin and request"Forge-Author" permission.')
        return cl._codereview_impl.CMDLand(options.force, options.bypass_hooks, options.verbose)
    current = cl.GetBranch()
    (remote, upstream_branch) = cl.FetchUpstreamTuple(cl.GetBranch())
    if ((not settings.GetIsGitSvn()) and (remote == '.')):
        print()
        print(('Attempting to push branch %r into another local branch!' % current))
        print()
        print('Either reparent this branch on top of origin/master:')
        print('  git reparent-branch --root')
        print()
        print('OR run `git rebase-update` if you think the parent branch is ')
        print('already committed.')
        print()
        print(('  Current parent: %r' % upstream_branch))
        return 1
    if ((not args) or (cmd == 'land')):
        args = [cl.GetUpstreamBranch()]
    if options.contributor:
        if (not re.match('^.*\\s<\\S+@\\S+>$', options.contributor)):
            print("Please provide contibutor as 'First Last <example@example.com>'")
            return 1
    base_branch = args[0]
    base_has_submodules = IsSubmoduleMergeCommit(base_branch)
    if git_common.is_dirty_git_tree(cmd):
        return 1
    upstream_commits = RunGit(['rev-list', ('^' + cl.GetBranchRef()), base_branch]).splitlines()
    if upstream_commits:
        print(('Base branch "%s" has %d commits not in this branch.' % (base_branch, len(upstream_commits))))
        print(('Run "git merge %s" before attempting to %s.' % (base_branch, cmd)))
        return 1
    svn_head = None
    if ((cmd == 'dcommit') or base_has_submodules):
        svn_head = RunGit(['log', '--grep=^git-svn-id:', '-1', '--pretty=format:%H'])
    if (cmd == 'dcommit'):
        base_svn_head = base_branch
        if base_has_submodules:
            base_svn_head += '^1'
        extra_commits = RunGit(['rev-list', ('^' + svn_head), base_svn_head])
        if extra_commits:
            print(('This branch has %d additional commits not upstreamed yet.' % len(extra_commits.splitlines())))
            print(('Upstream "%s" or rebase this branch on top of the upstream trunk before attempting to %s.' % (base_branch, cmd)))
            return 1
    merge_base = RunGit(['merge-base', base_branch, 'HEAD']).strip()
    if (not options.bypass_hooks):
        author = None
        if options.contributor:
            author = re.search('\\<(.*)\\>', options.contributor).group(1)
        hook_results = cl.RunHook(committing=True, may_prompt=(not options.force), verbose=options.verbose, change=cl.GetChange(merge_base, author))
        if (not hook_results.should_continue()):
            return 1
        status = GetTreeStatus()
        if ('closed' == status):
            print(('The tree is closed.  Please wait for it to reopen. Use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd))
            return 1
        elif ('unknown' == status):
            print(('Unable to determine tree status.  Please verify manually and use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd))
            return 1
    change_desc = ChangeDescription(options.message)
    if ((not change_desc.description) and cl.GetIssue()):
        change_desc = ChangeDescription(cl.GetDescription())
    if (not change_desc.description):
        if ((not cl.GetIssue()) and options.bypass_hooks):
            change_desc = ChangeDescription(CreateDescriptionFromLog([merge_base]))
        else:
            print('No description set.')
            print(('Visit %s/edit to set it.' % cl.GetIssueURL()))
            return 1
    if cl.GetIssue():
        change_desc.update_reviewers(cl.GetApprovingReviewers())
    commit_desc = ChangeDescription(change_desc.description)
    if cl.GetIssue():
        commit_desc.append_footer(('Review URL: %s .' % cl.GetIssueURL()))
    if options.contributor:
        commit_desc.append_footer(('Patch from %s.' % options.contributor))
    print('Description:')
    print(commit_desc.description)
    branches = [merge_base, cl.GetBranchRef()]
    if (not options.force):
        print_stats(options.similarity, options.find_copies, branches)
    MERGE_BRANCH = 'git-cl-commit'
    CHERRY_PICK_BRANCH = 'git-cl-cherry-pick'
    for branch in [MERGE_BRANCH, CHERRY_PICK_BRANCH]:
        showref_cmd = ['show-ref', '--quiet', '--verify', ('refs/heads/%s' % branch)]
        result = RunGitWithCode(showref_cmd)
        if (result[0] == 0):
            RunGit(['branch', '-D', branch])
    rel_base_path = settings.GetRelativeRoot()
    if rel_base_path:
        os.chdir(rel_base_path)
    retcode = (- 1)
    pushed_to_pending = False
    pending_ref = None
    revision = None
    try:
        RunGit(['checkout', '-q', '-b', MERGE_BRANCH])
        RunGit(['reset', '--soft', merge_base])
        if options.contributor:
            RunGit(['commit', '--author', options.contributor, '-m', commit_desc.description])
        else:
            RunGit(['commit', '-m', commit_desc.description])
        if base_has_submodules:
            cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip()
            RunGit(['branch', CHERRY_PICK_BRANCH, svn_head])
            RunGit(['checkout', CHERRY_PICK_BRANCH])
            RunGit(['cherry-pick', cherry_pick_commit])
        if (cmd == 'land'):
            (remote, branch) = cl.FetchUpstreamTuple(cl.GetBranch())
            mirror = settings.GetGitMirror(remote)
            pushurl = (mirror.url if mirror else remote)
            pending_prefix = settings.GetPendingRefPrefix()
            if ((not pending_prefix) or branch.startswith(pending_prefix)):
                (retcode, output) = RunGitWithCode(['push', '--porcelain', pushurl, ('HEAD:%s' % branch)])
                pushed_to_pending = (pending_prefix and branch.startswith(pending_prefix))
            else:
                assert branch.startswith('refs/'), branch
                assert (pending_prefix[(- 1)] == '/'), pending_prefix
                pending_ref = (pending_prefix + branch[len('refs/'):])
                (retcode, output) = PushToGitPending(pushurl, pending_ref, branch)
                pushed_to_pending = (retcode == 0)
            if (retcode == 0):
                revision = RunGit(['rev-parse', 'HEAD']).strip()
        else:
            cmd_args = ['svn', 'dcommit', ('-C%s' % options.similarity), '--no-rebase', '--rmdir']
            if settings.GetForceHttpsCommitUrl():
                remote_url = cl.GetGitSvnRemoteUrl()
                if (urlparse.urlparse(remote_url).scheme == 'http'):
                    remote_url = remote_url.replace('http://', 'https://')
                cmd_args.append(('--commit-url=%s' % remote_url))
            (_, output) = RunGitWithCode(cmd_args)
            if ('Committed r' in output):
                revision = re.match('.*?\nCommitted r(\\d+)', output, re.DOTALL).group(1)
        logging.debug(output)
    finally:
        RunGit(['checkout', '-q', cl.GetBranch()])
        RunGit(['branch', '-D', MERGE_BRANCH])
        if base_has_submodules:
            RunGit(['branch', '-D', CHERRY_PICK_BRANCH])
    if (not revision):
        print('Failed to push. If this persists, please file a bug.')
        return 1
    killed = False
    if pushed_to_pending:
        try:
            revision = WaitForRealCommit(remote, revision, base_branch, branch)
            pushed_to_pending = False
        except KeyboardInterrupt:
            killed = True
    if cl.GetIssue():
        to_pending = (' to pending queue' if pushed_to_pending else '')
        viewvc_url = settings.GetViewVCUrl()
        if (not to_pending):
            if (viewvc_url and revision):
                change_desc.append_footer(('Committed: %s%s' % (viewvc_url, revision)))
            elif revision:
                change_desc.append_footer(('Committed: %s' % (revision,)))
        print('Closing issue (you may be prompted for your codereview password)...')
        cl.UpdateDescription(change_desc.description)
        cl.CloseIssue()
        props = cl.GetIssueProperties()
        patch_num = len(props['patchsets'])
        comment = ('Committed patchset #%d (id:%d)%s manually as %s' % (patch_num, props['patchsets'][(- 1)], to_pending, revision))
        if options.bypass_hooks:
            comment += (' (tree was closed).' if (GetTreeStatus() == 'closed') else '.')
        else:
            comment += ' (presubmit successful).'
        cl.RpcServer().add_comment(cl.GetIssue(), comment)
        cl.SetIssue(None)
    if pushed_to_pending:
        (_, branch) = cl.FetchUpstreamTuple(cl.GetBranch())
        print(('The commit is in the pending queue (%s).' % pending_ref))
        print(('It will show up on %s in ~1 min, once it gets a Cr-Commit-Position footer.' % branch))
    hook = (POSTUPSTREAM_HOOK_PATTERN % cmd)
    if os.path.isfile(hook):
        RunCommand([hook, merge_base], error_ok=True)
    return (1 if killed else 0)
Common code for CMDland and CmdDCommit

In case of Gerrit, uses Gerrit REST api to "submit" the issue, which pushes
upstream and closes the issue automatically and atomically.

Otherwise (in case of Rietveld):
  Squashes branch into a single commit.
  Updates changelog with metadata (e.g. pointer to review).
  Pushes/dcommits the code upstream.
  Updates review and closes.
def SendUpstream(parser, args, cmd):
    'Common code for CMDland and CmdDCommit\n\n  In case of Gerrit, uses Gerrit REST api to "submit" the issue, which pushes\n  upstream and closes the issue automatically and atomically.\n\n  Otherwise (in case of Rietveld):\n    Squashes branch into a single commit.\n    Updates changelog with metadata (e.g. pointer to review).\n    Pushes/dcommits the code upstream.\n    Updates review and closes.\n  '
    parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', help='bypass upload presubmit hook')
    parser.add_option('-m', dest='message', help='override review description')
    parser.add_option('-f', action='store_true', dest='force', help="force yes to questions (don't prompt)")
    parser.add_option('-c', dest='contributor', help=(('external contributor for patch (appended to ' + 'description and used as author for git). Should be ') + "formatted as 'First Last <example@example.com>'"))
    add_git_similarity(parser)
    auth.add_auth_options(parser)
    (options, args) = parser.parse_args(args)
    auth_config = auth.extract_auth_config_from_options(options)
    cl = Changelist(auth_config=auth_config)
    if cl.IsGerrit():
        if options.message:
            parser.error('-m MESSAGE option is not supported for Gerrit.')
        if options.contributor:
            parser.error('-c CONTRIBUTOR option is not supported for Gerrit.\nBefore uploading a commit to Gerrit, ensure it\'s author field is the contributor\'s "name <email>". If you can\'t upload such a commit for review, contact your repository admin and request"Forge-Author" permission.')
        return cl._codereview_impl.CMDLand(options.force, options.bypass_hooks, options.verbose)
    current = cl.GetBranch()
    (remote, upstream_branch) = cl.FetchUpstreamTuple(cl.GetBranch())
    if ((not settings.GetIsGitSvn()) and (remote == '.')):
        print()
        print(('Attempting to push branch %r into another local branch!' % current))
        print()
        print('Either reparent this branch on top of origin/master:')
        print('  git reparent-branch --root')
        print()
        print('OR run `git rebase-update` if you think the parent branch is ')
        print('already committed.')
        print()
        print(('  Current parent: %r' % upstream_branch))
        return 1
    if ((not args) or (cmd == 'land')):
        args = [cl.GetUpstreamBranch()]
    if options.contributor:
        if (not re.match('^.*\\s<\\S+@\\S+>$', options.contributor)):
            print("Please provide contibutor as 'First Last <example@example.com>'")
            return 1
    base_branch = args[0]
    base_has_submodules = IsSubmoduleMergeCommit(base_branch)
    if git_common.is_dirty_git_tree(cmd):
        return 1
    upstream_commits = RunGit(['rev-list', ('^' + cl.GetBranchRef()), base_branch]).splitlines()
    if upstream_commits:
        print(('Base branch "%s" has %d commits not in this branch.' % (base_branch, len(upstream_commits))))
        print(('Run "git merge %s" before attempting to %s.' % (base_branch, cmd)))
        return 1
    svn_head = None
    if ((cmd == 'dcommit') or base_has_submodules):
        svn_head = RunGit(['log', '--grep=^git-svn-id:', '-1', '--pretty=format:%H'])
    if (cmd == 'dcommit'):
        base_svn_head = base_branch
        if base_has_submodules:
            base_svn_head += '^1'
        extra_commits = RunGit(['rev-list', ('^' + svn_head), base_svn_head])
        if extra_commits:
            print(('This branch has %d additional commits not upstreamed yet.' % len(extra_commits.splitlines())))
            print(('Upstream "%s" or rebase this branch on top of the upstream trunk before attempting to %s.' % (base_branch, cmd)))
            return 1
    merge_base = RunGit(['merge-base', base_branch, 'HEAD']).strip()
    if (not options.bypass_hooks):
        author = None
        if options.contributor:
            author = re.search('\\<(.*)\\>', options.contributor).group(1)
        hook_results = cl.RunHook(committing=True, may_prompt=(not options.force), verbose=options.verbose, change=cl.GetChange(merge_base, author))
        if (not hook_results.should_continue()):
            return 1
        status = GetTreeStatus()
        if ('closed' == status):
            print(('The tree is closed.  Please wait for it to reopen. Use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd))
            return 1
        elif ('unknown' == status):
            print(('Unable to determine tree status.  Please verify manually and use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd))
            return 1
    change_desc = ChangeDescription(options.message)
    if ((not change_desc.description) and cl.GetIssue()):
        change_desc = ChangeDescription(cl.GetDescription())
    if (not change_desc.description):
        if ((not cl.GetIssue()) and options.bypass_hooks):
            change_desc = ChangeDescription(CreateDescriptionFromLog([merge_base]))
        else:
            print('No description set.')
            print(('Visit %s/edit to set it.' % cl.GetIssueURL()))
            return 1
    if cl.GetIssue():
        change_desc.update_reviewers(cl.GetApprovingReviewers())
    commit_desc = ChangeDescription(change_desc.description)
    if cl.GetIssue():
        commit_desc.append_footer(('Review URL: %s .' % cl.GetIssueURL()))
    if options.contributor:
        commit_desc.append_footer(('Patch from %s.' % options.contributor))
    print('Description:')
    print(commit_desc.description)
    branches = [merge_base, cl.GetBranchRef()]
    if (not options.force):
        print_stats(options.similarity, options.find_copies, branches)
    MERGE_BRANCH = 'git-cl-commit'
    CHERRY_PICK_BRANCH = 'git-cl-cherry-pick'
    for branch in [MERGE_BRANCH, CHERRY_PICK_BRANCH]:
        showref_cmd = ['show-ref', '--quiet', '--verify', ('refs/heads/%s' % branch)]
        result = RunGitWithCode(showref_cmd)
        if (result[0] == 0):
            RunGit(['branch', '-D', branch])
    rel_base_path = settings.GetRelativeRoot()
    if rel_base_path:
        os.chdir(rel_base_path)
    retcode = (- 1)
    pushed_to_pending = False
    pending_ref = None
    revision = None
    try:
        RunGit(['checkout', '-q', '-b', MERGE_BRANCH])
        RunGit(['reset', '--soft', merge_base])
        if options.contributor:
            RunGit(['commit', '--author', options.contributor, '-m', commit_desc.description])
        else:
            RunGit(['commit', '-m', commit_desc.description])
        if base_has_submodules:
            cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip()
            RunGit(['branch', CHERRY_PICK_BRANCH, svn_head])
            RunGit(['checkout', CHERRY_PICK_BRANCH])
            RunGit(['cherry-pick', cherry_pick_commit])
        if (cmd == 'land'):
            (remote, branch) = cl.FetchUpstreamTuple(cl.GetBranch())
            mirror = settings.GetGitMirror(remote)
            pushurl = (mirror.url if mirror else remote)
            pending_prefix = settings.GetPendingRefPrefix()
            if ((not pending_prefix) or branch.startswith(pending_prefix)):
                (retcode, output) = RunGitWithCode(['push', '--porcelain', pushurl, ('HEAD:%s' % branch)])
                pushed_to_pending = (pending_prefix and branch.startswith(pending_prefix))
            else:
                assert branch.startswith('refs/'), branch
                assert (pending_prefix[(- 1)] == '/'), pending_prefix
                pending_ref = (pending_prefix + branch[len('refs/'):])
                (retcode, output) = PushToGitPending(pushurl, pending_ref, branch)
                pushed_to_pending = (retcode == 0)
            if (retcode == 0):
                revision = RunGit(['rev-parse', 'HEAD']).strip()
        else:
            cmd_args = ['svn', 'dcommit', ('-C%s' % options.similarity), '--no-rebase', '--rmdir']
            if settings.GetForceHttpsCommitUrl():
                remote_url = cl.GetGitSvnRemoteUrl()
                if (urlparse.urlparse(remote_url).scheme == 'http'):
                    remote_url = remote_url.replace('http://', 'https://')
                cmd_args.append(('--commit-url=%s' % remote_url))
            (_, output) = RunGitWithCode(cmd_args)
            if ('Committed r' in output):
                revision = re.match('.*?\nCommitted r(\\d+)', output, re.DOTALL).group(1)
        logging.debug(output)
    finally:
        RunGit(['checkout', '-q', cl.GetBranch()])
        RunGit(['branch', '-D', MERGE_BRANCH])
        if base_has_submodules:
            RunGit(['branch', '-D', CHERRY_PICK_BRANCH])
    if (not revision):
        print('Failed to push. If this persists, please file a bug.')
        return 1
    killed = False
    if pushed_to_pending:
        try:
            revision = WaitForRealCommit(remote, revision, base_branch, branch)
            pushed_to_pending = False
        except KeyboardInterrupt:
            killed = True
    if cl.GetIssue():
        to_pending = (' to pending queue' if pushed_to_pending else )
        viewvc_url = settings.GetViewVCUrl()
        if (not to_pending):
            if (viewvc_url and revision):
                change_desc.append_footer(('Committed: %s%s' % (viewvc_url, revision)))
            elif revision:
                change_desc.append_footer(('Committed: %s' % (revision,)))
        print('Closing issue (you may be prompted for your codereview password)...')
        cl.UpdateDescription(change_desc.description)
        cl.CloseIssue()
        props = cl.GetIssueProperties()
        patch_num = len(props['patchsets'])
        comment = ('Committed patchset #%d (id:%d)%s manually as %s' % (patch_num, props['patchsets'][(- 1)], to_pending, revision))
        if options.bypass_hooks:
            comment += (' (tree was closed).' if (GetTreeStatus() == 'closed') else '.')
        else:
            comment += ' (presubmit successful).'
        cl.RpcServer().add_comment(cl.GetIssue(), comment)
        cl.SetIssue(None)
    if pushed_to_pending:
        (_, branch) = cl.FetchUpstreamTuple(cl.GetBranch())
        print(('The commit is in the pending queue (%s).' % pending_ref))
        print(('It will show up on %s in ~1 min, once it gets a Cr-Commit-Position footer.' % branch))
    hook = (POSTUPSTREAM_HOOK_PATTERN % cmd)
    if os.path.isfile(hook):
        RunCommand([hook, merge_base], error_ok=True)
    return (1 if killed else 0)