summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-07-05 13:54:00 +0200
committerPeter Wu <peter@lekensteyn.nl>2014-07-05 13:54:00 +0200
commitea3c2837b880e624d698c1c7687f227eb4da1078 (patch)
tree2fb545dc9d40292c3966a77acaffe10a6ba0674d
parent5df0397960b00b7d82c098204aa52577dbc17046 (diff)
downloadscripts-ea3c2837b880e624d698c1c7687f227eb4da1078.tar.gz
gerrit-add-reviewers: helper to add reviewers for commits
Originally I wanted it to be a git-review post-review hook, but there seems to be no way to get the most recently pushed commits.
-rwxr-xr-xgit/gerrit-add-reviewers131
1 files changed, 131 insertions, 0 deletions
diff --git a/git/gerrit-add-reviewers b/git/gerrit-add-reviewers
new file mode 100755
index 0000000..a9d6347
--- /dev/null
+++ b/git/gerrit-add-reviewers
@@ -0,0 +1,131 @@
+#!/bin/bash
+# Finds commits with a review tag ("R=foo@example.com") and adds them as
+# gerrit reviewer.
+#
+# Author: Peter Wu <lekensteyn@gmail.com>
+# http://stackoverflow.com/q/24576855/427545
+#
+# Requirements: git, awk, ssh, bash
+
+cd "$(git rev-parse --show-toplevel)"
+
+user=
+host=
+port=29418
+project=
+
+# Load host from gitreview file if any
+[ ! -f .gitreview ] ||
+eval $(awk -F= '
+$1 == "host" && $2 ~ /^[a-zA-Z0-9][a-zA-Z0-9.-]*$/ { print "host=" $2 }
+$1 == "port" && $2 ~ /^[0-9]{1,5}$/ { print "port=" $2 }
+$1 == "project" && $2 ~ /^[a-zA-Z0-9._][a-zA-Z0-9._-]*$/ { print "project=" $2 }
+' .gitreview)
+
+# Load settings from git config
+eval $(git remote -v show -n |
+awk -vorighost=$host '/fetch\)$/ && $2 ~ /^ssh:/ {
+ split($2, url, /[/:@]+/);
+
+ # Apply settings on first result, or if the host matches
+ if (!got_one || orighost == url[3]) {
+ if (url[2] ~ /^[a-zA-Z0-9][a-zA-Z0-9.-]*$/)
+ print "user=" url[2];
+ if (url[3] ~ /^[a-zA-Z0-9][a-zA-Z0-9.-]*$/)
+ print "host=" url[3];
+ if (url[4] ~ /^[0-9]{1,5}$/)
+ print "port=" url[4];
+ got_one = 1;
+ }
+}')
+
+find_reviewers() {
+ local commit=$1
+
+ git show --no-patch --format=%b "$commit" |
+ awk -F= '/^R=[a-zA-Z0-9@._+-]+$/ { print $2 }'
+}
+
+set_reviewer() {
+ local cmd reviewer
+ local commit=$1 # Commit or Change-Id
+ shift # Remaining arguments: reviewers
+
+ # https://review.openstack.org/Documentation/cmd-set-reviewers.html
+ cmd='gerrit set-reviewers'
+ [ -z "$project" ] || cmd="$cmd --project $project"
+ for reviewer; do
+ cmd="$cmd -a $reviewer"
+ done
+ cmd="$cmd -- $commit"
+
+ echo "$cmd" >&2
+ ssh -p $port "$user@$host" "$cmd"
+}
+
+check_commits() {
+ local revlist=$1 commits count=0 retval=0
+
+ # One is not going to push that many commits/reviews at a time...
+ commits="$(git rev-list --reverse --max-count=100 $revlist --)" || return 1
+
+ if [ -z "$commits" ]; then
+ echo "No commits found" >&2
+ return 1
+ fi
+
+ for commit in $commits; do
+ reviewers=$(find_reviewers $commit)
+ if [ -n "$reviewers" ]; then
+ echo "Adding reviewers for $commit..." >&2
+ if ! set_reviewer $commit $reviewers; then
+ echo >&2
+ echo "Run 'git review' if you get a 'no such change' error" >&2
+ retval=1
+ break
+ fi
+ ((count++))
+ fi
+ done
+
+ printf 'Touched %d commits' $count >&2
+ if [ $retval -eq 0 ]; then
+ echo . >&2
+ else
+ echo ", but stopped due to an error" >&2
+ fi
+
+ return $retval
+}
+
+if [ -z "$user" ] || [ -z "$host" ]; then
+ echo "Warning: gerrit is not configured" >&2
+ exit 1
+fi
+
+case ${0##*/} in
+post-review)
+ # TODO
+ # maybe read https://review.openstack.org/Documentation/cmd-query.html
+ # if pre:
+ # create temp file with possibly unprocessed commits
+ echo "$0: Not implemented" >&2
+ ;;
+pre-review)
+ # TODO
+ # elif post:
+ # read temp file
+ # for each reviewer in temp file:
+ # ssh user@host -p port 'gerrit command to set reviewer'
+ echo "$0: Not implemented" >&2
+ ;;
+*)
+ if [[ $1 == *..* ]]; then
+ check_commits "$1"
+ else
+ echo "Usage: $0 <revlist>" >&2
+ echo "To review changes on this branch since master: $0 master.." >&2
+ exit 1
+ fi
+ ;;
+esac