A simple python script to mass pick open changes from gerrit in order based on dependencies.
This file contains 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
#!/bin/sh | |
""":" | |
exec python $0 ${1+"$@"} | |
""" | |
# Author: Clark Scheff | |
# | |
# Picks all open commits for a given project in the correct | |
# order based on their dependencies. There is plenty of | |
# room for improvments but this does work as intended. | |
# | |
# Note: make sure you are in the correct project directory before running this. | |
# | |
# An example of picking all open commits for android_frameworks_base | |
# mass_gerrit_pick.py -p ChameleonOS/android_frameworks_base -u d34d -b jellybean-mr2.1 -s review.chameleonos.org | |
import sys | |
import subprocess | |
import json | |
import getopt | |
# change these if you don't feel like supplying it at the command line | |
USERNAME = 'd34d' | |
BRANCH = 'kitkat' | |
SITE = 'review.chameleonos.org' | |
PROJECT = '' | |
LIMIT = 1000 | |
STATUS = 'open' | |
COMMITTER = None | |
def usage(): | |
print 'usage %s -p project [-b branch][-u username][-s site]' % sys.argv[0] | |
if len(sys.argv) < 2: | |
usage() | |
sys.exit(2) | |
try: | |
opts, args = getopt.getopt(sys.argv[1:], 'mp:b:u:s:l:c:', ['merged', 'project', 'branch', 'username', 'site', 'limit', 'committer']) | |
except getopt.GetoptError as err: | |
print str(err) | |
usage() | |
sys.exit(3) | |
has_project = False | |
for o, a in opts: | |
if o in ('-p', 'project'): | |
PROJECT = a | |
has_project = True | |
elif o in ('-b', 'branch'): | |
BRANCH = a | |
elif o in ('-u', 'username'): | |
USERNAME = a | |
elif o in ('-s', 'site'): | |
SITE = a | |
elif o in ('-l', 'limit'): | |
try: | |
LIMIT = int(a) | |
except: | |
pass | |
elif o in ('-m', 'merged'): | |
STATUS = 'merged' | |
elif o in ('-c', 'committer'): | |
COMMITTER = a | |
else: | |
assert False, 'unhandled option!' | |
if not has_project: | |
print 'Missing project' | |
usage() | |
sys.exit(4) | |
LOGIN = '%s@%s' % (USERNAME, SITE) | |
data = subprocess.check_output( | |
[ | |
'ssh', | |
'-p', | |
'29418', | |
LOGIN, | |
'gerrit', | |
'query', | |
'status:' + STATUS, 'project:' + PROJECT, | |
'limit:%d' % LIMIT, | |
'--dependencies', | |
'--current-patch-set', | |
'--format', 'JSON' | |
]) | |
# there is a \n at the very end so omit that from the list | |
listdata = data.split('\n')[:-1] | |
picks = [] | |
for i in range(len(listdata) - 1): | |
jsondata = json.loads(listdata[i]) | |
commitId = int(jsondata['number']) | |
try: | |
dependsOn = jsondata['dependsOn'][0] | |
dependencyId = int(dependsOn['number']) | |
except: | |
dependencyId = 0 | |
patchset = int(jsondata['currentPatchSet']['number']) | |
branch = jsondata['branch'] | |
if COMMITTER is None or COMMITTER == jsondata['owner']['username']: | |
if branch == BRANCH: | |
picks.append((commitId, dependencyId, patchset)) | |
# pre-sort the list based on dependency id | |
picks = sorted(picks, key=lambda x: x[1]) | |
# sort picks so dependencies come before the pick that depends on them | |
for i in range(len(picks)): | |
commitId, dependencyId, patchset = picks[i] | |
if dependencyId > 0: | |
for j in range(len(picks)): | |
if picks[j][0] == dependencyId: | |
tmp = picks[i] | |
del picks[i] | |
if i < j: | |
picks.insert(j, tmp) | |
else: | |
picks.insert(j+1, tmp) | |
break | |
# now go through and pick these bad boys | |
# template requires a tuple of (SITE, PROJECT, commitId % 100, commitId, patchset) | |
COMMAND_TEMPLATE='git fetch http://%s/%s refs/changes/%02d/%d/%d && git cherry-pick FETCH_HEAD' | |
for i in range(len(picks)): | |
commitId = picks[i][0] | |
change = commitId % 100 | |
command = COMMAND_TEMPLATE % (SITE, PROJECT, change, commitId, picks[i][2]) | |
subprocess.call(command, shell=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This doesn't order correctly.