From a19589abb493a764305f2030126df0de754a4113 Mon Sep 17 00:00:00 2001 From: Tom Marshall Date: Wed, 7 May 2014 13:11:15 -0500 Subject: [PATCH] Initial checkin --- android-build | 266 ++++++++++++++++++++++++++++++++++++++++++++++ android-changelog | 264 +++++++++++++++++++++++++++++++++++++++++++++ android-tag | 45 ++++++++ gerrit-fetch | 240 +++++++++++++++++++++++++++++++++++++++++ gerrit-pick | 3 + gerrit-pull | 3 + gerrit-push | 54 ++++++++++ 7 files changed, 875 insertions(+) create mode 100755 android-build create mode 100755 android-changelog create mode 100755 android-tag create mode 100755 gerrit-fetch create mode 100755 gerrit-pick create mode 100755 gerrit-pull create mode 100755 gerrit-push diff --git a/android-build b/android-build new file mode 100755 index 0000000..cd15151 --- /dev/null +++ b/android-build @@ -0,0 +1,266 @@ +#!/bin/bash -e + +# Acquire lock on source tree +parent=$(ps h -o comm $PPID) +if [ "$parent" != "flock" ]; then + exec flock ".lock" $0 "$@" +fi + +usage() +{ + prog=$(basename $0) + + echo "" + echo "Usage:" + echo " $prog [options] " + echo "" + echo " Options:" + echo " -a Automated build (check for clean working dir)" + echo " -c Clean output before build" + echo " Given once, clean device output (out/target/product)" + echo " Given twice, clean target output (out/target)" + echo " Given thrice, clean all output (out)" + echo " -C Clean output after successful build" + echo " Given once, clean device output (out/target/product)" + echo " Given twice, clean target output (out/target)" + echo " Given thrice, clean all output (out)" + echo " -j Specify -j value for make [CPUS]" + echo " -l Save build output to log file" + echo " -o Specify output directory" + echo " -O Specify Android out dir" + echo " -s Show commands" + echo " -t Specify make target [auto]" + echo " -v Specify version [none]" + echo "" + echo "Exit status: 0 on success, !0 on failure" + echo "" + echo "On success, output will be copied to \$TARGET_PRODUCT.zip." + echo "" + exit 1 +} + +# Tool locations +# XXX: not darwin compatible +CCACHE="prebuilts/misc/linux-x86/ccache/ccache" + +ccache_stats() +{ + # Calculate ccache stats + local ch=0 + local cm=0 + local ct=0 + local cpct="NA" + + OLDIFS="$IFS" + IFS=$'\n' + lines=($($CCACHE -s)) + IFS="$OLDIFS" + for (( n=0; $n < ${#lines[*]}; n=$(($n+1)) )); do + line=${lines[$n]} + if [ "${line:0:9}" = "cache hit" ]; then + ch=$(( ch + $(echo $line | sed 's/[^0-9]*//') )) + elif [ "${line:0:10}" = "cache miss" ]; then + read -a fields <<<$line + cm=$(( cm + $(echo $line | sed 's/[^0-9]*//') )) + fi + done + IFS="$OLDIFS" + if [ -n "$ch" -a -n "$cm" ]; then + ct=$(($ch+$cm)) + fi + if [ "$ct" -gt 0 ]; then + cpct=$((ch*100/ct)) + fi + + echo "ch=$ch" + echo "cm=$cm" + echo "ct=$ct" + echo "cpct=$cpct" +} + +# Set some useful vars +export USE_CCACHE=1 +export CPUS=$(grep "^processor" /proc/cpuinfo | wc -l) +export MEM=$(cat /proc/meminfo | grep "^MemTotal" | grep -o "[0-9]*") + +# Find actual value for jobs. +# - No more than 8 jobs +# - No more than one job per cpu +# - No more than one job per 1.5gb +max_jobs=8 +cpu_jobs="$CPUS" +if [ "$cpu_jobs" -lt "$max_jobs" ]; then + max_jobs="$cpu_jobs" +fi +mem_jobs=$(($MEM/1572864)) +if [ "$mem_jobs" -lt "$max_jobs" ]; then + max_jobs="$mem_jobs" +fi + +# Init options +opt_automated=0 +opt_clean=0 +opt_postclean=0 +opt_jobs="$max_jobs" +opt_log=0 +opt_outdir="." +opt_outandroid="" +opt_maketarget="auto" +opt_showcommands=0 +opt_version="" +while getopts "acCj:lo:O:st:v:" opt; do + case "$opt" in + a) opt_automated=1 ;; + c) opt_clean=$(($opt_clean+1)) ;; + C) opt_postclean=$(($opt_postclean+1)) ;; + j) opt_jobs="$OPTARG" ;; + l) opt_log=1 ;; + o) opt_outdir="$OPTARG" ;; + O) opt_outandroid="$OPTARG" ;; + s) opt_showcommands=1 ;; + t) opt_maketarget="$OPTARG" ;; + v) opt_version="$OPTARG" ;; + *) usage + esac +done +shift $(($OPTIND-1)) +if [ $# -ne 1 ]; then + usage +fi + +if [ -n "$opt_outandroid" ]; then + export OUT_DIR_COMMON_BASE="$opt_outandroid" +fi + +mkdir -p "$opt_outdir" + +# NB: "$combo" is used by build scripts +build_combo="$1" +project_device=$(echo $build_combo | cut -d'-' -f1) +project=$(echo $project_device | cut -d'_' -f1) +device=$(echo $project_device | cut -d'_' -f2) + +# Desired output files +if [ -n "$opt_version" ]; then + out_name="${opt_outdir}/${project_device}-${opt_version}" +else + out_name="${opt_outdir}/${project_device}" +fi + +if [ "$opt_log" -ne 0 ]; then + rm -f "${out_name}.log" + exec >> "${out_name}.log" 2>&1 +fi + +if [ ! -d ".repo" ]; then + echo "Invalid build tree" + exit 1 +fi + +case "$opt_clean" in +0) # Do nothing + ;; +1) # Clean device output + rm -rf "$OUT_DIR_COMMON_BASE/target/product" + ;; +2) # Clean target output + rm -rf "$OUT_DIR_COMMON_BASE/target" + ;; +*) # Clean all output + rm -rf "$OUT_DIR_COMMON_BASE" + ;; +esac + +# Detect make target +if [ -z "$opt_maketarget" -o "$opt_maketarget" = "auto" ]; then + opt_maketarget="otapackage" + if [ -f "build/core/Makefile" ]; then + if grep -q "^bacon:" "build/core/Makefile"; then + opt_maketarget="bacon" + fi + fi +fi + +if [ "$opt_showcommands" -ne 0 ]; then + opt_maketarget="showcommands $opt_maketarget" +fi + +# Ensure working directory is clean +if [ "$opt_automated" -ne 0 ]; then + android-repo status | grep -q "working directory clean" +fi + +. build/envsetup.sh +lunch "$build_combo" + +# Setup ccache +if [ -z "$CCACHE_ROOT" ]; then + CCACHE_ROOT="$HOME" +fi + +export CCACHE_DIR="$CCACHE_ROOT/.ccache-$project_device" +if [ ! -d "$CCACHE_DIR" ]; then + mkdir -p "$CCACHE_DIR" + $CCACHE -M 8G +fi + +# Clean some things +rm -f $OUT/system/build.prop + +eval $(ccache_stats) +sch=$ch +scm=$cm +sct=$ct +scpct=$cpct + +# Do the build +stime=$(date +%s) +make -j${opt_jobs} ${opt_maketarget} +etime=$(date +%s) + +# Find output zip +built_zip=$(ls -t $OUT/*.zip | head -1) +if [ ! -f "$built_zip" ]; then + echo "Error: cannot find built zip in $OUT" + exit 1 +fi + +# Copy output zip to well known place +cp "$built_zip" "${out_name}.zip" + +# Calculate elapsed time +elapsedsec=$((etime - stime)) +elapsed=$(printf "%02d:%02d" $((elapsedsec/60)) $((elapsedsec%60))) + +eval $(ccache_stats) +ech=$ch +ecm=$cm +ect=$ct +ecpct=$cpct + +dch=$((ech - sch)) +dcm=$((ecm - scm)) +dct=$((ect - sct)) +dcpct="NA" +if [ "$dct" -gt 0 ]; then + dcpct=$((dch*100/dct)) +fi + +echo "Build complete." +echo "elapsed time : $elapsed" +echo "ccache totals: $ech/$ect ($ecpct%)" +echo "ccache deltas: $dch/$dct ($dcpct%)" + +case "$opt_postclean" in +0) # Do nothing + ;; +1) # Clean device output + rm -rf "$OUT_DIR_COMMON_BASE/target/product" + ;; +2) # Clean target output + rm -rf "$OUT_DIR_COMMON_BASE/target" + ;; +*) # Clean all output + rm -rf "$OUT_DIR_COMMON_BASE" + ;; +esac diff --git a/android-changelog b/android-changelog new file mode 100755 index 0000000..b32c5a0 --- /dev/null +++ b/android-changelog @@ -0,0 +1,264 @@ +#!/usr/bin/python + +import os +import sys +import getopt +import subprocess +from xml.etree import ElementTree + +def read_manifest(file): + manifest = ElementTree.parse(file) + defaults = manifest.findall('default')[0] + for project in manifest.findall('project'): + if not 'remote' in project.attrib: + project.attrib['remote'] = defaults.attrib['remote'] + if not 'revision' in project.attrib: + project.attrib['revision'] = defaults.attrib['revision'] + return manifest + +def manifest_defaults(manifest): + defaults = dict() + + defaults['remote'] = '' + defaults['revision'] = '' + for e in manifest.findall('default'): + if 'remote' in e: + defaults['remote'] = e.attrib['remote'] + if 'revision' in e: + defaults['revision'] = e.attrib['revision'] + + oldpwd = os.getcwd() + os.chdir('.repo/manifests') + pipe = subprocess.Popen(['git', 'remote', '-v'], stdout=subprocess.PIPE) + line = pipe.stdout.readline() + fields = line.split() + defaults['fetch'] = os.path.dirname(fields[1]) + os.chdir(oldpwd) + + return defaults + +def manifest_remotes(manifest, defaults): + remotes = dict() + for e in manifest.findall('remote'): + if not 'name' in e.attrib: + print "ERROR: remote with no name attrib" + continue + name = e.attrib['name'] + if not 'fetch' in e.attrib: + print "ERROR: remote with no fetch attrib" + continue + e.attrib['fetch'] = e.attrib['fetch'].rstrip('/') + if e.attrib['fetch'] == '.': + e.attrib['fetch'] = defaults['fetch'] + if e.attrib['fetch'] == '..': + e.attrib['fetch'] = os.path.dirname(defaults['fetch']) + remotes[name] = e + return remotes + +def manifest_projects(manifest, remotes, defaults): + projects = dict() + for e in manifest.findall('project'): + if not 'name' in e.attrib: + print "ERROR: project with no name attrib" + continue + if not 'path' in e.attrib: + e.attrib['path'] = e.attrib['name'] + path = e.attrib['path'] + if path in projects: + print "ERROR: duplicate project path %s" % path + continue + if not 'remote' in e.attrib: + e.attrib['remote'] = defaults['remote'] + remote_name = e.attrib['remote'] + r = remotes[remote_name] + e.attrib['remote_url'] = r.attrib['fetch'] + '/' + e.attrib['name'] + projects[path] = e + return projects + +def is_same_project(p1, p2): + if p1.attrib['path'] != p2.attrib['path']: + return False + if p1.attrib['remote_url'] != p2.attrib['remote_url']: + return False + return True + +def run_git_in_dir(path, args): + pipe = os.popen("chdir %s && git %s" % (path, args)) + lines = pipe.readlines() + pipe.close() + return lines + +class TextEmitter: + def emit_header(self, f1, f2): + print "# Changelog" + print "# Created ..." + print "# %s vs %s" % (f1, f2) + + def emit_footer(self): + # empty + pass + + def emit_project_change_header(self): + print "=" * 72 + print "Project changes ..." + + def emit_project_change_text(self, text): + print "%s" % text + + def emit_project_change_footer(self): + print "" + + def emit_dir_changes_header(self, name, r1, r2): + print "=" * 72 + print "Changes in %s [%s .. %s]" % (name, r1, r2) + print "=" * 72 + print "" + + def emit_dir_changes_text(self, remote_url, text): + for line in text: + print line.rstrip() + + def emit_dir_changes_footer(self): + print "" + +class HtmlEmitter: + def emit_header(self, f1, f2): + print "" + print " " + print " Changelog" + print " " + print " " + + def emit_footer(self): + print " " + print "" + + def emit_project_change_header(self): + print "

Project changes

" + print "
" + + def emit_project_change_text(self, text): + print " %s
" % text + + def emit_project_change_footer(self): + # empty + pass + + def emit_dir_changes_header(self, name, r1, r2): + print "

Changes in %s [%s .. %s]

" % (name, r1, r2) + print "
" + + def emit_dir_changes_text(self, remote_url, text): + print "
"
+        for line in text:
+            txt = line.rstrip()
+            if line[0:7] == 'commit ' and remote_url.find('github.com') != -1:
+                id = line[7:]
+                lnk = '%s/commit/%s' % (remote_url, id)
+                txt = '%s' % (lnk, id)
+            print "  %s" % txt
+        print "  
" + + def emit_dir_changes_footer(self): + # empty + pass + +fmt = 'text' +showmerges = False +short = False + +opts, args = getopt.getopt(sys.argv[1:], 'f:ms', ['format=', 'show-merges', 'short']) +for k, v in opts: + if k in ('-f', '--format'): + fmt = v + if k in ('-m', '--show-merges'): + showmerges = True + if k in ('-s', '--short'): + short = True + +if len(args) != 2: + print "Usage: %s [-f text|html] [-m] manifest1 manifest2" + sys.exit(1) + +f1 = args[0] +f2 = args[1] +manifest1 = read_manifest(f1) +manifest2 = read_manifest(f2) +defaults1 = manifest_defaults(manifest1) +defaults2 = manifest_defaults(manifest2) +remotes1 = manifest_remotes(manifest1, defaults1) +remotes2 = manifest_remotes(manifest2, defaults2) +projects1 = manifest_projects(manifest1, remotes1, defaults1) +projects2 = manifest_projects(manifest2, remotes2, defaults2) + +diffable_projects = [] +changed_projects = [] +new_projects = [] +del_projects = [] + +for path in projects1.iterkeys(): + if path in projects2: + p1 = projects1[path] + p2 = projects2[path] + if is_same_project(p1, p2): + diffable_projects.append(path) + else: + changed_projects.append(path) + else: + del_projects.append(path) + +for path in projects2.iterkeys(): + if not path in projects1: + new_projects.append(path) + +if fmt == 'text': + emitter = TextEmitter() +else: + emitter = HtmlEmitter() + +emitter.emit_header(f1, f2) + +if len(new_projects) > 0 or len(del_projects) > 0 or len(changed_projects) > 0: + emitter.emit_project_change_header() + + for path in new_projects: + remote_url = projects2[path].attrib['remote_url'] + emitter.emit_project_change_text("new project %s: %s" % (path, remote_url)) + + for path in del_projects: + remote_url = projects1[path].attrib['remote_url'] + emitter.emit_project_change_text("deleted project %s: %s" % (path, remote_url)) + + for path in changed_projects: + old_remote_url = projects1[path].attrib['remote_url'] + new_remote_url = projects2[path].attrib['remote_url'] + emitter.emit_project_change_text("changed project %s: %s => %s" % (path, old_remote_url, new_remote_url)) + + emitter.emit_project_change_footer() + +for path in sorted(diffable_projects): + p1 = projects1[path] + r1 = p1.attrib['revision'] + p2 = projects2[path] + r2 = p2.attrib['revision'] + if r1 != r2: + lines = run_git_in_dir(path, "show --pretty=format:%%h %s" % (r1)) + r1a = lines[0].rstrip('\n') + lines = run_git_in_dir(path, "show --pretty=format:%%h %s" % (r2)) + r2a = lines[0].rstrip('\n') + gitargs = "log " + if not showmerges: + gitargs += "--no-merges " + if short: + gitargs += "--pretty=oneline " + else: + gitargs += "--pretty=short " + gitargs += "--abbrev-commit " + gitargs += "%s..%s" % (p1.attrib['revision'], p2.attrib['revision']) + lines = run_git_in_dir(path, gitargs) + if len(lines) > 0: + emitter.emit_dir_changes_header(path, r1a, r2a) + emitter.emit_dir_changes_text(p1.attrib['remote_url'], lines) + emitter.emit_dir_changes_footer() + +emitter.emit_footer() diff --git a/android-tag b/android-tag new file mode 100755 index 0000000..7627976 --- /dev/null +++ b/android-tag @@ -0,0 +1,45 @@ +#!/bin/sh + +topdir=$(pwd) + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +action="$1" + +create_tag() +{ + # XXX: should verify "git status" to ensure to uncommitted diffs + repo manifest -r | cat +} + +restore_tag() +{ + while read line; do + prj_entry=$(echo $line | grep " $tag" + cd "$topdir/$dir" + git checkout "$tag" + done +} + +case "$action" in + create) create_tag ;; + restore) restore_tag ;; + *) usage ;; +esac diff --git a/gerrit-fetch b/gerrit-fetch new file mode 100755 index 0000000..1c6e48c --- /dev/null +++ b/gerrit-fetch @@ -0,0 +1,240 @@ +#!/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['nodo'] = False +cfg['post'] = None +cfg['remote'] = None +cfg['revision'] = None +cfg['ssh'] = False +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 + +def usage(): + print "Usage: gerrit-fetch [args] " + print " --nodo Do not apply the change" + print " --post Apply change after fetching (cherry-pick|merge)" + print " --remote Use specified remote" + print " --revision Use specified change revision" + print " --ssh Use ssh, do not attempt http" + print " --verbose Increase verbose level" + sys.exit(1) + +optargs, argv = getopt.getopt(sys.argv[1:], 'np:sv', + ['nodo', 'post=', 'remote=', 'revision=', 'ssh', 'verbose']) +for k, v in optargs: + if k in ('-n', '--nodo'): + cfg['nodo'] = True + if k in ('-p', '--post'): + cfg['post'] = v + if k in ('--remote'): + cfg['remote'] = v + if k in ('--revision'): + cfg['revision'] = v + if k in ('-s', '--ssh'): + cfg['ssh'] = True + if k in ('-v', '--verbose'): + cfg['verbose'] += 1 + +if not cfg['post'] is None: + if cfg['post'] != 'cherry-pick' and cfg['post'] != 'merge': + usage() + +if len(argv) != 1: + usage() + +change_number = int(argv[0]) + +cur_dir = os.getcwd() +print "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) +print "top_dir=%s" % (top_dir) +if len(top_dir) < len(cur_dir): + prj_dir = cur_dir[len(top_dir)+1:] + print "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 prj_dir is None: + for elem in manifest.findall('default'): + cfg['remote'] = elem.get('name') + else: + for elem in manifest.findall('project'): + if elem.get('path') == prj_dir: + 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 = "http://%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)) + +# Fetch the change props +props = None +project_name = None +change_revision = cfg['revision'] +if not cfg['ssh']: + try: + # NB: o=DOWNLOAD_COMMANDS is not reliable so don't use it + url = '%s/changes/?q=%d&o=CURRENT_REVISION' % (review_url, change_number) + verbose("Attempting to fetch change from url=%s\n" % (url)) + response = urllib2.urlopen(url) + doc = response.read() + if not doc.startswith(")]}'\n"): + sys.stderr.write('Error: malformed change props (url=%s)\n' % (url)) + raise Exception('Malformed change props') + proplist = json.loads(doc[5:]) + if len(proplist) == 1: + verbose("proplist loads and has one element\n"); + props = proplist[0] + project_name = props['project'] + if change_revision is None: + change_rev_id = props['current_revision'] + change_rev = None + for rev in props['revisions']: + if rev == change_rev_id: + change_revision = props['revisions'][rev]['_number'] + except: + sys.stderr.write('Failed to fetch change props\n') + +if project_name is None: + args = [] + args.append('ssh') + args.append(review_host) + args.append('gerrit') + args.append('query') + args.append('--format=JSON') + args.append('--current-patch-set') + args.append("%d" %(change_number)) + verbose("Attempting to fetch change from cmd=\"%s\"\n" % (" ".join(args))) + 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) + lines = out.split('\n') + props = json.loads(lines[0]) + project_name = props['project'] + if change_revision is None: + change_revision = props['currentPatchSet']['number'] + + # If we used ssh to access the change, also use ssh to fetch it + review_url = "ssh://%s" % (review_host) + +if project_name is None: + sys.stderr.write('Error: cannot fetch change properties\n') + sys.exit(1) +verbose("project=%s\n" % (project_name)) + +if change_revision is None: + sys.stderr.write('Error: cannot fetch change revision\n') + sys.exit(1) +verbose("change_revision=%s\n" % (change_revision)) + +project = None +for elem in manifest.findall('project'): + if elem.get('name') == project_name: + project = elem +if project is None: + sys.stderr.write('Error: project not found\n') + sys.exit(1) +project_path = project.get('path') + +if prj_dir is None: + # Switch to the project directory + verbose("Switching to project directory %s\n" % (project_path)) + try: + os.chdir(project_path) + except: + sys.stderr.write('Error: path not found\n') + sys.exit(1) +else: + # Verify correct directory + verbose("Verifying project directory %s vs %s\n" % (project_path, prj_dir)) + if prj_dir != project_path: + sys.stderr.write("Error: change applies to %s, we are in %s\n" % (project_path, prj_dir)) + sys.exit(1) + +change_hash = "%02d" % (change_number % 100) + +# Fetch the change +args = [] +args.append('git') +args.append('fetch') +args.append('%s/%s' % (review_url, project_name)) +args.append('refs/changes/%s/%s/%s' % (change_hash, change_number, change_revision)) +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 fetch change\n') + sys.exit(1) + +if not cfg['post'] is None: + # Pick the change + args = [] + args.append('git') + args.append(cfg['post']) + args.append('FETCH_HEAD') + 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 %s change\n" % (cfg['post'])) + sys.exit(1) + +verbose('Success\n') +sys.exit(0) diff --git a/gerrit-pick b/gerrit-pick new file mode 100755 index 0000000..1c8fa85 --- /dev/null +++ b/gerrit-pick @@ -0,0 +1,3 @@ +#!/bin/bash + +exec gerrit-fetch --post=cherry-pick "$@" diff --git a/gerrit-pull b/gerrit-pull new file mode 100755 index 0000000..a36311e --- /dev/null +++ b/gerrit-pull @@ -0,0 +1,3 @@ +#!/bin/bash + +exec gerrit-fetch --post=pull "$@" diff --git a/gerrit-push b/gerrit-push new file mode 100755 index 0000000..3309950 --- /dev/null +++ b/gerrit-push @@ -0,0 +1,54 @@ +#!/bin/bash + +find_topdir() +{ + while [ ! -d ".repo" ]; do + cd ".." + if [ $PWD = "/" ]; then + echo "Cannot find topdir" + exit 1 + fi + done + pwd +} + +SCHEME="ssh" +GIT="git" +if [ "$1" = "-t" ]; then + GIT="echo git" + shift +fi +if [ "$1" = "-h" ]; then + SCHEME="https" +fi + +topdir=$(find_topdir) +len=$(( ${#topdir} + 1 )) +prj_path=${PWD:$len} + +prj_entry=$(repo manifest | grep "project .*path=\"$prj_path\"") +if [ -z "$prj_entry" ]; then + echo "Cannot find project entry for $prj_path" + exit 1 +fi + +def_entry=$(repo manifest | grep "default ") +def_remote_name=$(echo $def_entry | egrep -o "remote=([^ ]*)" | cut -d'"' -f2) +def_remote_entry=$(repo manifest | grep "remote .*name=\"$def_remote_name\"") + +prj_name=$(echo $prj_entry | egrep -o "name=([^ ]*)" | cut -d'"' -f2) +prj_remote_name=$(echo $prj_entry | egrep -o "remote=([^ ]*)" | cut -d'"' -f2) +prj_revision=$(echo $prj_entry | egrep -o "revision=([^ ]*)" | cut -d'"' -f2) +if [ -z "$prj_revision" ]; then + prj_revision=$(echo $def_entry | egrep -o "revision=([^ ]*)" | cut -d'"' -f2) +fi +prj_revision="${prj_revision##refs/heads/}" + +if [ -n "$prj_remote_name" ]; then + remote_entry=$(repo manifest | grep "remote .*name=\"$prj_remote_name\"") +else + remote_entry=$(repo manifest | grep "remote .*name=\"$def_remote_name\"") +fi +remote_review=$(echo $remote_entry | egrep -o "review=([^ ]*)" | cut -d'"' -f2) + +$GIT push "$SCHEME://$remote_review:29418/$prj_name" "HEAD:refs/for/$prj_revision"