Chromium Code Reviews| 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 import json | 10 import json |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 dirty = RunGit(['diff-index', '--name-status', 'HEAD']) | 156 dirty = RunGit(['diff-index', '--name-status', 'HEAD']) |
| 157 if dirty: | 157 if dirty: |
| 158 print 'Cannot %s with a dirty tree. You must commit locally first.' % cmd | 158 print 'Cannot %s with a dirty tree. You must commit locally first.' % cmd |
| 159 print 'Uncommitted files: (git diff-index --name-status HEAD)' | 159 print 'Uncommitted files: (git diff-index --name-status HEAD)' |
| 160 print dirty[:4096] | 160 print dirty[:4096] |
| 161 if len(dirty) > 4096: | 161 if len(dirty) > 4096: |
| 162 print '... (run "git diff-index --name-status HEAD" to see full output).' | 162 print '... (run "git diff-index --name-status HEAD" to see full output).' |
| 163 return True | 163 return True |
| 164 return False | 164 return False |
| 165 | 165 |
| 166 | |
| 167 def git_cl_sanity_checks(upstream_git_obj): | |
| 168 """Checks git repo status and ensures diff is from local commits.""" | |
| 169 | |
| 170 # Verify the commit we're diffing against is in our current branch. | |
| 171 upstream_sha = RunGit(['rev-parse', '--verify', upstream_git_obj]).strip() | |
| 172 common_ancestor = RunGit(['merge-base', upstream_sha, 'HEAD']).strip() | |
| 173 if upstream_sha != common_ancestor: | |
| 174 print >> sys.stderr, ( | |
| 175 'ERROR: %s is not in the current branch. You may need to rebase your ' | |
| 176 'tracking branch' % upstream_sha) | |
| 177 return False | |
| 178 | |
| 179 # List the commits inside the diff, and verify they are all local. | |
| 180 commits_in_diff = RunGit( | |
| 181 ['rev-list', '^%s' % upstream_sha, 'HEAD']).splitlines() | |
| 182 commits_in_origin = RunGit( | |
| 183 ['rev-list', '^%s' % upstream_sha, 'remotes/origin/master']).splitlines() | |
|
M-A Ruel
2012/10/28 22:29:52
I don't understand why remotes/origin/master is ha
| |
| 184 | |
| 185 common_commits = set(commits_in_diff) & set(commits_in_origin) | |
| 186 if common_commits: | |
| 187 print >> sys.stderr, ( | |
| 188 'ERROR: Your diff contains %d commits already in origin/master.\n' | |
| 189 'Run "git log --oneline origin/master..HEAD" to get a list of commits ' | |
| 190 'in the diff' % len(common_commits)) | |
| 191 return False | |
| 192 return True | |
| 193 | |
| 194 | |
| 166 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): | 195 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): |
| 167 """Return the corresponding git ref if |base_url| together with |glob_spec| | 196 """Return the corresponding git ref if |base_url| together with |glob_spec| |
| 168 matches the full |url|. | 197 matches the full |url|. |
| 169 | 198 |
| 170 If |allow_wildcards| is true, |glob_spec| can contain wildcards (see below). | 199 If |allow_wildcards| is true, |glob_spec| can contain wildcards (see below). |
| 171 """ | 200 """ |
| 172 fetch_suburl, as_ref = glob_spec.split(':') | 201 fetch_suburl, as_ref = glob_spec.split(':') |
| 173 if allow_wildcards: | 202 if allow_wildcards: |
| 174 glob_match = re.match('(.+/)?(\*|{[^/]*})(/.+)?', fetch_suburl) | 203 glob_match = re.match('(.+/)?(\*|{[^/]*})(/.+)?', fetch_suburl) |
| 175 if glob_match: | 204 if glob_match: |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 if issue: | 629 if issue: |
| 601 RunGit(['config', self._IssueSetting(), str(issue)]) | 630 RunGit(['config', self._IssueSetting(), str(issue)]) |
| 602 if self.rietveld_server: | 631 if self.rietveld_server: |
| 603 RunGit(['config', self._RietveldServer(), self.rietveld_server]) | 632 RunGit(['config', self._RietveldServer(), self.rietveld_server]) |
| 604 else: | 633 else: |
| 605 RunGit(['config', '--unset', self._IssueSetting()]) | 634 RunGit(['config', '--unset', self._IssueSetting()]) |
| 606 self.SetPatchset(0) | 635 self.SetPatchset(0) |
| 607 self.has_issue = False | 636 self.has_issue = False |
| 608 | 637 |
| 609 def GetChange(self, upstream_branch, author): | 638 def GetChange(self, upstream_branch, author): |
| 639 if not git_cl_sanity_checks(upstream_branch): | |
| 640 DieWithError('\nGit sanity check failure') | |
| 641 | |
| 610 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() or '.' | 642 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() or '.' |
| 611 absroot = os.path.abspath(root) | 643 absroot = os.path.abspath(root) |
| 612 | 644 |
| 613 # We use the sha1 of HEAD as a name of this change. | 645 # We use the sha1 of HEAD as a name of this change. |
| 614 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() | 646 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() |
| 615 # Need to pass a relative path for msysgit. | 647 # Need to pass a relative path for msysgit. |
| 616 try: | 648 try: |
| 617 files = scm.GIT.CaptureStatus([root], '.', upstream_branch) | 649 files = scm.GIT.CaptureStatus([root], '.', upstream_branch) |
| 618 except subprocess2.CalledProcessError: | 650 except subprocess2.CalledProcessError: |
| 619 DieWithError( | 651 DieWithError( |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1011 (options, args) = parser.parse_args(args) | 1043 (options, args) = parser.parse_args(args) |
| 1012 | 1044 |
| 1013 if not options.force and is_dirty_git_tree('presubmit'): | 1045 if not options.force and is_dirty_git_tree('presubmit'): |
| 1014 print 'use --force to check even if tree is dirty.' | 1046 print 'use --force to check even if tree is dirty.' |
| 1015 return 1 | 1047 return 1 |
| 1016 | 1048 |
| 1017 cl = Changelist() | 1049 cl = Changelist() |
| 1018 if args: | 1050 if args: |
| 1019 base_branch = args[0] | 1051 base_branch = args[0] |
| 1020 else: | 1052 else: |
| 1021 # Default to diffing against the "upstream" branch. | 1053 # Default to diffing against the common ancestor of the upstream branch. |
| 1022 base_branch = cl.GetUpstreamBranch() | 1054 base_branch = RunGit(['merge-base', cl.GetUpstreamBranch(), 'HEAD']).strip() |
| 1023 | 1055 |
| 1024 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, | 1056 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, |
| 1025 may_prompt=False, verbose=options.verbose, | 1057 may_prompt=False, verbose=options.verbose, |
| 1026 author=None) | 1058 author=None) |
| 1027 return 0 | 1059 return 0 |
| 1028 | 1060 |
| 1029 | 1061 |
| 1030 def AddChangeIdToCommitMessage(options, args): | 1062 def AddChangeIdToCommitMessage(options, args): |
| 1031 """Re-commits using the current message, assumes the commit hook is in | 1063 """Re-commits using the current message, assumes the commit hook is in |
| 1032 place. | 1064 place. |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1209 'See http://goo.gl/JGg0Z for details.\n') | 1241 'See http://goo.gl/JGg0Z for details.\n') |
| 1210 | 1242 |
| 1211 if is_dirty_git_tree('upload'): | 1243 if is_dirty_git_tree('upload'): |
| 1212 return 1 | 1244 return 1 |
| 1213 | 1245 |
| 1214 cl = Changelist() | 1246 cl = Changelist() |
| 1215 if args: | 1247 if args: |
| 1216 # TODO(ukai): is it ok for gerrit case? | 1248 # TODO(ukai): is it ok for gerrit case? |
| 1217 base_branch = args[0] | 1249 base_branch = args[0] |
| 1218 else: | 1250 else: |
| 1219 # Default to diffing against the "upstream" branch. | 1251 # Default to diffing against common ancestor of upstream branch |
| 1220 base_branch = cl.GetUpstreamBranch() | 1252 base_branch = RunGit(['merge-base', cl.GetUpstreamBranch(), 'HEAD']).strip() |
| 1221 args = [base_branch + "..."] | 1253 args = [base_branch] |
| 1222 | 1254 |
| 1223 if not options.bypass_hooks: | 1255 if not options.bypass_hooks: |
| 1224 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, | 1256 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, |
| 1225 may_prompt=not options.force, | 1257 may_prompt=not options.force, |
| 1226 verbose=options.verbose, | 1258 verbose=options.verbose, |
| 1227 author=None) | 1259 author=None) |
| 1228 if not hook_results.should_continue(): | 1260 if not hook_results.should_continue(): |
| 1229 return 1 | 1261 return 1 |
| 1230 if not options.reviewers and hook_results.reviewers: | 1262 if not options.reviewers and hook_results.reviewers: |
| 1231 options.reviewers = hook_results.reviewers | 1263 options.reviewers = hook_results.reviewers |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1649 cl = Changelist() | 1681 cl = Changelist() |
| 1650 if not cl.GetIssue(): | 1682 if not cl.GetIssue(): |
| 1651 parser.error('Need to upload first') | 1683 parser.error('Need to upload first') |
| 1652 | 1684 |
| 1653 if not options.name: | 1685 if not options.name: |
| 1654 options.name = cl.GetBranch() | 1686 options.name = cl.GetBranch() |
| 1655 | 1687 |
| 1656 # Process --bot and --testfilter. | 1688 # Process --bot and --testfilter. |
| 1657 if not options.bot: | 1689 if not options.bot: |
| 1658 # Get try slaves from PRESUBMIT.py files if not specified. | 1690 # Get try slaves from PRESUBMIT.py files if not specified. |
| 1659 change = cl.GetChange(cl.GetUpstreamBranch(), None) | 1691 change = cl.GetChange( |
| 1692 RunGit(['merge-base', cl.GetUpstreamBranch(), 'HEAD']).strip(), | |
| 1693 None) | |
| 1660 options.bot = presubmit_support.DoGetTrySlaves( | 1694 options.bot = presubmit_support.DoGetTrySlaves( |
| 1661 change, | 1695 change, |
| 1662 change.LocalPaths(), | 1696 change.LocalPaths(), |
| 1663 settings.GetRoot(), | 1697 settings.GetRoot(), |
| 1664 None, | 1698 None, |
| 1665 None, | 1699 None, |
| 1666 options.verbose, | 1700 options.verbose, |
| 1667 sys.stdout) | 1701 sys.stdout) |
| 1668 if not options.bot: | 1702 if not options.bot: |
| 1669 parser.error('No default try builder to try, use --bot') | 1703 parser.error('No default try builder to try, use --bot') |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1809 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1843 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
| 1810 | 1844 |
| 1811 # Not a known command. Default to help. | 1845 # Not a known command. Default to help. |
| 1812 GenUsage(parser, 'help') | 1846 GenUsage(parser, 'help') |
| 1813 return CMDhelp(parser, argv) | 1847 return CMDhelp(parser, argv) |
| 1814 | 1848 |
| 1815 | 1849 |
| 1816 if __name__ == '__main__': | 1850 if __name__ == '__main__': |
| 1817 fix_encoding.fix_encoding() | 1851 fix_encoding.fix_encoding() |
| 1818 sys.exit(main(sys.argv[1:])) | 1852 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |