Add --partial_ok to compare_branches.py.

This change lets compare_branches.py succeed with a partial set of
cherry-picks. In our case, we sometimes get baacked up with several
commits needing to be cherry-picked. The first few cherry-pick fine, and
there's a problematic commit sometime down the line. By accepting the
first few that cherry-pick fine, someone resolving the conflict can
start at where that conflict begins, rather than having to wrangle more
commits unnecessarily.

I tested this with and without the flag, and confirmed that if the
first commit is problematic for cherry-picks, the command does
fail.

Change-Id: I2a8b34577f9cb74565adf90a2b7d5328bc555f85
Reviewed-on: http://gerrit.cloudera.org:8080/10025
Reviewed-by: Joe McDonnell <joemcdonn...@cloudera.com>
Tested-by: Philip Zeyliger <phi...@cloudera.com>


Project: http://git-wip-us.apache.org/repos/asf/impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/impala/commit/242e822a
Tree: http://git-wip-us.apache.org/repos/asf/impala/tree/242e822a
Diff: http://git-wip-us.apache.org/repos/asf/impala/diff/242e822a

Branch: refs/heads/master
Commit: 242e822ae6819c5029270f58f771ee61c52b676e
Parents: 257ae0e
Author: Philip Zeyliger <phi...@cloudera.com>
Authored: Wed Apr 11 15:36:14 2018 -0700
Committer: Philip Zeyliger <phi...@cloudera.com>
Committed: Wed Apr 11 22:54:51 2018 +0000

----------------------------------------------------------------------
 bin/compare_branches.py | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/impala/blob/242e822a/bin/compare_branches.py
----------------------------------------------------------------------
diff --git a/bin/compare_branches.py b/bin/compare_branches.py
index 0928751..8b54636 100755
--- a/bin/compare_branches.py
+++ b/bin/compare_branches.py
@@ -90,6 +90,8 @@ def create_parser():
   parser.add_argument('--cherry_pick', action='store_true', default=False,
       help='Cherry-pick mismatched commits to current branch. This ' +
         'must match (in the hash sense) the target branch.')
+  parser.add_argument('--partial_ok', action='store_true', default=False,
+      help='Exit with success if at least one cherrypick succeeded.')
   parser.add_argument('--source_branch', default='master')
   parser.add_argument('--target_branch', default='2.x')
   parser.add_argument('--source_remote_name', default='asf-gerrit',
@@ -159,7 +161,7 @@ def build_commit_map(branch, merge_base):
   logging.debug("Commit map for branch %s has size %d.", branch, len(result))
   return result
 
-def cherrypick(cherry_pick_hashes, full_target_branch_name):
+def cherrypick(cherry_pick_hashes, full_target_branch_name, partial_ok):
   """Cherrypicks the given commits.
 
   Also, asserts that full_target_branch_name matches the current HEAD.
@@ -167,6 +169,9 @@ def cherrypick(cherry_pick_hashes, full_target_branch_name):
   cherry_pick_hashes is a list of git hashes, in the order to
   be cherry-picked.
 
+  If partial_ok is true, return gracefully if at least one cherrypick
+  has succeeded.
+
   Note that this function does not push to the remote.
   """
   print "Cherrypicking %d changes." % (len(cherry_pick_hashes),)
@@ -184,10 +189,16 @@ def cherrypick(cherry_pick_hashes, 
full_target_branch_name):
     sys.exit(1)
 
   cherry_pick_hashes.reverse()
-  for cherry_pick_hash in cherry_pick_hashes:
-    subprocess.check_call(
+  for i, cherry_pick_hash in enumerate(cherry_pick_hashes):
+    ret = subprocess.call(
         ['git', 'cherry-pick', '--keep-redundant-commits', cherry_pick_hash])
-
+    if ret != 0:
+      if partial_ok and i > 0:
+        subprocess.check_call(['git', 'cherry-pick', '--abort'])
+        print "Failed to cherry-pick %s; stopping picks." % (cherry_pick_hash,)
+        return
+      else:
+        raise Exception("Failed to cherry-pick: %s" % (cherry_pick_hash,))
 
 def main():
   parser = create_parser()
@@ -270,7 +281,7 @@ def main():
                .format(pformat(commits_ignored)))
 
   if options.cherry_pick:
-    cherrypick(cherry_pick_hashes, full_target_branch_name)
+    cherrypick(cherry_pick_hashes, full_target_branch_name, options.partial_ok)
 
 if __name__ == '__main__':
   main()

Reply via email to