Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: git_cl.py

Issue 1891233003: Support getting changes of non-HEAD branches (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@branch-to-cl
Patch Set: fix Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | presubmit_support.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 and Gerrit.""" 8 """A git-command for integrating reviews on Rietveld and Gerrit."""
9 9
10 from distutils.version import LooseVersion 10 from distutils.version import LooseVersion
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 return RunGit(['config', param], **kwargs).strip() 821 return RunGit(['config', param], **kwargs).strip()
822 822
823 823
824 def ShortBranchName(branch): 824 def ShortBranchName(branch):
825 """Convert a name like 'refs/heads/foo' to just 'foo'.""" 825 """Convert a name like 'refs/heads/foo' to just 'foo'."""
826 return branch.replace('refs/heads/', '', 1) 826 return branch.replace('refs/heads/', '', 1)
827 827
828 828
829 def GetCurrentBranchRef(): 829 def GetCurrentBranchRef():
830 """Returns branch ref (e.g., refs/heads/master) or None.""" 830 """Returns branch ref (e.g., refs/heads/master) or None."""
831 return RunGit(['symbolic-ref', 'HEAD'], 831 ref = RunGit(['symbolic-ref', 'HEAD'],
832 stderr=subprocess2.VOID, error_ok=True).strip() or None 832 stderr=subprocess2.VOID, error_ok=True).strip() or None
833 if ref and not ref.startswith('refs/heads/'):
834 ref = 'refs/heads/'+ref
835 return ref
833 836
834 837
835 def GetCurrentBranch(): 838 def GetCurrentBranch():
836 """Returns current branch or None. 839 """Returns current branch or None.
837 840
838 For refs/heads/* branches, returns just last part. For others, full ref. 841 For refs/heads/* branches, returns just last part. For others, full ref.
839 """ 842 """
840 branchref = GetCurrentBranchRef() 843 branchref = GetCurrentBranchRef()
841 if branchref: 844 if branchref:
842 return ShortBranchName(branchref) 845 return ShortBranchName(branchref)
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 GIT_INSTRUCTIONS_URL) 1108 GIT_INSTRUCTIONS_URL)
1106 branch = 'HEAD' 1109 branch = 'HEAD'
1107 if branch.startswith('refs/remotes'): 1110 if branch.startswith('refs/remotes'):
1108 self._remote = (remote, branch) 1111 self._remote = (remote, branch)
1109 elif branch.startswith('refs/branch-heads/'): 1112 elif branch.startswith('refs/branch-heads/'):
1110 self._remote = (remote, branch.replace('refs/', 'refs/remotes/')) 1113 self._remote = (remote, branch.replace('refs/', 'refs/remotes/'))
1111 else: 1114 else:
1112 self._remote = (remote, 'refs/remotes/%s/%s' % (remote, branch)) 1115 self._remote = (remote, 'refs/remotes/%s/%s' % (remote, branch))
1113 return self._remote 1116 return self._remote
1114 1117
1115 def GitSanityChecks(self, upstream_git_obj): 1118 def GitSanityChecks(self, upstream_git_obj, local_ref='HEAD'):
1116 """Checks git repo status and ensures diff is from local commits.""" 1119 """Checks git repo status and ensures diff is from local commits."""
1117 1120
1118 if upstream_git_obj is None: 1121 if upstream_git_obj is None:
1119 if self.GetBranch() is None: 1122 if self.GetBranch() is None:
1120 print >> sys.stderr, ( 1123 print >> sys.stderr, (
1121 'ERROR: unable to determine current branch (detached HEAD?)') 1124 'ERROR: unable to determine current branch (detached HEAD?)')
1122 else: 1125 else:
1123 print >> sys.stderr, ( 1126 print >> sys.stderr, (
1124 'ERROR: no upstream branch') 1127 'ERROR: no upstream branch')
1125 return False 1128 return False
1126 1129
1127 # Verify the commit we're diffing against is in our current branch. 1130 # Verify the commit we're diffing against is in our current branch.
1128 upstream_sha = RunGit(['rev-parse', '--verify', upstream_git_obj]).strip() 1131 upstream_sha = RunGit(['rev-parse', '--verify', upstream_git_obj]).strip()
1129 common_ancestor = RunGit(['merge-base', upstream_sha, 'HEAD']).strip() 1132 common_anc = RunGit(['merge-base', upstream_sha, local_ref]).strip()
1130 if upstream_sha != common_ancestor: 1133 if upstream_sha != common_anc:
1131 print >> sys.stderr, ( 1134 print >> sys.stderr, (
1132 'ERROR: %s is not in the current branch. You may need to rebase ' 1135 'ERROR: %s is not in the current branch. You may need to rebase '
1133 'your tracking branch' % upstream_sha) 1136 'your tracking branch' % upstream_sha)
1134 return False 1137 return False
1135 1138
1136 # List the commits inside the diff, and verify they are all local. 1139 # List the commits inside the diff, and verify they are all local.
1137 commits_in_diff = RunGit( 1140 commits_in_diff = RunGit(
1138 ['rev-list', '^%s' % upstream_sha, 'HEAD']).splitlines() 1141 ['rev-list', '^%s' % upstream_sha, local_ref]).splitlines()
1139 code, remote_branch = RunGitWithCode(['config', 'gitcl.remotebranch']) 1142 code, remote_branch = RunGitWithCode(['config', 'gitcl.remotebranch'])
1140 remote_branch = remote_branch.strip() 1143 remote_branch = remote_branch.strip()
1141 if code != 0: 1144 if code != 0:
1142 _, remote_branch = self.GetRemoteBranch() 1145 _, remote_branch = self.GetRemoteBranch()
1143 1146
1144 commits_in_remote = RunGit( 1147 commits_in_remote = RunGit(
1145 ['rev-list', '^%s' % upstream_sha, remote_branch]).splitlines() 1148 ['rev-list', '^%s' % upstream_sha, remote_branch]).splitlines()
1146 1149
1147 common_commits = set(commits_in_diff) & set(commits_in_remote) 1150 common_commits = set(commits_in_diff) & set(commits_in_remote)
1148 if common_commits: 1151 if common_commits:
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 if codereview_server: 1254 if codereview_server:
1252 RunGit(['config', codereview_setting, codereview_server]) 1255 RunGit(['config', codereview_setting, codereview_server])
1253 else: 1256 else:
1254 current_issue = self.GetIssue() 1257 current_issue = self.GetIssue()
1255 if current_issue: 1258 if current_issue:
1256 RunGit(['config', '--unset', issue_setting]) 1259 RunGit(['config', '--unset', issue_setting])
1257 self.issue = None 1260 self.issue = None
1258 self.SetPatchset(None) 1261 self.SetPatchset(None)
1259 1262
1260 def GetChange(self, upstream_branch, author): 1263 def GetChange(self, upstream_branch, author):
1261 if not self.GitSanityChecks(upstream_branch): 1264 local_ref = self.GetBranchRef()
1265 if not self.GitSanityChecks(upstream_branch, local_ref):
1262 DieWithError('\nGit sanity check failure') 1266 DieWithError('\nGit sanity check failure')
1263 1267
1264 root = settings.GetRelativeRoot() 1268 root = settings.GetRelativeRoot()
1265 if not root: 1269 if not root:
1266 root = '.' 1270 root = '.'
1267 absroot = os.path.abspath(root) 1271 absroot = os.path.abspath(root)
1268 1272
1269 # We use the sha1 of HEAD as a name of this change. 1273 # We use the sha1 of HEAD as a name of this change.
1270 name = RunGitWithCode(['rev-parse', 'HEAD'])[1].strip() 1274 name = RunGitWithCode(['rev-parse', local_ref])[1].strip()
1271 # Need to pass a relative path for msysgit. 1275 # Need to pass a relative path for msysgit.
1272 try: 1276 try:
1273 files = scm.GIT.CaptureStatus([root], '.', upstream_branch) 1277 files = scm.GIT.CaptureStatus([root], '.', upstream_branch, local_ref)
1274 except subprocess2.CalledProcessError: 1278 except subprocess2.CalledProcessError:
1275 DieWithError( 1279 DieWithError(
1276 ('\nFailed to diff against upstream branch %s\n\n' 1280 ('\nFailed to diff against upstream branch %s\n\n'
1277 'This branch probably doesn\'t exist anymore. To reset the\n' 1281 'This branch probably doesn\'t exist anymore. To reset the\n'
1278 'tracking branch, please run\n' 1282 'tracking branch, please run\n'
1279 ' git branch --set-upstream %s trunk\n' 1283 ' git branch --set-upstream %s trunk\n'
1280 'replacing trunk with origin/master or the relevant branch') % 1284 'replacing trunk with origin/master or the relevant branch') %
1281 (upstream_branch, self.GetBranch())) 1285 (upstream_branch, self.GetBranch()))
1282 1286
1283 issue = self.GetIssue() 1287 issue = self.GetIssue()
1284 patchset = self.GetPatchset() 1288 patchset = self.GetPatchset()
1285 if issue: 1289 if issue:
1286 description = self.GetDescription() 1290 description = self.GetDescription()
1287 else: 1291 else:
1288 # If the change was never uploaded, use the log messages of all commits 1292 # If the change was never uploaded, use the log messages of all commits
1289 # up to the branch point, as git cl upload will prefill the description 1293 # up to the branch point, as git cl upload will prefill the description
1290 # with these log messages. 1294 # with these log messages.
1291 args = ['log', '--pretty=format:%s%n%n%b', '%s...' % (upstream_branch)] 1295 args = ['log', '--pretty=format:%s%n%n%b',
1296 '%s...%s' % (upstream_branch, local_ref)]
1292 description = RunGitWithCode(args)[1].strip() 1297 description = RunGitWithCode(args)[1].strip()
1293 1298
1294 if not author: 1299 if not author:
1295 author = RunGit(['config', 'user.email']).strip() or None 1300 author = RunGit(['config', 'user.email']).strip() or None
1296 return presubmit_support.GitChange( 1301 return presubmit_support.GitChange(
1297 name, 1302 name,
1298 description, 1303 description,
1299 absroot, 1304 absroot,
1300 files, 1305 files,
1301 issue, 1306 issue,
1302 patchset, 1307 patchset,
1303 author, 1308 author,
1304 upstream=upstream_branch) 1309 upstream=upstream_branch,
1310 local_ref=local_ref)
1305 1311
1306 def UpdateDescription(self, description): 1312 def UpdateDescription(self, description):
1307 self.description = description 1313 self.description = description
1308 return self._codereview_impl.UpdateDescriptionRemote(description) 1314 return self._codereview_impl.UpdateDescriptionRemote(description)
1309 1315
1310 def RunHook(self, committing, may_prompt, verbose, change): 1316 def RunHook(self, committing, may_prompt, verbose, change):
1311 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" 1317 """Calls sys.exit() if the hook fails; returns a HookResults otherwise."""
1312 try: 1318 try:
1313 return presubmit_support.DoPresubmitChecks(change, committing, 1319 return presubmit_support.DoPresubmitChecks(change, committing,
1314 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, 1320 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin,
(...skipping 3505 matching lines...) Expand 10 before | Expand all | Expand 10 after
4820 if __name__ == '__main__': 4826 if __name__ == '__main__':
4821 # These affect sys.stdout so do it outside of main() to simplify mocks in 4827 # These affect sys.stdout so do it outside of main() to simplify mocks in
4822 # unit testing. 4828 # unit testing.
4823 fix_encoding.fix_encoding() 4829 fix_encoding.fix_encoding()
4824 setup_color.init() 4830 setup_color.init()
4825 try: 4831 try:
4826 sys.exit(main(sys.argv[1:])) 4832 sys.exit(main(sys.argv[1:]))
4827 except KeyboardInterrupt: 4833 except KeyboardInterrupt:
4828 sys.stderr.write('interrupted\n') 4834 sys.stderr.write('interrupted\n')
4829 sys.exit(1) 4835 sys.exit(1)
OLDNEW
« no previous file with comments | « no previous file | presubmit_support.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698