buildman: Try to guess the upstream commit

Buildman normally obtains the upstream commit by asking git. Provided that
the branch was created with 'git checkout -b <branch> <some_upstream>' then
this normally works.

When there is no upstream, we can try to guess one, by looking up through
the commits until we find a branch. Add a function to try this and print
a warning if buildman ends up relying on it.

Also update the documentation to match.

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: Wolfgang Denk <wd@denx.de>
This commit is contained in:
Simon Glass 2014-12-01 17:33:54 -07:00
parent 1a91567510
commit 2a9e2c6a09
3 changed files with 67 additions and 16 deletions

View file

@ -310,8 +310,9 @@ branch with a valid upstream)
$ ./tools/buildman/buildman -b <branch> -n $ ./tools/buildman/buildman -b <branch> -n
If it can't detect the upstream branch, try checking out the branch, and If it can't detect the upstream branch, try checking out the branch, and
doing something like 'git branch --set-upstream <branch> upstream/master' doing something like 'git branch --set-upstream-to upstream/master'
or something similar. or something similar. Buildman will try to guess a suitable upstream branch
if it can't find one (you will see a message like" Guessing upstream as ...).
As an example: As an example:

View file

@ -127,12 +127,12 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
if not options.branch: if not options.branch:
count = 1 count = 1
else: else:
count = gitutil.CountCommitsInBranch(options.git_dir, count, msg = gitutil.CountCommitsInBranch(options.git_dir,
options.branch) options.branch)
if count is None: if count is None:
str = ("Branch '%s' not found or has no upstream" % sys.exit(col.Color(col.RED, msg))
options.branch) if msg:
sys.exit(col.Color(col.RED, str)) print col.Color(col.YELLOW, msg)
count += 1 # Build upstream commit also count += 1 # Build upstream commit also
if not count: if not count:

View file

@ -61,6 +61,52 @@ def CountCommitsToBranch():
patch_count = int(stdout) patch_count = int(stdout)
return patch_count return patch_count
def NameRevision(commit_hash):
"""Gets the revision name for a commit
Args:
commit_hash: Commit hash to look up
Return:
Name of revision, if any, else None
"""
pipe = ['git', 'name-rev', commit_hash]
stdout = command.RunPipe([pipe], capture=True, oneline=True).stdout
# We expect a commit, a space, then a revision name
name = stdout.split(' ')[1].strip()
return name
def GuessUpstream(git_dir, branch):
"""Tries to guess the upstream for a branch
This lists out top commits on a branch and tries to find a suitable
upstream. It does this by looking for the first commit where
'git name-rev' returns a plain branch name, with no ! or ^ modifiers.
Args:
git_dir: Git directory containing repo
branch: Name of branch
Returns:
Tuple:
Name of upstream branch (e.g. 'upstream/master') or None if none
Warning/error message, or None if none
"""
pipe = [LogCmd(branch, git_dir=git_dir, oneline=True, count=100)]
result = command.RunPipe(pipe, capture=True, capture_stderr=True,
raise_on_error=False)
if result.return_code:
return None, "Branch '%s' not found" % branch
for line in result.stdout.splitlines()[1:]:
commit_hash = line.split(' ')[0]
name = NameRevision(commit_hash)
if '~' not in name and '^' not in name:
if name.startswith('remotes/'):
name = name[8:]
return name, "Guessing upstream as '%s'" % name
return None, "Cannot find a suitable upstream for branch '%s'" % branch
def GetUpstream(git_dir, branch): def GetUpstream(git_dir, branch):
"""Returns the name of the upstream for a branch """Returns the name of the upstream for a branch
@ -69,7 +115,9 @@ def GetUpstream(git_dir, branch):
branch: Name of branch branch: Name of branch
Returns: Returns:
Name of upstream branch (e.g. 'upstream/master') or None if none Tuple:
Name of upstream branch (e.g. 'upstream/master') or None if none
Warning/error message, or None if none
""" """
try: try:
remote = command.OutputOneLine('git', '--git-dir', git_dir, 'config', remote = command.OutputOneLine('git', '--git-dir', git_dir, 'config',
@ -77,13 +125,14 @@ def GetUpstream(git_dir, branch):
merge = command.OutputOneLine('git', '--git-dir', git_dir, 'config', merge = command.OutputOneLine('git', '--git-dir', git_dir, 'config',
'branch.%s.merge' % branch) 'branch.%s.merge' % branch)
except: except:
return None upstream, msg = GuessUpstream(git_dir, branch)
return upstream, msg
if remote == '.': if remote == '.':
return merge return merge
elif remote and merge: elif remote and merge:
leaf = merge.split('/')[-1] leaf = merge.split('/')[-1]
return '%s/%s' % (remote, leaf) return '%s/%s' % (remote, leaf), None
else: else:
raise ValueError, ("Cannot determine upstream branch for branch " raise ValueError, ("Cannot determine upstream branch for branch "
"'%s' remote='%s', merge='%s'" % (branch, remote, merge)) "'%s' remote='%s', merge='%s'" % (branch, remote, merge))
@ -99,10 +148,11 @@ def GetRangeInBranch(git_dir, branch, include_upstream=False):
Expression in the form 'upstream..branch' which can be used to Expression in the form 'upstream..branch' which can be used to
access the commits. If the branch does not exist, returns None. access the commits. If the branch does not exist, returns None.
""" """
upstream = GetUpstream(git_dir, branch) upstream, msg = GetUpstream(git_dir, branch)
if not upstream: if not upstream:
return None return None, msg
return '%s%s..%s' % (upstream, '~' if include_upstream else '', branch) rstr = '%s%s..%s' % (upstream, '~' if include_upstream else '', branch)
return rstr, msg
def CountCommitsInBranch(git_dir, branch, include_upstream=False): def CountCommitsInBranch(git_dir, branch, include_upstream=False):
"""Returns the number of commits in the given branch. """Returns the number of commits in the given branch.
@ -114,14 +164,14 @@ def CountCommitsInBranch(git_dir, branch, include_upstream=False):
Number of patches that exist on top of the branch, or None if the Number of patches that exist on top of the branch, or None if the
branch does not exist. branch does not exist.
""" """
range_expr = GetRangeInBranch(git_dir, branch, include_upstream) range_expr, msg = GetRangeInBranch(git_dir, branch, include_upstream)
if not range_expr: if not range_expr:
return None return None, msg
pipe = [LogCmd(range_expr, git_dir=git_dir, oneline=True), pipe = [LogCmd(range_expr, git_dir=git_dir, oneline=True),
['wc', '-l']] ['wc', '-l']]
result = command.RunPipe(pipe, capture=True, oneline=True) result = command.RunPipe(pipe, capture=True, oneline=True)
patch_count = int(result.stdout) patch_count = int(result.stdout)
return patch_count return patch_count, msg
def CountCommits(commit_range): def CountCommits(commit_range):
"""Returns the number of commits in the given range. """Returns the number of commits in the given range.