mirror of https://gerrit.osmocom.org/osmo-dev
gits: use @{u} to get upstream branch, not origin/%s
git has an internal concept of a branch's upstream branch, and the remote need not be 'origin', and also, the upstream branch name may differ completely. So, use git's {u} keyword to obtain the upstream branch name. This removes all 'origin' strings from gits. Also, git_branch_exists() is no longer needed, drop it. Also remove a couple of default arguments which aren't ever used because we always pass arguments anyway. In the case of git_ahead_behind(), we would have use for a default branch_upstream=None to imply calling git_branch_upstream(), but then during rebase, if no upstream exists, we would invoke it twice to get None a second time. So just call the function explicitly. I thought about returning an empty string instead of None, but it's too convoluted. In git_output(), pipe STDERR to STDOUT, because every time we parse a remote ref (git ref-parse --abbrev-ref '%s{u}') and there is no remote branch, git prints 'Fatal: there is no remote bla bla' on stdout, and that error is expected / ok to happen, so it just clutters the 'gits' output. The easiest way to achieve silence then is to pipe to STDOUT, IIUC otherwise we'd have to use Popen() and communicate()... In the case of error, subprocess raises an exception and we see that an error happens. In the ref-parse case we can simply catch the exception and be quiet. Change-Id: Ife146903ae1323a4e568587ccfd4018725e9d719
This commit is contained in:
parent
d63a44c2ec
commit
68d8f34206
52
src/gits
52
src/gits
|
@ -58,7 +58,7 @@ def git(git_dir, *args, may_fail=False, section_marker=False, show_cmd=True):
|
|||
|
||||
|
||||
def git_output(git_dir, *args):
|
||||
return subprocess.check_output(['git', '-C', git_dir, ] + list(args)).decode('utf-8')
|
||||
return subprocess.check_output(['git', '-C', git_dir, ] + list(args), stderr=subprocess.STDOUT).decode('utf-8')
|
||||
|
||||
|
||||
def git_bool(git_dir, *args):
|
||||
|
@ -69,20 +69,16 @@ def git_bool(git_dir, *args):
|
|||
return False
|
||||
|
||||
|
||||
def git_branch_exists(git_dir, branch='origin/master'):
|
||||
return git_bool(git_dir, 'rev-parse', '--quiet', '--verify', branch)
|
||||
|
||||
|
||||
def git_ahead_behind(git_dir, branch='master', remote='origin'):
|
||||
def git_ahead_behind(git_dir, branch, branch_upstream):
|
||||
''' Count revisions ahead/behind of the remote branch.
|
||||
returns: (ahead, behind) (e.g. (0, 5)) '''
|
||||
|
||||
# Missing remote branch
|
||||
if not git_branch_exists(git_dir, remote + '/' + branch):
|
||||
if not branch_upstream:
|
||||
return (0, 0)
|
||||
|
||||
behind = git_output(git_dir, 'rev-list', '--count', '%s..%s/%s' % (branch, remote, branch))
|
||||
ahead = git_output(git_dir, 'rev-list', '--count', '%s/%s..%s' % (remote, branch, branch))
|
||||
behind = git_output(git_dir, 'rev-list', '--count', '%s..%s' % (branch, branch_upstream))
|
||||
ahead = git_output(git_dir, 'rev-list', '--count', '%s..%s' % (branch_upstream, branch))
|
||||
return (int(ahead.rstrip()), int(behind.rstrip()))
|
||||
|
||||
|
||||
|
@ -98,12 +94,20 @@ def git_branch_current(git_dir):
|
|||
return ret
|
||||
|
||||
|
||||
def git_branch_upstream(git_dir, branch_name='HEAD'):
|
||||
'''Return an upstream branch name, or an None if there is none.'''
|
||||
try:
|
||||
return git_output(git_dir, 'rev-parse', '--abbrev-ref', '%s@{u}' % branch_name).rstrip()
|
||||
except subprocess.CalledProcessError:
|
||||
return None
|
||||
|
||||
|
||||
def git_has_modifications(git_dir):
|
||||
return not git_bool(git_dir, 'diff', '--quiet', 'HEAD')
|
||||
|
||||
|
||||
def git_can_fast_forward(git_dir, branch='master', remote='origin'):
|
||||
return git_bool(git_dir, 'merge-base', '--is-ancestor', branch, remote + '/' + branch)
|
||||
def git_can_fast_forward(git_dir, branch, branch_upstream):
|
||||
return git_bool(git_dir, 'merge-base', '--is-ancestor', branch, branch_upstream)
|
||||
|
||||
|
||||
def format_branch_ahead_behind(branch, ahead, behind):
|
||||
|
@ -142,12 +146,14 @@ def git_branch_summary(git_dir):
|
|||
if not is_current and branch not in interesting_branch_names:
|
||||
continue
|
||||
|
||||
ahead, behind = git_ahead_behind(git_dir, branch)
|
||||
ahead, behind = git_ahead_behind(git_dir, branch,
|
||||
git_branch_upstream(git_dir, branch))
|
||||
|
||||
if not ahead and not behind and not is_current:
|
||||
# skip branches that are "not interesting"
|
||||
continue
|
||||
|
||||
# Branch with ahead/behind origin info ("master[+1|-5]")
|
||||
# Branch with ahead/behind upstream info ("master[+1|-5]")
|
||||
strs.append(format_branch_ahead_behind(branch, ahead, behind))
|
||||
return strs
|
||||
|
||||
|
@ -238,8 +244,10 @@ def rebase(git_dir):
|
|||
print('Not on a branch: %s' % git_dir)
|
||||
raise SkipThisRepo()
|
||||
|
||||
print('Rebasing branch: ' + orig_branch)
|
||||
ahead, behind = git_ahead_behind(git_dir, orig_branch)
|
||||
upstream_branch = git_branch_upstream(git_dir, orig_branch)
|
||||
|
||||
print('Rebasing %r onto %r' % (orig_branch, upstream_branch))
|
||||
ahead, behind = git_ahead_behind(git_dir, orig_branch, upstream_branch)
|
||||
|
||||
if git_has_modifications(git_dir):
|
||||
do_commit = ask(git_dir, 'Local mods.',
|
||||
|
@ -262,24 +270,24 @@ def rebase(git_dir):
|
|||
raise SkipThisRepo()
|
||||
|
||||
# Missing upstream branch
|
||||
if not git_branch_exists(git_dir, 'origin/' + orig_branch):
|
||||
if not upstream_branch:
|
||||
print('there is no upstream branch for %r' % orig_branch)
|
||||
|
||||
# Diverged
|
||||
elif ahead and behind:
|
||||
do_reset = ask(git_dir, 'Diverged.',
|
||||
'%s: git reset --hard origin/%s?' % (
|
||||
orig_branch, orig_branch),
|
||||
'%s: git reset --hard %s?' % (
|
||||
orig_branch, upstream_branch),
|
||||
'<empty> no',
|
||||
'OK yes (write OK in caps!)',
|
||||
valid_answers=('', 'OK'))
|
||||
|
||||
if do_reset == 'OK':
|
||||
git(git_dir, 'reset', '--hard', 'origin/%s' % orig_branch)
|
||||
git(git_dir, 'reset', '--hard', upstream_branch)
|
||||
|
||||
# Behind
|
||||
elif behind:
|
||||
if git_can_fast_forward(git_dir, orig_branch):
|
||||
if git_can_fast_forward(git_dir, orig_branch, upstream_branch):
|
||||
print('fast-forwarding...')
|
||||
git(git_dir, 'merge')
|
||||
else:
|
||||
|
@ -303,13 +311,13 @@ def rebase(git_dir):
|
|||
git(git_dir, 'commit', '-am', 'wip', may_fail=True)
|
||||
git(git_dir, 'checkout', orig_branch)
|
||||
|
||||
do_reset = ask(git_dir, '%s: git reset --hard origin/%s?' % (orig_branch, orig_branch),
|
||||
do_reset = ask(git_dir, '%s: git reset --hard %s?' % (orig_branch, upstream_branch),
|
||||
'<empty> no',
|
||||
'OK yes (write OK in caps!)',
|
||||
valid_answers=('', 'OK'))
|
||||
|
||||
if do_reset == 'OK':
|
||||
git(git_dir, 'reset', '--hard', 'origin/%s' % orig_branch)
|
||||
git(git_dir, 'reset', '--hard', upstream_branch)
|
||||
|
||||
return orig_branch
|
||||
|
||||
|
|
Loading…
Reference in New Issue