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 2070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2081 """Fetches pending_ref, cherry-picks current HEAD on top of it, pushes. | 2081 """Fetches pending_ref, cherry-picks current HEAD on top of it, pushes. |
2082 | 2082 |
2083 Returns: | 2083 Returns: |
2084 (retcode of last operation, output log of last operation). | 2084 (retcode of last operation, output log of last operation). |
2085 """ | 2085 """ |
2086 assert pending_ref.startswith('refs/'), pending_ref | 2086 assert pending_ref.startswith('refs/'), pending_ref |
2087 local_pending_ref = 'refs/git-cl/' + pending_ref[len('refs/'):] | 2087 local_pending_ref = 'refs/git-cl/' + pending_ref[len('refs/'):] |
2088 cherry = RunGit(['rev-parse', 'HEAD']).strip() | 2088 cherry = RunGit(['rev-parse', 'HEAD']).strip() |
2089 code = 0 | 2089 code = 0 |
2090 out = '' | 2090 out = '' |
2091 attempt = 0 | 2091 max_attempts = 3 |
2092 while attempt < 5: | 2092 attempts_left = max_attempts |
2093 attempt += 1 | 2093 while attempts_left: |
2094 if attempts_left != max_attempts: | |
2095 print 'Retrying, %d attempts left...' % (attempts_left - 1,) | |
2096 attempts_left -= 1 | |
2094 | 2097 |
2095 # Fetch. Retry fetch errors. | 2098 # Fetch. Retry fetch errors. |
2099 print 'Fetching pending ref %s...' % pending_ref | |
2096 code, out = RunGitWithCode( | 2100 code, out = RunGitWithCode( |
2097 ['retry', 'fetch', remote, '+%s:%s' % (pending_ref, local_pending_ref)], | 2101 ['retry', 'fetch', remote, '+%s:%s' % (pending_ref, local_pending_ref)]) |
2098 suppress_stderr=True) | |
2099 if code: | 2102 if code: |
2103 print 'Fetch failed with exit code %d.' % code | |
2104 if out.strip(): | |
2105 print out.strip() | |
2100 continue | 2106 continue |
2101 | 2107 |
2102 # Try to cherry pick. Abort on merge conflicts. | 2108 # Try to cherry pick. Abort on merge conflicts. |
2109 print 'Cherry-picking commit on top of pending ref...' | |
2103 RunGitWithCode(['checkout', local_pending_ref], suppress_stderr=True) | 2110 RunGitWithCode(['checkout', local_pending_ref], suppress_stderr=True) |
2104 code, out = RunGitWithCode(['cherry-pick', cherry], suppress_stderr=True) | 2111 code, out = RunGitWithCode(['cherry-pick', cherry]) |
2105 if code: | 2112 if code: |
2106 print ( | 2113 print ( |
2107 'Your patch doesn\'t apply cleanly to upstream ref \'%s\', ' | 2114 'Your patch doesn\'t apply cleanly to ref \'%s\', ' |
2108 'the following files have merge conflicts:' % upstream_ref) | 2115 'the following files have merge conflicts:' % pending_ref) |
2109 print RunGit(['diff', '--name-status', '--diff-filter=U']).strip() | 2116 print RunGit(['diff', '--name-status', '--diff-filter=U']).strip() |
2110 print 'Please rebase your patch and try again.' | 2117 print 'Please rebase your patch and try again.' |
2111 RunGitWithCode(['cherry-pick', '--abort'], suppress_stderr=True) | 2118 RunGitWithCode(['cherry-pick', '--abort']) |
2112 return code, out | 2119 return code, out |
2113 | 2120 |
2114 # Applied cleanly, try to push now. Retry on error (flake or non-ff push). | 2121 # 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 | |
2115 code, out = RunGitWithCode( | 2123 code, out = RunGitWithCode( |
2116 ['retry', 'push', '--porcelain', remote, 'HEAD:%s' % pending_ref]) | 2124 ['retry', 'push', '--porcelain', remote, 'HEAD:%s' % pending_ref]) |
2117 if code == 0: | 2125 if code == 0: |
2118 # Success. | 2126 # Success. |
2119 return code, out | 2127 return code, out |
2120 | 2128 |
2129 print 'Push failed with exit code %d.' % code | |
2130 if out.strip(): | |
2131 print out.strip() | |
Vadim Sh.
2014/08/26 21:12:05
that was the most crucial missing part, for whatev
| |
2132 if IsFatalPushFailure(out): | |
2133 print ( | |
2134 'Fatal push error. Make sure your .netrc credentials and git ' | |
2135 'user.email are correct and you have push access to the repo.') | |
2136 return code, out | |
2137 | |
2138 print 'All attempts to push to pending ref failed.' | |
2121 return code, out | 2139 return code, out |
2122 | 2140 |
2123 | 2141 |
2142 def IsFatalPushFailure(push_stdout): | |
2143 """True if retrying push won't help.""" | |
2144 return '(prohibited by Gerrit)' in push_stdout | |
2145 | |
2146 | |
2124 @subcommand.usage('[upstream branch to apply against]') | 2147 @subcommand.usage('[upstream branch to apply against]') |
2125 def CMDdcommit(parser, args): | 2148 def CMDdcommit(parser, args): |
2126 """Commits the current changelist via git-svn.""" | 2149 """Commits the current changelist via git-svn.""" |
2127 if not settings.GetIsGitSvn(): | 2150 if not settings.GetIsGitSvn(): |
2128 message = """This doesn't appear to be an SVN repository. | 2151 message = """This doesn't appear to be an SVN repository. |
2129 If your project has a git mirror with an upstream SVN master, you probably need | 2152 If your project has a git mirror with an upstream SVN master, you probably need |
2130 to run 'git svn init', see your project's git mirror documentation. | 2153 to run 'git svn init', see your project's git mirror documentation. |
2131 If your project has a true writeable upstream repository, you probably want | 2154 If your project has a true writeable upstream repository, you probably want |
2132 to run 'git cl land' instead. | 2155 to run 'git cl land' instead. |
2133 Choose wisely, if you get this wrong, your commit might appear to succeed but | 2156 Choose wisely, if you get this wrong, your commit might appear to succeed but |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2742 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 2765 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |
2743 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 2766 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
2744 | 2767 |
2745 | 2768 |
2746 if __name__ == '__main__': | 2769 if __name__ == '__main__': |
2747 # These affect sys.stdout so do it outside of main() to simplify mocks in | 2770 # These affect sys.stdout so do it outside of main() to simplify mocks in |
2748 # unit testing. | 2771 # unit testing. |
2749 fix_encoding.fix_encoding() | 2772 fix_encoding.fix_encoding() |
2750 colorama.init() | 2773 colorama.init() |
2751 sys.exit(main(sys.argv[1:])) | 2774 sys.exit(main(sys.argv[1:])) |
OLD | NEW |