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 |