From 2a9e2c6a0962cb04a12d833cc5c1c0920fa3b4f5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 1 Dec 2014 17:33:54 -0700 Subject: 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 ' 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 Suggested-by: Wolfgang Denk --- tools/buildman/README | 5 ++-- tools/buildman/control.py | 10 +++---- tools/patman/gitutil.py | 68 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 67 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/buildman/README b/tools/buildman/README index 0f8ea200f5..8e7a68c34f 100644 --- a/tools/buildman/README +++ b/tools/buildman/README @@ -310,8 +310,9 @@ branch with a valid upstream) $ ./tools/buildman/buildman -b -n If it can't detect the upstream branch, try checking out the branch, and -doing something like 'git branch --set-upstream 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: diff --git a/tools/buildman/control.py b/tools/buildman/control.py index 48797e90a7..cec02c6d53 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -127,12 +127,12 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, if not options.branch: count = 1 else: - count = gitutil.CountCommitsInBranch(options.git_dir, - options.branch) + count, msg = gitutil.CountCommitsInBranch(options.git_dir, + options.branch) if count is None: - str = ("Branch '%s' not found or has no upstream" % - options.branch) - 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: diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py index b68df5d72e..34c6b04853 100644 --- a/tools/patman/gitutil.py +++ b/tools/patman/gitutil.py @@ -61,6 +61,52 @@ def CountCommitsToBranch(): patch_count = int(stdout) 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): """Returns the name of the upstream for a branch @@ -69,7 +115,9 @@ def GetUpstream(git_dir, branch): branch: Name of branch 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: 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) except: - 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 else: 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. -- cgit v1.2.1