Commit ade368c4 authored by bauerb@chromium.org's avatar bauerb@chromium.org

Add configuration option for upstream branch and improve guessing the svn branch.

The svn branch heuristic does roughly the same thing git-svn does: We first iterate backwards over the history to find the svn URL (like svn://svn.chromium.org/chrome/trunk/src). Then we go through all defined svn-remote section looking for one where the URL is the root of the svn URL (svn://svn.chromium.org/chrome in that case), and the fetch spec looks like "trunk/src:remotes/origin/trunk". If the base URL + left part (trunk/src) is the full URL, the right part (remotes/origin/trunk) is the git ref that is updated when we do a `git svn fetch`! This works for git-svn branches that fetch from trunk as well as milestone branches.

BUG=none
TEST=none

Review URL: http://codereview.chromium.org/6597004

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@76364 0039d316-1c4b-4281-b951-d872f2087c98
parent 2a009624
......@@ -162,40 +162,41 @@ class Settings(object):
# Try to figure out which remote branch we're based on.
# Strategy:
# 1) find all git-svn branches and note their svn URLs.
# 2) iterate through our branch history and match up the URLs.
# 1) iterate through our branch history and find the svn URL.
# 2) find the svn-remote that fetches from the URL.
# regexp matching the git-svn line that contains the URL.
git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE)
# Get the refname and svn url for all refs/remotes/*.
remotes = RunGit(['for-each-ref', '--format=%(refname)',
'refs/remotes']).splitlines()
svn_refs = {}
for ref in remotes:
match = git_svn_re.search(RunGit(['cat-file', '-p', ref]))
# Prefer origin/HEAD over all others.
if match and (match.group(1) not in svn_refs or
ref == "refs/remotes/origin/HEAD"):
svn_refs[match.group(1)] = ref
if len(svn_refs) == 1:
# Only one svn branch exists -- seems like a good candidate.
self.svn_branch = svn_refs.values()[0]
elif len(svn_refs) > 1:
# We have more than one remote branch available. We don't
# want to go through all of history, so read a line from the
# pipe at a time.
# The -100 is an arbitrary limit so we don't search forever.
cmd = ['git', 'log', '-100', '--pretty=medium']
proc = Popen(cmd, stdout=subprocess.PIPE)
for line in proc.stdout:
match = git_svn_re.match(line)
# We don't want to go through all of history, so read a line from the
# pipe at a time.
# The -100 is an arbitrary limit so we don't search forever.
cmd = ['git', 'log', '-100', '--pretty=medium']
proc = Popen(cmd, stdout=subprocess.PIPE)
for line in proc.stdout:
match = git_svn_re.match(line)
if match:
url = match.group(1)
proc.stdout.close() # Cut pipe.
break
if url:
svn_remote_re = re.compile(r'^svn-remote\.([^.]+)\.url (.*)$')
remotes = RunGit(['config', '--get-regexp',
r'^svn-remote\..*\.url']).splitlines()
for remote in remotes:
match = svn_remote_re.match(remote)
if match:
url = match.group(1)
if url in svn_refs:
self.svn_branch = svn_refs[url]
proc.stdout.close() # Cut pipe.
remote = match.group(1)
base_url = match.group(2)
fetch_spec = RunGit(
['config', 'svn-remote.'+remote+'.fetch']).strip().split(':')
if fetch_spec[0]:
full_url = base_url + '/' + fetch_spec[0]
else:
full_url = base_url
if full_url == url:
self.svn_branch = fetch_spec[1]
break
if not self.svn_branch:
......@@ -300,23 +301,28 @@ class Changelist(object):
if upstream_branch:
remote = RunGit(['config', 'branch.%s.remote' % branch]).strip()
else:
# Fall back on trying a git-svn upstream branch.
if settings.GetIsGitSvn():
upstream_branch = settings.GetSVNBranch()
upstream_branch = RunGit(['config', 'rietveld.upstream-branch'],
error_ok=True).strip()
if upstream_branch:
remote = RunGit(['config', 'rietveld.upstream-remote']).strip()
else:
# Else, try to guess the origin remote.
remote_branches = RunGit(['branch', '-r']).split()
if 'origin/master' in remote_branches:
# Fall back on origin/master if it exits.
remote = 'origin'
upstream_branch = 'refs/heads/master'
elif 'origin/trunk' in remote_branches:
# Fall back on origin/trunk if it exists. Generally a shared
# git-svn clone
remote = 'origin'
upstream_branch = 'refs/heads/trunk'
# Fall back on trying a git-svn upstream branch.
if settings.GetIsGitSvn():
upstream_branch = settings.GetSVNBranch()
else:
DieWithError("""Unable to determine default branch to diff against.
# Else, try to guess the origin remote.
remote_branches = RunGit(['branch', '-r']).split()
if 'origin/master' in remote_branches:
# Fall back on origin/master if it exits.
remote = 'origin'
upstream_branch = 'refs/heads/master'
elif 'origin/trunk' in remote_branches:
# Fall back on origin/trunk if it exists. Generally a shared
# git-svn clone
remote = 'origin'
upstream_branch = 'refs/heads/trunk'
else:
DieWithError("""Unable to determine default branch to diff against.
Either pass complete "git diff"-style arguments, like
git cl upload origin/master
or verify this branch is set up to track another (via the --track argument to
......
......@@ -144,45 +144,42 @@ class GIT(object):
"""Returns the svn branch name if found."""
# Try to figure out which remote branch we're based on.
# Strategy:
# 1) find all git-svn branches and note their svn URLs.
# 2) iterate through our branch history and match up the URLs.
# 1) iterate through our branch history and find the svn URL.
# 2) find the svn-remote that fetches from the URL.
# regexp matching the git-svn line that contains the URL.
git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE)
# Get the refname and svn url for all refs/remotes/*.
remotes = GIT.Capture(
['for-each-ref', '--format=%(refname)', 'refs/remotes'],
cwd=cwd).splitlines()
svn_refs = {}
for ref in remotes:
match = git_svn_re.search(
GIT.Capture(['cat-file', '-p', ref], cwd=cwd))
# Prefer origin/HEAD over all others.
if match and (match.group(1) not in svn_refs or
ref == "refs/remotes/origin/HEAD"):
svn_refs[match.group(1)] = ref
svn_branch = ''
if len(svn_refs) == 1:
# Only one svn branch exists -- seems like a good candidate.
svn_branch = svn_refs.values()[0]
elif len(svn_refs) > 1:
# We have more than one remote branch available. We don't
# want to go through all of history, so read a line from the
# pipe at a time.
# The -100 is an arbitrary limit so we don't search forever.
cmd = ['git', 'log', '-100', '--pretty=medium']
proc = gclient_utils.Popen(cmd, stdout=subprocess.PIPE, cwd=cwd)
for line in proc.stdout:
match = git_svn_re.match(line)
# We don't want to go through all of history, so read a line from the
# pipe at a time.
# The -100 is an arbitrary limit so we don't search forever.
cmd = ['git', 'log', '-100', '--pretty=medium']
proc = gclient_utils.Popen(cmd, stdout=subprocess.PIPE)
for line in proc.stdout:
match = git_svn_re.match(line)
if match:
url = match.group(1)
proc.stdout.close() # Cut pipe.
break
if url:
svn_remote_re = re.compile(r'^svn-remote\.([^.]+)\.url (.*)$')
remotes = GIT.Capture(['config', '--get-regexp',
r'^svn-remote\..*\.url'], cwd=cwd).splitlines()
for remote in remotes:
match = svn_remote_re.match(remote)
if match:
url = match.group(1)
if url in svn_refs:
svn_branch = svn_refs[url]
proc.stdout.close() # Cut pipe.
break
return svn_branch
remote = match.group(1)
base_url = match.group(2)
fetch_spec = GIT.Capture(
['config', 'svn-remote.%s.fetch' % remote],
cwd=cwd).strip().split(':')
if fetch_spec[0]:
full_url = base_url + '/' + fetch_spec[0]
else:
full_url = base_url
if full_url == url:
return fetch_spec[1]
@staticmethod
def FetchUpstreamTuple(cwd):
......@@ -204,25 +201,37 @@ class GIT(object):
except gclient_utils.Error:
pass
else:
# Fall back on trying a git-svn upstream branch.
if GIT.IsGitSvn(cwd):
upstream_branch = GIT.GetSVNBranch(cwd)
try:
upstream_branch = GIT.Capture(
['config', 'rietveld.upstream-branch'], cwd=cwd).strip()
except gclient_utils.Error:
upstream_branch = None
if upstream_branch:
try:
remote = GIT.Capture(
['config', 'rietveld.upstream-remote'], cwd=cwd).strip()
except gclient_utils.Error:
pass
else:
# Else, try to guess the origin remote.
remote_branches = GIT.Capture(['branch', '-r'], cwd=cwd).split()
if 'origin/master' in remote_branches:
# Fall back on origin/master if it exits.
remote = 'origin'
upstream_branch = 'refs/heads/master'
elif 'origin/trunk' in remote_branches:
# Fall back on origin/trunk if it exists. Generally a shared
# git-svn clone
remote = 'origin'
upstream_branch = 'refs/heads/trunk'
# Fall back on trying a git-svn upstream branch.
if GIT.IsGitSvn(cwd):
upstream_branch = GIT.GetSVNBranch(cwd)
else:
# Give up.
remote = None
upstream_branch = None
# Else, try to guess the origin remote.
remote_branches = GIT.Capture(['branch', '-r'], cwd=cwd).split()
if 'origin/master' in remote_branches:
# Fall back on origin/master if it exits.
remote = 'origin'
upstream_branch = 'refs/heads/master'
elif 'origin/trunk' in remote_branches:
# Fall back on origin/trunk if it exists. Generally a shared
# git-svn clone
remote = 'origin'
upstream_branch = 'refs/heads/trunk'
else:
# Give up.
remote = None
upstream_branch = None
return remote, upstream_branch
@staticmethod
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment