Commit 2a9e2c6a authored by Simon Glass's avatar Simon Glass

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: default avatarSimon Glass <>
Suggested-by: default avatarWolfgang Denk <>
parent 1a915675
......@@ -310,8 +310,9 @@ branch with a valid upstream)
$ ./tools/buildman/buildman -b <branch> -n
If it can't detect the upstream branch, try checking out the branch, and
doing something like 'git branch --set-upstream <branch> upstream/master'
or something similar.
doing something like 'git branch --set-upstream-to upstream/master'
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:
......@@ -127,12 +127,12 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
if not options.branch:
count = 1
count = gitutil.CountCommitsInBranch(options.git_dir,
count, msg = gitutil.CountCommitsInBranch(options.git_dir,
if count is None:
str = ("Branch '%s' not found or has no upstream" %
sys.exit(col.Color(col.RED, str))
sys.exit(col.Color(col.RED, msg))
if msg:
print col.Color(col.YELLOW, msg)
count += 1 # Build upstream commit also
if not count:
......@@ -61,6 +61,52 @@ def CountCommitsToBranch():
patch_count = int(stdout)
return patch_count
def NameRevision(commit_hash):
"""Gets the revision name for a commit
commit_hash: Commit hash to look up
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.
git_dir: Git directory containing repo
branch: Name of branch
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,
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):
"""Returns the name of the upstream for a branch
......@@ -69,7 +115,9 @@ def GetUpstream(git_dir, branch):
branch: Name of branch
Name of upstream branch (e.g. 'upstream/master') or None if none
Name of upstream branch (e.g. 'upstream/master') or None if none
Warning/error message, or None if none
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',
'branch.%s.merge' % branch)
return None
upstream, msg = GuessUpstream(git_dir, branch)
return upstream, msg
if remote == '.':
return merge
elif remote and merge:
leaf = merge.split('/')[-1]
return '%s/%s' % (remote, leaf)
return '%s/%s' % (remote, leaf), None
raise ValueError, ("Cannot determine upstream branch for branch "
"'%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
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:
return None
return '%s%s..%s' % (upstream, '~' if include_upstream else '', branch)
return None, msg
rstr = '%s%s..%s' % (upstream, '~' if include_upstream else '', branch)
return rstr, msg
def CountCommitsInBranch(git_dir, branch, include_upstream=False):
"""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
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:
return None
return None, msg
pipe = [LogCmd(range_expr, git_dir=git_dir, oneline=True),
['wc', '-l']]
result = command.RunPipe(pipe, capture=True, oneline=True)
patch_count = int(result.stdout)
return patch_count
return patch_count, msg
def CountCommits(commit_range):
"""Returns the number of commits in the given range.
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