#!/usr/bin/python import os import sys import getopt import subprocess import urllib2 import json import re from xml.etree import ElementTree cfg = dict() cfg['draft'] = False cfg['nodo'] = False cfg['ssh'] = False cfg['remote'] = None cfg['verbose'] = 0 def verbose(s): if cfg['verbose'] > 0: sys.stderr.write(s) def get_topdir(): dir = os.getcwd() while not os.path.exists("%s/.repo" % (dir)): dir = os.path.realpath("%s/.." % (dir)) if dir == '/': raise OSError(2, 'No such file or directory', dir) return dir optargs, argv = getopt.getopt(sys.argv[1:], 'dnsv', ['draft', 'nodo', 'remote=', 'ssh', 'verbose']) for k, v in optargs: if k in ('-d', '--draft'): cfg['draft'] = True if k in ('-n', '--nodo'): cfg['nodo'] = True if k in ('--remote'): cfg['remote'] = v if k in ('-s', '--ssh'): cfg['ssh'] = True if k in ('-v', '--verbose'): cfg['verbose'] += 1 if len(argv) != 0: print "Usage: gerrit-push [args]" print " --draft Push as draft" print " --nodo Do not apply the change" print " --remote Use specified remote" print " --ssh Use ssh, do not attempt http" print " --verbose Increase verbose level" sys.exit(1) cur_dir = os.getcwd() verbose("cur_dir=%s" % (cur_dir)) prj_dir = None try: top_dir = get_topdir() except OSError: sys.stderr.write("Cannot find top of android tree\n") sys.exit(1) verbose("top_dir=%s" % (top_dir)) if len(top_dir) >= len(cur_dir): sys.stderr.write("Not in project directory\n") sys.exit(1) prj_dir = cur_dir[len(top_dir)+1:] verbose("prj_dir=%s" % (prj_dir)) # Read our manifest args = [] args.append('repo') args.append('manifest') child = subprocess.Popen(args, stdin=None, stdout=subprocess.PIPE, stderr=None) out, err = child.communicate() if child.returncode != 0: sys.stderr.write('Failed to read manifest\n') sys.exit(1) manifest = ElementTree.fromstring(out) # Figure out which remote to use remote_name = cfg['remote'] if remote_name is None: if not prj_dir is None: for elem in manifest.findall('project'): if elem.get('path') == prj_dir: remote_name = elem.get('remote') if remote_name is None: for elem in manifest.findall('default'): remote_name = elem.get('remote') if remote_name is None: sys.stderr.write("Cannot find appropriate remote entry in manifest\n"); sys.exit(1); verbose("remote_name=%s\n" % (remote_name)) review_url = None review_host = None for elem in manifest.findall('remote'): if elem.get('name') == remote_name: review_url = elem.get('review') if review_url.find(':') == -1: review_host = review_url review_url = "ssh://%s" % (review_url) else: review_host = review_url.strip_url_schema() if review_url is None or review_host is None: sys.stderr.write("Cannot find appropriate remote url in manifest\n"); sys.exit(1); verbose("review_url=%s, review_host=%s\n" % (review_url, review_host)) project = None for elem in manifest.findall('project'): if elem.get('path') == prj_dir: project = elem if project is None: sys.stderr.write('Error: project not found\n') sys.exit(1) project_path = project.get('path') project_name = project.get('name') # Figure out which branch to use project_branch = project.get('revision') if project_branch is None: for elem in manifest.findall('default'): project_branch = elem.get('revision') if project_branch is None: sys.stderr.write("Cannot find project branch in manifest\n"); sys.exit(1); if project_branch.startswith('refs/heads/'): project_branch = project_branch[11:] verbose("project_branch=%s\n" % (project_branch)) # Push the change args = [] args.append('git') args.append('push') args.append('%s/%s' % (review_url, project_name)) args.append('HEAD:refs/for/%s' % (project_branch)) if cfg['nodo']: print ' '.join(args) else: child = subprocess.Popen(args, stdin=None, stdout=None, stderr=None) out, err = child.communicate() if child.returncode != 0: sys.stderr.write('Failed to push change\n') sys.exit(1) verbose('Success\n') sys.exit(0)