| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # git-cl -- a git-command for integrating reviews on Rietveld | 2 # git-cl -- a git-command for integrating reviews on Rietveld |
| 3 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 3 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
| 4 | 4 |
| 5 import errno | 5 import errno |
| 6 import logging | 6 import logging |
| 7 import optparse | 7 import optparse |
| 8 import os | 8 import os |
| 9 import re | 9 import re |
| 10 import subprocess | 10 import subprocess |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 ['config', '--get-regexp', r'^svn-remote\.'])[0] == 0 | 155 ['config', '--get-regexp', r'^svn-remote\.'])[0] == 0 |
| 156 return self.is_git_svn | 156 return self.is_git_svn |
| 157 | 157 |
| 158 def GetSVNBranch(self): | 158 def GetSVNBranch(self): |
| 159 if self.svn_branch is None: | 159 if self.svn_branch is None: |
| 160 if not self.GetIsGitSvn(): | 160 if not self.GetIsGitSvn(): |
| 161 DieWithError('Repo doesn\'t appear to be a git-svn repo.') | 161 DieWithError('Repo doesn\'t appear to be a git-svn repo.') |
| 162 | 162 |
| 163 # Try to figure out which remote branch we're based on. | 163 # Try to figure out which remote branch we're based on. |
| 164 # Strategy: | 164 # Strategy: |
| 165 # 1) find all git-svn branches and note their svn URLs. | 165 # 1) iterate through our branch history and find the svn URL. |
| 166 # 2) iterate through our branch history and match up the URLs. | 166 # 2) find the svn-remote that fetches from the URL. |
| 167 | 167 |
| 168 # regexp matching the git-svn line that contains the URL. | 168 # regexp matching the git-svn line that contains the URL. |
| 169 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) | 169 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) |
| 170 | 170 |
| 171 # Get the refname and svn url for all refs/remotes/*. | 171 # We don't want to go through all of history, so read a line from the |
| 172 remotes = RunGit(['for-each-ref', '--format=%(refname)', | 172 # pipe at a time. |
| 173 'refs/remotes']).splitlines() | 173 # The -100 is an arbitrary limit so we don't search forever. |
| 174 svn_refs = {} | 174 cmd = ['git', 'log', '-100', '--pretty=medium'] |
| 175 for ref in remotes: | 175 proc = Popen(cmd, stdout=subprocess.PIPE) |
| 176 match = git_svn_re.search(RunGit(['cat-file', '-p', ref])) | 176 for line in proc.stdout: |
| 177 # Prefer origin/HEAD over all others. | 177 match = git_svn_re.match(line) |
| 178 if match and (match.group(1) not in svn_refs or | 178 if match: |
| 179 ref == "refs/remotes/origin/HEAD"): | 179 url = match.group(1) |
| 180 svn_refs[match.group(1)] = ref | 180 proc.stdout.close() # Cut pipe. |
| 181 break |
| 181 | 182 |
| 182 if len(svn_refs) == 1: | 183 if url: |
| 183 # Only one svn branch exists -- seems like a good candidate. | 184 svn_remote_re = re.compile(r'^svn-remote\.([^.]+)\.url (.*)$') |
| 184 self.svn_branch = svn_refs.values()[0] | 185 remotes = RunGit(['config', '--get-regexp', |
| 185 elif len(svn_refs) > 1: | 186 r'^svn-remote\..*\.url']).splitlines() |
| 186 # We have more than one remote branch available. We don't | 187 for remote in remotes: |
| 187 # want to go through all of history, so read a line from the | 188 match = svn_remote_re.match(remote) |
| 188 # pipe at a time. | |
| 189 # The -100 is an arbitrary limit so we don't search forever. | |
| 190 cmd = ['git', 'log', '-100', '--pretty=medium'] | |
| 191 proc = Popen(cmd, stdout=subprocess.PIPE) | |
| 192 for line in proc.stdout: | |
| 193 match = git_svn_re.match(line) | |
| 194 if match: | 189 if match: |
| 195 url = match.group(1) | 190 remote = match.group(1) |
| 196 if url in svn_refs: | 191 base_url = match.group(2) |
| 197 self.svn_branch = svn_refs[url] | 192 fetch_spec = RunGit( |
| 198 proc.stdout.close() # Cut pipe. | 193 ['config', 'svn-remote.'+remote+'.fetch']).strip().split(':') |
| 194 if fetch_spec[0]: |
| 195 full_url = base_url + '/' + fetch_spec[0] |
| 196 else: |
| 197 full_url = base_url |
| 198 if full_url == url: |
| 199 self.svn_branch = fetch_spec[1] |
| 199 break | 200 break |
| 200 | 201 |
| 201 if not self.svn_branch: | 202 if not self.svn_branch: |
| 202 DieWithError('Can\'t guess svn branch -- try specifying it on the ' | 203 DieWithError('Can\'t guess svn branch -- try specifying it on the ' |
| 203 'command line') | 204 'command line') |
| 204 | 205 |
| 205 return self.svn_branch | 206 return self.svn_branch |
| 206 | 207 |
| 207 def GetTreeStatusUrl(self, error_ok=False): | 208 def GetTreeStatusUrl(self, error_ok=False): |
| 208 if not self.tree_status_url: | 209 if not self.tree_status_url: |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 """Returns a tuple containg remote and remote ref, | 294 """Returns a tuple containg remote and remote ref, |
| 294 e.g. 'origin', 'refs/heads/master' | 295 e.g. 'origin', 'refs/heads/master' |
| 295 """ | 296 """ |
| 296 remote = '.' | 297 remote = '.' |
| 297 branch = self.GetBranch() | 298 branch = self.GetBranch() |
| 298 upstream_branch = RunGit(['config', 'branch.%s.merge' % branch], | 299 upstream_branch = RunGit(['config', 'branch.%s.merge' % branch], |
| 299 error_ok=True).strip() | 300 error_ok=True).strip() |
| 300 if upstream_branch: | 301 if upstream_branch: |
| 301 remote = RunGit(['config', 'branch.%s.remote' % branch]).strip() | 302 remote = RunGit(['config', 'branch.%s.remote' % branch]).strip() |
| 302 else: | 303 else: |
| 303 # Fall back on trying a git-svn upstream branch. | 304 upstream_branch = RunGit(['config', 'rietveld.upstream-branch'], |
| 304 if settings.GetIsGitSvn(): | 305 error_ok=True).strip() |
| 305 upstream_branch = settings.GetSVNBranch() | 306 if upstream_branch: |
| 307 remote = RunGit(['config', 'rietveld.upstream-remote']).strip() |
| 306 else: | 308 else: |
| 307 # Else, try to guess the origin remote. | 309 # Fall back on trying a git-svn upstream branch. |
| 308 remote_branches = RunGit(['branch', '-r']).split() | 310 if settings.GetIsGitSvn(): |
| 309 if 'origin/master' in remote_branches: | 311 upstream_branch = settings.GetSVNBranch() |
| 310 # Fall back on origin/master if it exits. | |
| 311 remote = 'origin' | |
| 312 upstream_branch = 'refs/heads/master' | |
| 313 elif 'origin/trunk' in remote_branches: | |
| 314 # Fall back on origin/trunk if it exists. Generally a shared | |
| 315 # git-svn clone | |
| 316 remote = 'origin' | |
| 317 upstream_branch = 'refs/heads/trunk' | |
| 318 else: | 312 else: |
| 319 DieWithError("""Unable to determine default branch to diff against. | 313 # Else, try to guess the origin remote. |
| 314 remote_branches = RunGit(['branch', '-r']).split() |
| 315 if 'origin/master' in remote_branches: |
| 316 # Fall back on origin/master if it exits. |
| 317 remote = 'origin' |
| 318 upstream_branch = 'refs/heads/master' |
| 319 elif 'origin/trunk' in remote_branches: |
| 320 # Fall back on origin/trunk if it exists. Generally a shared |
| 321 # git-svn clone |
| 322 remote = 'origin' |
| 323 upstream_branch = 'refs/heads/trunk' |
| 324 else: |
| 325 DieWithError("""Unable to determine default branch to diff against. |
| 320 Either pass complete "git diff"-style arguments, like | 326 Either pass complete "git diff"-style arguments, like |
| 321 git cl upload origin/master | 327 git cl upload origin/master |
| 322 or verify this branch is set up to track another (via the --track argument to | 328 or verify this branch is set up to track another (via the --track argument to |
| 323 "git checkout -b ...").""") | 329 "git checkout -b ...").""") |
| 324 | 330 |
| 325 return remote, upstream_branch | 331 return remote, upstream_branch |
| 326 | 332 |
| 327 def GetUpstreamBranch(self): | 333 def GetUpstreamBranch(self): |
| 328 if self.upstream_branch is None: | 334 if self.upstream_branch is None: |
| 329 remote, upstream_branch = self.FetchUpstreamTuple() | 335 remote, upstream_branch = self.FetchUpstreamTuple() |
| (...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 1278 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |
| 1273 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1279 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
| 1274 | 1280 |
| 1275 # Not a known command. Default to help. | 1281 # Not a known command. Default to help. |
| 1276 GenUsage(parser, 'help') | 1282 GenUsage(parser, 'help') |
| 1277 return CMDhelp(parser, argv) | 1283 return CMDhelp(parser, argv) |
| 1278 | 1284 |
| 1279 | 1285 |
| 1280 if __name__ == '__main__': | 1286 if __name__ == '__main__': |
| 1281 sys.exit(main(sys.argv[1:])) | 1287 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |