| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
| 7 | 7 |
| 8 """A git-command for integrating reviews on Rietveld.""" | 8 """A git-command for integrating reviews on Rietveld.""" |
| 9 | 9 |
| 10 from distutils.version import LooseVersion | 10 from distutils.version import LooseVersion |
| (...skipping 1875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1886 base_svn_head += '^1' | 1886 base_svn_head += '^1' |
| 1887 | 1887 |
| 1888 extra_commits = RunGit(['rev-list', '^' + svn_head, base_svn_head]) | 1888 extra_commits = RunGit(['rev-list', '^' + svn_head, base_svn_head]) |
| 1889 if extra_commits: | 1889 if extra_commits: |
| 1890 print ('This branch has %d additional commits not upstreamed yet.' | 1890 print ('This branch has %d additional commits not upstreamed yet.' |
| 1891 % len(extra_commits.splitlines())) | 1891 % len(extra_commits.splitlines())) |
| 1892 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' | 1892 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' |
| 1893 'before attempting to %s.' % (base_branch, cmd)) | 1893 'before attempting to %s.' % (base_branch, cmd)) |
| 1894 return 1 | 1894 return 1 |
| 1895 | 1895 |
| 1896 base_branch = RunGit(['merge-base', base_branch, 'HEAD']).strip() | 1896 merge_base = RunGit(['merge-base', base_branch, 'HEAD']).strip() |
| 1897 if not options.bypass_hooks: | 1897 if not options.bypass_hooks: |
| 1898 author = None | 1898 author = None |
| 1899 if options.contributor: | 1899 if options.contributor: |
| 1900 author = re.search(r'\<(.*)\>', options.contributor).group(1) | 1900 author = re.search(r'\<(.*)\>', options.contributor).group(1) |
| 1901 hook_results = cl.RunHook( | 1901 hook_results = cl.RunHook( |
| 1902 committing=True, | 1902 committing=True, |
| 1903 may_prompt=not options.force, | 1903 may_prompt=not options.force, |
| 1904 verbose=options.verbose, | 1904 verbose=options.verbose, |
| 1905 change=cl.GetChange(base_branch, author)) | 1905 change=cl.GetChange(merge_base, author)) |
| 1906 if not hook_results.should_continue(): | 1906 if not hook_results.should_continue(): |
| 1907 return 1 | 1907 return 1 |
| 1908 | 1908 |
| 1909 # Check the tree status if the tree status URL is set. | 1909 # Check the tree status if the tree status URL is set. |
| 1910 status = GetTreeStatus() | 1910 status = GetTreeStatus() |
| 1911 if 'closed' == status: | 1911 if 'closed' == status: |
| 1912 print('The tree is closed. Please wait for it to reopen. Use ' | 1912 print('The tree is closed. Please wait for it to reopen. Use ' |
| 1913 '"git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) | 1913 '"git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) |
| 1914 return 1 | 1914 return 1 |
| 1915 elif 'unknown' == status: | 1915 elif 'unknown' == status: |
| 1916 print('Unable to determine tree status. Please verify manually and ' | 1916 print('Unable to determine tree status. Please verify manually and ' |
| 1917 'use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) | 1917 'use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) |
| 1918 return 1 | 1918 return 1 |
| 1919 else: | 1919 else: |
| 1920 breakpad.SendStack( | 1920 breakpad.SendStack( |
| 1921 'GitClHooksBypassedCommit', | 1921 'GitClHooksBypassedCommit', |
| 1922 'Issue %s/%s bypassed hook when committing (tree status was "%s")' % | 1922 'Issue %s/%s bypassed hook when committing (tree status was "%s")' % |
| 1923 (cl.GetRietveldServer(), cl.GetIssue(), GetTreeStatus()), | 1923 (cl.GetRietveldServer(), cl.GetIssue(), GetTreeStatus()), |
| 1924 verbose=False) | 1924 verbose=False) |
| 1925 | 1925 |
| 1926 change_desc = ChangeDescription(options.message) | 1926 change_desc = ChangeDescription(options.message) |
| 1927 if not change_desc.description and cl.GetIssue(): | 1927 if not change_desc.description and cl.GetIssue(): |
| 1928 change_desc = ChangeDescription(cl.GetDescription()) | 1928 change_desc = ChangeDescription(cl.GetDescription()) |
| 1929 | 1929 |
| 1930 if not change_desc.description: | 1930 if not change_desc.description: |
| 1931 if not cl.GetIssue() and options.bypass_hooks: | 1931 if not cl.GetIssue() and options.bypass_hooks: |
| 1932 change_desc = ChangeDescription(CreateDescriptionFromLog([base_branch])) | 1932 change_desc = ChangeDescription(CreateDescriptionFromLog([merge_base])) |
| 1933 else: | 1933 else: |
| 1934 print 'No description set.' | 1934 print 'No description set.' |
| 1935 print 'Visit %s/edit to set it.' % (cl.GetIssueURL()) | 1935 print 'Visit %s/edit to set it.' % (cl.GetIssueURL()) |
| 1936 return 1 | 1936 return 1 |
| 1937 | 1937 |
| 1938 # Keep a separate copy for the commit message, because the commit message | 1938 # Keep a separate copy for the commit message, because the commit message |
| 1939 # contains the link to the Rietveld issue, while the Rietveld message contains | 1939 # contains the link to the Rietveld issue, while the Rietveld message contains |
| 1940 # the commit viewvc url. | 1940 # the commit viewvc url. |
| 1941 # Keep a separate copy for the commit message. | 1941 # Keep a separate copy for the commit message. |
| 1942 if cl.GetIssue(): | 1942 if cl.GetIssue(): |
| 1943 change_desc.update_reviewers(cl.GetApprovingReviewers()) | 1943 change_desc.update_reviewers(cl.GetApprovingReviewers()) |
| 1944 | 1944 |
| 1945 commit_desc = ChangeDescription(change_desc.description) | 1945 commit_desc = ChangeDescription(change_desc.description) |
| 1946 if cl.GetIssue(): | 1946 if cl.GetIssue(): |
| 1947 commit_desc.append_footer('Review URL: %s' % cl.GetIssueURL()) | 1947 commit_desc.append_footer('Review URL: %s' % cl.GetIssueURL()) |
| 1948 if options.contributor: | 1948 if options.contributor: |
| 1949 commit_desc.append_footer('Patch from %s.' % options.contributor) | 1949 commit_desc.append_footer('Patch from %s.' % options.contributor) |
| 1950 | 1950 |
| 1951 print('Description:') | 1951 print('Description:') |
| 1952 print(commit_desc.description) | 1952 print(commit_desc.description) |
| 1953 | 1953 |
| 1954 branches = [base_branch, cl.GetBranchRef()] | 1954 branches = [merge_base, cl.GetBranchRef()] |
| 1955 if not options.force: | 1955 if not options.force: |
| 1956 print_stats(options.similarity, options.find_copies, branches) | 1956 print_stats(options.similarity, options.find_copies, branches) |
| 1957 | 1957 |
| 1958 # We want to squash all this branch's commits into one commit with the proper | 1958 # We want to squash all this branch's commits into one commit with the proper |
| 1959 # description. We do this by doing a "reset --soft" to the base branch (which | 1959 # description. We do this by doing a "reset --soft" to the base branch (which |
| 1960 # keeps the working copy the same), then dcommitting that. If origin/master | 1960 # keeps the working copy the same), then dcommitting that. If origin/master |
| 1961 # has a submodule merge commit, we'll also need to cherry-pick the squashed | 1961 # has a submodule merge commit, we'll also need to cherry-pick the squashed |
| 1962 # commit onto a branch based on the git-svn head. | 1962 # commit onto a branch based on the git-svn head. |
| 1963 MERGE_BRANCH = 'git-cl-commit' | 1963 MERGE_BRANCH = 'git-cl-commit' |
| 1964 CHERRY_PICK_BRANCH = 'git-cl-cherry-pick' | 1964 CHERRY_PICK_BRANCH = 'git-cl-cherry-pick' |
| 1965 # Delete the branches if they exist. | 1965 # Delete the branches if they exist. |
| 1966 for branch in [MERGE_BRANCH, CHERRY_PICK_BRANCH]: | 1966 for branch in [MERGE_BRANCH, CHERRY_PICK_BRANCH]: |
| 1967 showref_cmd = ['show-ref', '--quiet', '--verify', 'refs/heads/%s' % branch] | 1967 showref_cmd = ['show-ref', '--quiet', '--verify', 'refs/heads/%s' % branch] |
| 1968 result = RunGitWithCode(showref_cmd) | 1968 result = RunGitWithCode(showref_cmd) |
| 1969 if result[0] == 0: | 1969 if result[0] == 0: |
| 1970 RunGit(['branch', '-D', branch]) | 1970 RunGit(['branch', '-D', branch]) |
| 1971 | 1971 |
| 1972 # We might be in a directory that's present in this branch but not in the | 1972 # We might be in a directory that's present in this branch but not in the |
| 1973 # trunk. Move up to the top of the tree so that git commands that expect a | 1973 # trunk. Move up to the top of the tree so that git commands that expect a |
| 1974 # valid CWD won't fail after we check out the merge branch. | 1974 # valid CWD won't fail after we check out the merge branch. |
| 1975 rel_base_path = settings.GetRelativeRoot() | 1975 rel_base_path = settings.GetRelativeRoot() |
| 1976 if rel_base_path: | 1976 if rel_base_path: |
| 1977 os.chdir(rel_base_path) | 1977 os.chdir(rel_base_path) |
| 1978 | 1978 |
| 1979 # Stuff our change into the merge branch. | 1979 # Stuff our change into the merge branch. |
| 1980 # We wrap in a try...finally block so if anything goes wrong, | 1980 # We wrap in a try...finally block so if anything goes wrong, |
| 1981 # we clean up the branches. | 1981 # we clean up the branches. |
| 1982 retcode = -1 | 1982 retcode = -1 |
| 1983 used_pending = False | 1983 pushed_to_pending = False |
| 1984 pending_ref = None | 1984 pending_ref = None |
| 1985 revision = None |
| 1985 try: | 1986 try: |
| 1986 RunGit(['checkout', '-q', '-b', MERGE_BRANCH]) | 1987 RunGit(['checkout', '-q', '-b', MERGE_BRANCH]) |
| 1987 RunGit(['reset', '--soft', base_branch]) | 1988 RunGit(['reset', '--soft', merge_base]) |
| 1988 if options.contributor: | 1989 if options.contributor: |
| 1989 RunGit( | 1990 RunGit( |
| 1990 [ | 1991 [ |
| 1991 'commit', '--author', options.contributor, | 1992 'commit', '--author', options.contributor, |
| 1992 '-m', commit_desc.description, | 1993 '-m', commit_desc.description, |
| 1993 ]) | 1994 ]) |
| 1994 else: | 1995 else: |
| 1995 RunGit(['commit', '-m', commit_desc.description]) | 1996 RunGit(['commit', '-m', commit_desc.description]) |
| 1996 if base_has_submodules: | 1997 if base_has_submodules: |
| 1997 cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip() | 1998 cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip() |
| 1998 RunGit(['branch', CHERRY_PICK_BRANCH, svn_head]) | 1999 RunGit(['branch', CHERRY_PICK_BRANCH, svn_head]) |
| 1999 RunGit(['checkout', CHERRY_PICK_BRANCH]) | 2000 RunGit(['checkout', CHERRY_PICK_BRANCH]) |
| 2000 RunGit(['cherry-pick', cherry_pick_commit]) | 2001 RunGit(['cherry-pick', cherry_pick_commit]) |
| 2001 if cmd == 'land': | 2002 if cmd == 'land': |
| 2002 remote, branch = cl.FetchUpstreamTuple(cl.GetBranch()) | 2003 remote, branch = cl.FetchUpstreamTuple(cl.GetBranch()) |
| 2003 pending_prefix = settings.GetPendingRefPrefix() | 2004 pending_prefix = settings.GetPendingRefPrefix() |
| 2004 if not pending_prefix or branch.startswith(pending_prefix): | 2005 if not pending_prefix or branch.startswith(pending_prefix): |
| 2005 # If not using refs/pending/heads/* at all, or target ref is already set | 2006 # If not using refs/pending/heads/* at all, or target ref is already set |
| 2006 # to pending, then push to the target ref directly. | 2007 # to pending, then push to the target ref directly. |
| 2007 retcode, output = RunGitWithCode( | 2008 retcode, output = RunGitWithCode( |
| 2008 ['push', '--porcelain', remote, 'HEAD:%s' % branch]) | 2009 ['push', '--porcelain', remote, 'HEAD:%s' % branch]) |
| 2009 used_pending = pending_prefix and branch.startswith(pending_prefix) | 2010 pushed_to_pending = pending_prefix and branch.startswith(pending_prefix) |
| 2010 else: | 2011 else: |
| 2011 # Cherry-pick the change on top of pending ref and then push it. | 2012 # Cherry-pick the change on top of pending ref and then push it. |
| 2012 assert branch.startswith('refs/'), branch | 2013 assert branch.startswith('refs/'), branch |
| 2013 assert pending_prefix[-1] == '/', pending_prefix | 2014 assert pending_prefix[-1] == '/', pending_prefix |
| 2014 pending_ref = pending_prefix + branch[len('refs/'):] | 2015 pending_ref = pending_prefix + branch[len('refs/'):] |
| 2015 retcode, output = PushToGitPending(remote, pending_ref, branch) | 2016 retcode, output = PushToGitPending(remote, pending_ref, branch) |
| 2016 used_pending = (retcode == 0) | 2017 revision = RunGit(['rev-parse', 'HEAD']).strip() |
| 2018 pushed_to_pending = (retcode == 0) |
| 2017 logging.debug(output) | 2019 logging.debug(output) |
| 2018 else: | 2020 else: |
| 2019 # dcommit the merge branch. | 2021 # dcommit the merge branch. |
| 2020 retcode, output = RunGitWithCode(['svn', 'dcommit', | 2022 retcode, output = RunGitWithCode(['svn', 'dcommit', |
| 2021 '-C%s' % options.similarity, | 2023 '-C%s' % options.similarity, |
| 2022 '--no-rebase', '--rmdir']) | 2024 '--no-rebase', '--rmdir']) |
| 2023 finally: | 2025 finally: |
| 2024 # And then swap back to the original branch and clean up. | 2026 # And then swap back to the original branch and clean up. |
| 2025 RunGit(['checkout', '-q', cl.GetBranch()]) | 2027 RunGit(['checkout', '-q', cl.GetBranch()]) |
| 2026 RunGit(['branch', '-D', MERGE_BRANCH]) | 2028 RunGit(['branch', '-D', MERGE_BRANCH]) |
| 2027 if base_has_submodules: | 2029 if base_has_submodules: |
| 2028 RunGit(['branch', '-D', CHERRY_PICK_BRANCH]) | 2030 RunGit(['branch', '-D', CHERRY_PICK_BRANCH]) |
| 2029 | 2031 |
| 2032 if retcode == 0 and pushed_to_pending: |
| 2033 try: |
| 2034 revision = WaitForRealCommit(remote, revision, base_branch, branch) |
| 2035 # We set pushed_to_pending to False, since it made it all the way to the |
| 2036 # real ref. |
| 2037 pushed_to_pending = False |
| 2038 except KeyboardInterrupt: |
| 2039 pass |
| 2040 |
| 2030 if cl.GetIssue(): | 2041 if cl.GetIssue(): |
| 2031 if cmd == 'dcommit' and 'Committed r' in output: | 2042 if not revision: |
| 2032 revision = re.match('.*?\nCommitted r(\\d+)', output, re.DOTALL).group(1) | 2043 if cmd == 'dcommit' and 'Committed r' in output: |
| 2033 elif cmd == 'land' and retcode == 0: | 2044 revision = re.match( |
| 2034 match = (re.match(r'.*?([a-f0-9]{7,})\.\.([a-f0-9]{7,})$', l) | 2045 '.*?\nCommitted r(\\d+)', output, re.DOTALL).group(1) |
| 2035 for l in output.splitlines(False)) | 2046 elif cmd == 'land' and retcode == 0: |
| 2036 match = filter(None, match) | 2047 match = (re.match(r'.*?([a-f0-9]{7,})\.\.([a-f0-9]{7,})$', l) |
| 2037 if len(match) != 1: | 2048 for l in output.splitlines(False)) |
| 2038 DieWithError("Couldn't parse ouput to extract the committed hash:\n%s" % | 2049 match = filter(None, match) |
| 2039 output) | 2050 if len(match) != 1: |
| 2040 revision = match[0].group(2) | 2051 DieWithError( |
| 2041 else: | 2052 "Couldn't parse ouput to extract the committed hash:\n%s" % output) |
| 2042 return 1 | 2053 revision = match[0].group(2) |
| 2043 to_pending = ' to pending queue' if used_pending else '' | 2054 else: |
| 2055 return 1 |
| 2056 |
| 2057 revision = revision[:7] |
| 2058 |
| 2059 to_pending = ' to pending queue' if pushed_to_pending else '' |
| 2044 viewvc_url = settings.GetViewVCUrl() | 2060 viewvc_url = settings.GetViewVCUrl() |
| 2045 if viewvc_url and revision: | 2061 if not to_pending: |
| 2046 change_desc.append_footer( | 2062 if viewvc_url and revision: |
| 2047 'Committed%s: %s%s' % (to_pending, viewvc_url, revision)) | 2063 change_desc.append_footer( |
| 2048 elif revision: | 2064 'Committed: %s%s' % (viewvc_url, revision)) |
| 2049 change_desc.append_footer('Committed%s: %s' % (to_pending, revision)) | 2065 elif revision: |
| 2066 change_desc.append_footer('Committed: %s' % (revision,)) |
| 2050 print ('Closing issue ' | 2067 print ('Closing issue ' |
| 2051 '(you may be prompted for your codereview password)...') | 2068 '(you may be prompted for your codereview password)...') |
| 2052 cl.UpdateDescription(change_desc.description) | 2069 cl.UpdateDescription(change_desc.description) |
| 2053 cl.CloseIssue() | 2070 cl.CloseIssue() |
| 2054 props = cl.GetIssueProperties() | 2071 props = cl.GetIssueProperties() |
| 2055 patch_num = len(props['patchsets']) | 2072 patch_num = len(props['patchsets']) |
| 2056 comment = "Committed patchset #%d (id:%d)%s manually as %s" % ( | 2073 comment = "Committed patchset #%d (id:%d)%s manually as %s" % ( |
| 2057 patch_num, props['patchsets'][-1], to_pending, revision) | 2074 patch_num, props['patchsets'][-1], to_pending, revision) |
| 2058 if options.bypass_hooks: | 2075 if options.bypass_hooks: |
| 2059 comment += ' (tree was closed).' if GetTreeStatus() == 'closed' else '.' | 2076 comment += ' (tree was closed).' if GetTreeStatus() == 'closed' else '.' |
| 2060 else: | 2077 else: |
| 2061 comment += ' (presubmit successful).' | 2078 comment += ' (presubmit successful).' |
| 2062 cl.RpcServer().add_comment(cl.GetIssue(), comment) | 2079 cl.RpcServer().add_comment(cl.GetIssue(), comment) |
| 2063 cl.SetIssue(None) | 2080 cl.SetIssue(None) |
| 2064 | 2081 |
| 2065 if used_pending and retcode == 0: | 2082 if pushed_to_pending and retcode == 0: |
| 2066 _, branch = cl.FetchUpstreamTuple(cl.GetBranch()) | 2083 _, branch = cl.FetchUpstreamTuple(cl.GetBranch()) |
| 2067 print 'The commit is in the pending queue (%s).' % pending_ref | 2084 print 'The commit is in the pending queue (%s).' % pending_ref |
| 2068 print ( | 2085 print ( |
| 2069 'It will show up on %s in ~1 min, once it gets Cr-Commit-Position ' | 2086 'It will show up on %s in ~1 min, once it gets Cr-Commit-Position ' |
| 2070 'footer.' % branch) | 2087 'footer.' % branch) |
| 2071 | 2088 |
| 2072 if retcode == 0: | 2089 if retcode == 0: |
| 2073 hook = POSTUPSTREAM_HOOK_PATTERN % cmd | 2090 hook = POSTUPSTREAM_HOOK_PATTERN % cmd |
| 2074 if os.path.isfile(hook): | 2091 if os.path.isfile(hook): |
| 2075 RunCommand([hook, base_branch], error_ok=True) | 2092 RunCommand([hook, merge_base], error_ok=True) |
| 2076 | 2093 |
| 2077 return 0 | 2094 return 0 |
| 2078 | 2095 |
| 2079 | 2096 |
| 2097 def WaitForRealCommit(remote, pushed_commit, local_base_ref, real_ref): |
| 2098 print |
| 2099 print 'Waiting for commit to be landed on %s...' % real_ref |
| 2100 print '(If you are impatient, you may Ctrl-C once without harm)' |
| 2101 target_tree = RunGit(['rev-parse', '%s:' % pushed_commit]).strip() |
| 2102 current_rev = RunGit(['rev-parse', local_base_ref]).strip() |
| 2103 |
| 2104 loop = 0 |
| 2105 while True: |
| 2106 sys.stdout.write('fetching (%d)... \r' % loop) |
| 2107 sys.stdout.flush() |
| 2108 loop += 1 |
| 2109 |
| 2110 RunGit(['retry', 'fetch', remote, real_ref], stderr=subprocess2.VOID) |
| 2111 to_rev = RunGit(['rev-parse', 'FETCH_HEAD']).strip() |
| 2112 commits = RunGit(['rev-list', '%s..%s' % (current_rev, to_rev)]) |
| 2113 for commit in commits.splitlines(): |
| 2114 if RunGit(['rev-parse', '%s:' % commit]).strip() == target_tree: |
| 2115 print 'Found commit on %s' % real_ref |
| 2116 return commit |
| 2117 |
| 2118 current_rev = to_rev |
| 2119 |
| 2120 |
| 2080 def PushToGitPending(remote, pending_ref, upstream_ref): | 2121 def PushToGitPending(remote, pending_ref, upstream_ref): |
| 2081 """Fetches pending_ref, cherry-picks current HEAD on top of it, pushes. | 2122 """Fetches pending_ref, cherry-picks current HEAD on top of it, pushes. |
| 2082 | 2123 |
| 2083 Returns: | 2124 Returns: |
| 2084 (retcode of last operation, output log of last operation). | 2125 (retcode of last operation, output log of last operation). |
| 2085 """ | 2126 """ |
| 2086 assert pending_ref.startswith('refs/'), pending_ref | 2127 assert pending_ref.startswith('refs/'), pending_ref |
| 2087 local_pending_ref = 'refs/git-cl/' + pending_ref[len('refs/'):] | 2128 local_pending_ref = 'refs/git-cl/' + pending_ref[len('refs/'):] |
| 2088 cherry = RunGit(['rev-parse', 'HEAD']).strip() | 2129 cherry = RunGit(['rev-parse', 'HEAD']).strip() |
| 2089 code = 0 | 2130 code = 0 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2117 print 'Please rebase your patch and try again.' | 2158 print 'Please rebase your patch and try again.' |
| 2118 RunGitWithCode(['cherry-pick', '--abort']) | 2159 RunGitWithCode(['cherry-pick', '--abort']) |
| 2119 return code, out | 2160 return code, out |
| 2120 | 2161 |
| 2121 # Applied cleanly, try to push now. Retry on error (flake or non-ff push). | 2162 # Applied cleanly, try to push now. Retry on error (flake or non-ff push). |
| 2122 print 'Pushing commit to %s... It can take a while.' % pending_ref | 2163 print 'Pushing commit to %s... It can take a while.' % pending_ref |
| 2123 code, out = RunGitWithCode( | 2164 code, out = RunGitWithCode( |
| 2124 ['retry', 'push', '--porcelain', remote, 'HEAD:%s' % pending_ref]) | 2165 ['retry', 'push', '--porcelain', remote, 'HEAD:%s' % pending_ref]) |
| 2125 if code == 0: | 2166 if code == 0: |
| 2126 # Success. | 2167 # Success. |
| 2168 print 'Commit pushed to pending ref successfully!' |
| 2127 return code, out | 2169 return code, out |
| 2128 | 2170 |
| 2129 print 'Push failed with exit code %d.' % code | 2171 print 'Push failed with exit code %d.' % code |
| 2130 if out.strip(): | 2172 if out.strip(): |
| 2131 print out.strip() | 2173 print out.strip() |
| 2132 if IsFatalPushFailure(out): | 2174 if IsFatalPushFailure(out): |
| 2133 print ( | 2175 print ( |
| 2134 'Fatal push error. Make sure your .netrc credentials and git ' | 2176 'Fatal push error. Make sure your .netrc credentials and git ' |
| 2135 'user.email are correct and you have push access to the repo.') | 2177 'user.email are correct and you have push access to the repo.') |
| 2136 return code, out | 2178 return code, out |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2765 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 2807 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |
| 2766 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 2808 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
| 2767 | 2809 |
| 2768 | 2810 |
| 2769 if __name__ == '__main__': | 2811 if __name__ == '__main__': |
| 2770 # These affect sys.stdout so do it outside of main() to simplify mocks in | 2812 # These affect sys.stdout so do it outside of main() to simplify mocks in |
| 2771 # unit testing. | 2813 # unit testing. |
| 2772 fix_encoding.fix_encoding() | 2814 fix_encoding.fix_encoding() |
| 2773 colorama.init() | 2815 colorama.init() |
| 2774 sys.exit(main(sys.argv[1:])) | 2816 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |