Last active
December 13, 2022 13:05
-
-
Save netfeed/16bbf23c908226008313c2161a2362df to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| import argparse | |
| import sys | |
| import shlex | |
| import subprocess | |
| import os | |
| import os.path | |
| def get_command(branch=None, grep=None): | |
| b = '' | |
| g = '' | |
| if grep: | |
| g = "--grep '%s'" %(grep) if grep else '' | |
| b = branch if branch else '' | |
| else: | |
| b = '--no-merges %s ^develop' %(branch) | |
| s = "git log %s --pretty='format:%%h' --reverse --no-merges %s" %(g, b) | |
| return shlex.split(s) | |
| def get_hashes(branch=None, grep=None): | |
| command = get_command(branch, grep) | |
| process = subprocess.Popen( | |
| command, | |
| universal_newlines=True, | |
| stdout=subprocess.PIPE, | |
| stdin=subprocess.PIPE) | |
| stdout, stderr = process.communicate() | |
| if stderr: | |
| raise OSError(stderr) | |
| return stdout.splitlines() | |
| def get_options(): | |
| parser = argparse.ArgumentParser( | |
| prog='Recursive Cherry Pick') | |
| parser.add_argument('--grep') | |
| parser.add_argument('--continue', action='store_true', dest='cont') | |
| parser.add_argument('--abort', action='store_true') | |
| parser.add_argument('--dry-run', action='store_true') | |
| parser.add_argument('branch', nargs='?') | |
| args = parser.parse_args() | |
| if args.cont or args.abort: | |
| return (None, None, args.dry_run, args.cont, args.abort) | |
| if args.grep is None and args.branch is None: | |
| raise OSError("at least one of branch and grep is needed") | |
| return (args.branch, args.grep, args.dry_run, False, False) | |
| def write_hashes(filename, hashes): | |
| with open(filename, 'w') as f: | |
| f.writelines(l + '\n' for l in hashes) | |
| def read_hashes(filename): | |
| with open(filename, 'r') as f: | |
| lines = f.readlines() | |
| return [l.strip() for l in lines] | |
| def start(branch, grep, filename): | |
| if branch is None and grep is None: | |
| raise OSError("at least one of branch and grep is needed") | |
| hashes = get_hashes(branch, grep) | |
| write_hashes(filename, hashes) | |
| def abort_prog(filename): | |
| os.remove(filename) | |
| def continue_cherry_pick(): | |
| process = subprocess.Popen(['git', 'status'], stdout=subprocess.PIPE, stdin=subprocess.PIPE) | |
| stdout, stderr = process.communicate() | |
| if 'You are currently cherry-picking' not in str(stdout): | |
| return | |
| cont = subprocess.Popen(['git', 'cherry-pick', '--continue'], stdout=subprocess.PIPE, stdin=subprocess.PIPE) | |
| stdout, stderr = cont.communicate() | |
| if cont.returncode != 0: | |
| raise OSError(str(stdout)) | |
| def cherry_pick(filename, dry_run): | |
| hashes = read_hashes(filename) | |
| if not hashes: | |
| abort_prog(filename) | |
| return | |
| current = hashes.pop(0) | |
| dr = '-n' if dry_run else '' | |
| s = 'git cherry-pick %s %s' %(dr, current) | |
| write_hashes(filename, hashes) | |
| command = shlex.split(s) | |
| process = subprocess.Popen( | |
| command, | |
| stdout=subprocess.PIPE, | |
| stdin=subprocess.PIPE) | |
| stdout, stderr = process.communicate() | |
| if stdout: | |
| print(stdout) | |
| cherry_pick(filename, dry_run) | |
| else: | |
| print(stderr) | |
| sys.exit(1) | |
| filename = '/tmp/rec-cherry-pick' | |
| branch, grep, dry_run, cont, abort = get_options() | |
| if not os.path.isfile(filename): | |
| start(branch, grep, filename) | |
| cont = True | |
| elif not cont and not abort: | |
| raise OSError("--continue or --abort needed as there's an ongoing process") | |
| if abort: | |
| abort_prog(filename) | |
| elif cont: | |
| continue_cherry_pick() | |
| cherry_pick(filename, dry_run) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment