diff options
authorRichard Maw <>2014-08-30 22:22:48 +0100
committerRichard Maw <>2014-09-02 17:31:17 +0100
commit66ec3928392d09cba6037fc6c665cb1aa02e86e1 (patch)
parentf96452965e8065466bdd7188e66dded581bdc1a7 (diff)
Use git's remotes to determine unpushed branchesbaserock/richardmaw/less-ls-remote
Rather than using `git ls-remote` every time to see if there are changes at the remote end, use a local cache. Git already solves this problem with its refs/remotes/$foo branch namespace, so we can just use that instead. In addition, the detection of which upstream branch to use has been improved; it now uses git's notion of which the upstream branch of your current branch is, which saves effort in the implementation, and allows the name of the local branch to differ from that of the remote branch. This now won't notice if the branch you currently have checked out had commits pushed from another source, but for some use-cases this is preferable, as the result equivalent to if you had built before the other push. It may make sense to further extend this logic to check that the local branch is not ahead of the remote branch, instead of requiring them to be equal.
2 files changed, 23 insertions, 10 deletions
diff --git a/morphlib/ b/morphlib/
index 885f5cf8..638350e3 100644
--- a/morphlib/
+++ b/morphlib/
@@ -222,17 +222,14 @@ class BuildBranch(object):
for gd, (build_ref, index) in self._to_push.iteritems():
- remote = gd.get_remote('origin')
- head_ref = gd.disambiguate_ref(gd.HEAD)
+ head_ref = gd.HEAD
+ upstream_ref = gd.get_upstream_of_branch(head_ref)
+ if upstream_ref is None:
+ yield gd
+ continue
head_sha1 = gd.resolve_ref_to_commit(head_ref)
- pushed_refs = sorted(
- (remote_ref
- for remote_sha1, remote_ref in
- # substring match of refs, since ref may be a tag,
- # in which case it would end with ^{}
- if remote_sha1 == head_sha1 and head_ref in remote_ref),
- key=len)
- if not pushed_refs:
+ upstream_sha1 = gd.resolve_ref_to_commit(upstream_ref)
+ if head_sha1 != upstream_sha1:
yield gd
def push_build_branches(self, push_cb=lambda **kwargs: None):
diff --git a/morphlib/ b/morphlib/
index 40ac643f..9fef4f1e 100644
--- a/morphlib/
+++ b/morphlib/
@@ -515,6 +515,22 @@ class GitDirectory(object):
return 'refs/heads/' + ref
+ def get_upstream_of_branch(self, branch): # pragma: no cover
+ try:
+ out = morphlib.git.gitcmd(
+ self._runcmd, 'rev-parse', '--abbrev-ref',
+ '%s@{upstream}' % branch).strip()
+ return out
+ except cliapp.AppException as e:
+ emsg = str(e)
+ if 'does not point to a branch' in emsg:
+ # ref wasn't a branch, can't have upstream
+ # treat it the same as no upstream for convenience
+ return None
+ elif 'No upstream configured for branch' in emsg:
+ return None
+ raise
def resolve_ref_to_commit(self, ref):
return self._rev_parse('%s^{commit}' % ref)