blob: bf552037ebcf48cbe4c340b330a856e5e8e9e051 [file] [log] [blame]
#!/usr/bin/env bash
# run a gerrit ssh command
gssh() { ssh -x -p "$PORT" "$SERVER" "$@" ; 2>&1 ; } # [args]...
query() {
gssh gerrit query --format=json "$@" | head -1 | \
python -c 'import sys,json; print json.dumps(json.load(sys.stdin))'
}
q() { "$@" > /dev/null 2>&1 ; } # cmd [args...] # quiet a command
die() { echo -e "$@" ; exit 1 ; } # error_message
mygit() { git --work-tree="$REPO_DIR" --git-dir="$GIT_DIR" "$@" ; } # [args...]
# > uuid
gen_uuid() { uuidgen | openssl dgst -sha1 -binary | xxd -p; }
gen_commit_msg() { # msg > commit_msg
local msg=$1
echo "$msg
Change-Id: I$(gen_uuid)"
}
get_open_changes() {
curl --netrc --silent "http://$SERVER:8080/a/changes/?q=status:open"
}
get_branch_revision() { # prj branch > revision
curl --netrc --silent \
"http://$SERVER:8080/a/projects/$1/branches/$2" | \
tail -n +2 | jq --raw-output '.revision'
}
create_branch() { # prj revision dest_branch
curl --netrc --silent --data "revision=$2" \
"http://$SERVER:8080/a/projects/$1/branches/$3"
}
get_change_num() { # < gerrit_push_response > changenum
local url=$(awk '$NF ~ /\[NEW\]/ { print $2 }')
echo "${url##*\/}" | tr -d -c '[:digit:]'
}
cherry_pick_change() { # change_num dest_branch > changenum
curl -X POST --netrc --silent --header 'Content-Type: application/json' \
--data '{"message" : "Copied Change", "destination" : "'$2'"}' \
"http://$SERVER:8080/a/changes/$1/revisions/current/cherrypick" | \
tail -n +2 | jq --raw-output '._number'
}
create_change() { # branch file [commit_message] > changenum
local branch=$1 tmpfile=$2 msg=$3 out rtn
local content=$RANDOM dest=refs/for/$branch
out=$(mygit fetch "$GITURL" "$branch" 2>&1) ||\
die "Failed to fetch $branch: $out"
out=$(mygit checkout FETCH_HEAD 2>&1) ||\
die "Failed to checkout $branch: $out"
echo -e "$content" > "$tmpfile"
out=$(mygit add "$tmpfile" 2>&1) || die "Failed to git add: $out"
msg=$(gen_commit_msg "Add $tmpfile")
out=$(mygit commit -m "$msg" 2>&1) ||\
die "Failed to commit change: $out"
[ -n "$VERBOSE" ] && echo " commit:$out" >&2
out=$(mygit push "$GITURL" "HEAD:$dest" 2>&1) ||\
die "Failed to push change: $out"
out=$(echo "$out" | get_change_num) ; rtn=$? ; echo "$out"
[ -n "$VERBOSE" ] && echo " change:$out" >&2
return $rtn
}
get_depends_on_tag() { # change > depends-on tag
local change_number=$1
IFS=$'\n'
local comments=( $(gssh gerrit query --comments "$change_number") )
IFS=''
for ((i = "${#comments[@]}" -1 ; i >= 0 ; i--)) ; do
if [[ "${comments[i]}" =~ 'Depends-on:' ]] ; then
echo "${comments[i]}" | sed 's/^ *//g'
break
fi
done
}
# ------------------------- Usage ---------------------------
usage() { # [error_message]
cat <<-EOF
Usage: $MYPROG [-s|--server <server>] [-p|--project <project>]
[-r|--srcref <ref branch>] [-d|--destref <ref branch>] [-h|--help]
-h|--help usage/help
-s|--server <server> server to use for the test (default: localhost)
-p|--project <project> git project to use (default: project0)
-r|--srcref <ref branch> reference branch used to create changes (default: master)
-d|--destref <ref branch> reference branch used to propagate change (default: foo)
EOF
[ -n "$1" ] && echo -e '\n'"ERROR: $1"
exit 1
}
parseArgs() {
SERVER="localhost"
PROJECT="tools/test/project0"
SRC_REF_BRANCH="master"
DEST_REF_BRANCH="foo"
while (( "$#" )) ; do
case "$1" in
--server|-s) shift; SERVER=$1 ;;
--project|-p) shift; PROJECT=$1 ;;
--srcref|-r) shift; SRC_REF_BRANCH=$1 ;;
--destref|-d) shift; DEST_REF_BRANCH=$1 ;;
--help|-h) usage ;;
--verbose|-v) VERBOSE=$1 ;;
*) usage "invalid argument '$1'" ;;
esac
shift
done
[ -n "$SERVER" ] || usage "server not set"
[ -n "$PROJECT" ] || usage "project not set"
[ -n "$SRC_REF_BRANCH" ] || usage "source ref branch not set"
[ -n "$DEST_REF_BRANCH" ] || usage "dest ref branch not set"
}
MYPROG=$(basename "$0")
MYDIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
source "$MYDIR/lib_result.sh"
PORT=29418
parseArgs "$@"
TEST_DIR="$MYDIR/../target/test"
rm -rf "$TEST_DIR"
mkdir -p "$TEST_DIR"
GITURL=ssh://$SERVER:$PORT/$PROJECT
# We need to do an initial REST call, as the first REST call after a server is
# brought up results in being anonymous despite providing proper authentication.
q get_open_changes
q create_branch "$PROJECT" "$(get_branch_revision "$PROJECT" "$SRC_REF_BRANCH")" "$DEST_REF_BRANCH"
SRC_REF=$SRC_REF_BRANCH
echo "$SRC_REF_BRANCH" | grep -q '^refs/' || SRC_REF=refs/heads/$SRC_REF_BRANCH
git ls-remote "$GITURL" | grep -q "$SRC_REF" || usage "invalid project/server/srcref"
DEST_REF=$DEST_REF_BRANCH
echo "$DEST_REF_BRANCH" | grep -q '^refs/' || DEST_REF=refs/heads/$DEST_REF_BRANCH
git ls-remote "$GITURL" | grep -q "$DEST_REF" || usage "invalid project/server/destref"
REPO_DIR=$TEST_DIR/repo
q git init "$REPO_DIR"
GIT_DIR=$REPO_DIR/.git
FILE_A=$REPO_DIR/fileA
# ------------------------- Depends-on Test ---------------------------
base_change=$(create_change "$SRC_REF_BRANCH" "$FILE_A") || exit
src_change=$(create_change "$SRC_REF_BRANCH" "$FILE_A") || exit
gssh gerrit review --message \'"Depends-on: $base_change"\' "$src_change",1
dest_change=$(cherry_pick_change "$src_change" "$DEST_REF")
expected="Depends-on: $(query "$base_change" | jq --raw-output '.id')"
actual=$(get_depends_on_tag "$dest_change")
result_out "propagate depends-on" "$expected" "$actual"
exit $RESULT