]> git.wh0rd.org - home.git/commitdiff
git-rb-all: handle more edge cases
authorMike Frysinger <vapier@gentoo.org>
Sat, 20 Feb 2021 16:34:56 +0000 (11:34 -0500)
committerMike Frysinger <vapier@gentoo.org>
Sat, 20 Feb 2021 16:34:56 +0000 (11:34 -0500)
.bin/git-rb-all

index 92834ac6aef213abf1af4cb6e2c3a821536c89cb..a2f7922a9c84358ed6edca4bcb612b3fcfd0a547 100755 (executable)
@@ -49,10 +49,18 @@ class Color:
     HILITE = _combine(Terminal.BOLD, Terminal.FG_CYAN)
     BRACKET = _combine(Terminal.BOLD, Terminal.FG_BLUE)
 
+    @classmethod
+    def good(cls, msg):
+        return cls.GOOD + msg + cls.NORMAL
+
+    @classmethod
+    def bad(cls, msg):
+        return cls.BAD + msg + cls.NORMAL
+
 
 def fatal(msg):
     """Show an error |msg| then exit."""
-    print(f'{Color.BAD}{PROG}: error: {msg}{Color.NORMAL}', file=sys.stderr)
+    print(Color.bad(f'{PROG}: error: {msg}'), file=sys.stderr)
     sys.exit(1)
 
 
@@ -87,6 +95,13 @@ def rebase_inprogress():
     return False
 
 
+@functools.lru_cache(maxsize=None)
+def cherry_pick_inprogress():
+    """Determine whether a cherry-pick is in progress."""
+    output = git(['rev-parse', '--git-path', 'CHERRY_PICK_HEAD']).stdout.strip()
+    return Path(output).exists()
+
+
 class AppendOption(argparse.Action):
     """Append the command line option (with no arguments) to dest.
 
@@ -123,10 +138,6 @@ def main(argv):
     parser = get_parser()
     opts = parser.parse_args(argv)
 
-    # Skip if rebase is in progress.
-    if rebase_inprogress():
-        fatal('skipping due to active rebase')
-
     # Switch to the top dir in case the working dir doesn't exist in every branch.
     topdir = git(['rev-parse', '--show-toplevel']).stdout.strip()
     os.chdir(topdir)
@@ -138,7 +149,7 @@ def main(argv):
     #  ||s-stash||
     state = git(
         ['for-each-ref', '--format=%(HEAD)|%(worktreepath)|%(refname:short)|%(upstream)|%(upstream:track,nobracket)',
-         'refs/heads/*']).stdout.splitlines()
+         'HEAD', 'refs/heads/*']).stdout.splitlines()
 
     curr_state = None
     branch_width = 0
@@ -154,7 +165,10 @@ def main(argv):
     if not local_count:
         return 0
     if not curr_state:
-        fatal('unable to resolve current branch')
+        # Are we in a detached head state?
+        if not git(['symbolic-ref', '-q', 'HEAD'], check=False).returncode:
+            fatal('unable to resolve current branch')
+        curr_state = git(['rev-parse', 'HEAD']).stdout.strip()
 
     switched_head = False
     branches = {}
@@ -176,7 +190,7 @@ def main(argv):
         m = re.search(r'behind ([0-9]+)', ahead_behind)
         behind = int(m.group(1)) if m else 0
         if not behind:
-            print('Up-to-date!')
+            print(Color.good('up-to-date'))
             continue
         elif not ahead:
             # If we haven't switched the checkout, update-ref on current HEAD
@@ -187,17 +201,27 @@ def main(argv):
             else:
                 result = git(['merge', '-q', '--ff-only'], check=False)
                 if result.returncode:
-                    print(f'{Color.BAD}unable to merge{Color.NORMAL}\n' + result.stdout.strip())
+                    print(Color.bad('unable to merge') + '\n' + result.stdout.strip())
                 else:
                     print('fast forwarded [merged]')
             continue
 
+        # Skip this ref if tree is in a bad state.
+        if rebase_inprogress():
+            print(Color.bad('skipping due to active rebase'))
+            continue
+        if cherry_pick_inprogress():
+            print(Color.bad('skipping due to active cherry-pick'))
+            continue
         if checkout_is_dirty():
-            print(f'{Color.BAD}unable to rebase: tree is dirty{Color.NORMAL}')
+            print(Color.bad('unable to rebase: tree is dirty'))
             continue
 
         print(f'rebasing [{ahead_behind}] ', end='', flush=True)
-        git(['checkout', '-q', branch])
+        result = git(['checkout', '-q', branch], check=False)
+        if result.returncode:
+            print(Color.bad('unable to checkout') + '\n' + result.stdout.strip())
+            continue
         switched_head = True
         if opts.catchup:
             print()
@@ -206,9 +230,9 @@ def main(argv):
             result = git(['rebase'] + opts.git_options, check=False)
             if result.returncode:
                 git(['rebase', '--abort'])
-                print(f'{Color.BAD}failed{Color.NORMAL}\n' + result.stdout.strip())
+                print(Color.bad('failed') + '\n' + result.stdout.strip())
             else:
-                print('OK!')
+                print(Color.good('OK'))
 
     if switched_head:
         git(['checkout', '-q', curr_state])