]> git.wh0rd.org - home.git/commitdiff
git-rb-catchup: add option to automatically stop at last failing rebase
authorMike Frysinger <vapier@gentoo.org>
Sun, 21 Feb 2021 07:08:47 +0000 (02:08 -0500)
committerMike Frysinger <vapier@gentoo.org>
Sun, 21 Feb 2021 07:08:47 +0000 (02:08 -0500)
.bin/git-rb-catchup

index bb6b910ef7f84f24678b30903b9e3fd72399cd7a..3414c0200b86fdb8e963d19a0cd24212709df8fb 100755 (executable)
@@ -29,7 +29,7 @@ def rebase(target):
         return False
 
 
-def rebase_bisect(lbranch, rbranch, behind):
+def rebase_bisect(lbranch, rbranch, behind, leave_rebase=False):
     """Try to rebase branch as close to |rbranch| as possible."""
     def attempt(pos):
         target = f'{rbranch}~{pos}'
@@ -43,20 +43,32 @@ def rebase_bisect(lbranch, rbranch, behind):
         print('OK' if ret else 'failed')
         return ret
 
-    #"min" is the latest branch commit while "max" is where we're now.
-    min = 0
-    max = behind
+    # "pmin" is the latest branch position while "pmax" is where we're now.
+    pmin = 0
+    pmax = behind
     old_mid = None
+    first_fail = 0
     while True:
-        mid = min + (max - min) // 2
-        if mid == old_mid or mid < min or mid >= max:
+        mid = pmin + (pmax - pmin) // 2
+        if mid == old_mid or mid < pmin or mid >= pmax:
             break
         if attempt(mid):
-            max = mid
+            pmax = mid
         else:
-            min = mid
+            first_fail = max(first_fail, mid)
+            pmin = mid
         old_mid = mid
-    print('Done')
+
+    if pmin or pmax:
+        last_target = f'{rbranch}~{first_fail}'
+        if leave_rebase:
+            print('Restarting', last_target)
+            result = git(['rebase', last_target], check=False)
+            print(result.stdout.strip())
+        else:
+            print('Found first failure', last_target)
+    else:
+        print('All caught up!')
 
 
 def get_ahead_behind(lbranch, rbranch):
@@ -92,6 +104,10 @@ def get_parser():
         '--skip-initial-rebase-latest', dest='initial_rebase',
         action='store_false', default=True,
         help='skip initial rebase attempt onto the latest branch')
+    parser.add_argument(
+        '--leave-at-last-failed-rebase', dest='leave_rebase',
+        action='store_true', default=False,
+        help='leave tree state at last failing rebase')
     parser.add_argument(
         'branch', nargs='?',
         help='branch to rebase onto')
@@ -130,7 +146,7 @@ def main(argv):
                 print('OK!')
                 return 0
             print('failed; falling back to bisect')
-        rebase_bisect(lbranch, rbranch, behind)
+        rebase_bisect(lbranch, rbranch, behind, leave_rebase=opts.leave_rebase)
 
 
 if __name__ == '__main__':