Initial checkin
This commit is contained in:
parent
bd02b76e5d
commit
a19589abb4
|
@ -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] <build_combo>"
|
||||
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
|
|
@ -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 "<html>"
|
||||
print " <head>"
|
||||
print " <title>Changelog</title>"
|
||||
print " </head>"
|
||||
print " <body>"
|
||||
|
||||
def emit_footer(self):
|
||||
print " </body>"
|
||||
print "</html>"
|
||||
|
||||
def emit_project_change_header(self):
|
||||
print " <h3>Project changes</h3>"
|
||||
print " <hr>"
|
||||
|
||||
def emit_project_change_text(self, text):
|
||||
print " %s<br>" % text
|
||||
|
||||
def emit_project_change_footer(self):
|
||||
# empty
|
||||
pass
|
||||
|
||||
def emit_dir_changes_header(self, name, r1, r2):
|
||||
print " <h3>Changes in %s [%s .. %s]</h3>" % (name, r1, r2)
|
||||
print " <hr>"
|
||||
|
||||
def emit_dir_changes_text(self, remote_url, text):
|
||||
print " <pre>"
|
||||
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 = '<a href="%s">%s</a>' % (lnk, id)
|
||||
print " %s" % txt
|
||||
print " </pre>"
|
||||
|
||||
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()
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/sh
|
||||
|
||||
topdir=$(pwd)
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 <create|restore>"
|
||||
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 "<project ")
|
||||
if [ -z "$prj_entry" ]; then
|
||||
continue
|
||||
fi
|
||||
dir=$(echo $prj_entry | egrep -o "path=([^ ]*)" | cut -d'"' -f2)
|
||||
tag=$(echo $prj_entry | egrep -o "revision=([^ ]*)" | cut -d'"' -f2)
|
||||
if [ -z "$dir" -o -z "$tag" ]; then
|
||||
echo "Malformed line $line"
|
||||
continue
|
||||
fi
|
||||
if [ ! -d "$topdir/$dir" ]; then
|
||||
echo "No such dir $dir"
|
||||
continue
|
||||
fi
|
||||
echo "$dir -> $tag"
|
||||
cd "$topdir/$dir"
|
||||
git checkout "$tag"
|
||||
done
|
||||
}
|
||||
|
||||
case "$action" in
|
||||
create) create_tag ;;
|
||||
restore) restore_tag ;;
|
||||
*) usage ;;
|
||||
esac
|
|
@ -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] <change-num>"
|
||||
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)
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec gerrit-fetch --post=cherry-pick "$@"
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec gerrit-fetch --post=pull "$@"
|
|
@ -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"
|
Loading…
Reference in New Issue