blob: 4466ee8493a9df5cc44c734467cb635cd69a2221 [file] [log] [blame]
#!/usr/bin/env bash
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#### CATEGORY=Source tree
### Creates an integration CL to test other CLs in the global integration commit queue.
## usage: fx make-integration-patch
##
## The command prints instructions and prompts the user for input. Once
## all input has been collected, it creates a patches.json file in
## integration/, creates a changelist and pushes it to Gerrit.
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/../lib/vars.sh || exit $?
fx-config-read
function print-instructions {
echo "INSTRUCTIONS:"
echo
echo "For each change you wish to test with global integration:"
echo " 1) Navigate to the change in Gerrit's web UI"
echo " 2) Click on Download Patch (in the menu at the top right)"
echo " 3) Copy any of the download options"
echo " 4) Paste it here followed by a newline"
echo
echo "When all changes have been added, type ^D"
echo
echo "... GO!"
echo
}
function print-help {
echo "usage: fx make-integration-patch [OPTIONS]"
echo " -h, --help this help message"
echo " -m, --message commit message"
echo
print-instructions
}
function print-after-instructions {
echo
echo "The URL for your change is above. You can now navigate there and"
echo "CQ+1 (dry run) the CL to test global integration with your patches."
}
function abort-if-unclean {
local dir="$1"
if ! git -C "${dir}" status --porcelain; then
echo "ERROR: git repo at ${dir} must be clean." > /dev/stderr
exit 1
fi
}
function write-patches-json {
local file="$1/patches.json"
local contents="$2"
echo "$contents" > "$file"
}
function prompt-or-exit {
local prompt="$1"
read -p "${prompt} [yN] " -n 1 -r yesno
echo
if [[ ! "$yesno" =~ ^[Yy]$ ]]; then
exit 0
fi
}
function create-git-commit-and-upload {
local dir="$1"
local message="$2"
git -C "$dir" add -A
if [[ "$message" = "" ]]; then
git -C "$dir" commit -m "DO NOT SUBMIT - testing unsubmitted changes in GI"
else
git -C "$dir" commit -m "$message"
fi
git -C "$dir" push origin "HEAD:refs/for/master%wip"
return $?
}
function read-patches-from-stdin {
local line host project ref first=true
declare -a seen_projects
while read line; do
local url=$(echo "$line" | cut -d " " -f 3 | sed 's/"//g')
host=$(echo "$url" | cut -d / -f 3)
project=$(echo "$url" | cut -d / -f 4-)
ref=$(echo "$line" | cut -d " " -f 4)
if [ -z "$url" ]; then
continue
fi
for seen in "${seen_projects[@]}"; do
if [[ "${seen}" == "${project}" ]]; then
fx-error "You are limited to one patch per project. Project '${project}' saw two patches."
fx-error "Please collapse all changes in one project into a single change."
return 1
fi
done
seen_projects+=("${project}")
# The patches.json requires host-review.googlesource.com, while Gerrit's download
# commands vend host.googlesource.com or just host. For example, some
# repositories will show up as sso://host/project, in which case we extract
# host and need to append -review.googlesource.com to it.
if [[ "$host" =~ .*googlesource.* ]]; then
if [[ "$host" =~ .*-review.* ]]; then
fx-error "Invalid hostname. Make sure you paste the line from" \
"the 'Download' section of the Gerrit CL, not the Gerrit CL itself."
exit 1
fi
host=$(echo "$host" | sed "s/\.googlesource/-review\.googlesource/")
else
host="$host-review.googlesource.com"
fi
if [[ ${first} = false ]]; then
printf ',\n'
fi
printf ' {\n "ref": "%s",\n "host": "%s",\n "project": "%s"\n }' "$ref" "$host" "$project"
first=false
done < /dev/stdin
}
function main {
local integration_dir="${FUCHSIA_DIR}/integration"
local message=
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
print-help
exit 0
;;
-m|--message)
shift
message="$1"
;;
*)
echo "Invalid flag $1"
print-help
exit 1
esac
shift
done
abort-if-unclean "$integration_dir"
print-instructions
# Track seen projects. We are limited to a single patch per project.
local patches
patches=$(read-patches-from-stdin)
local result=$?
if [[ $result -ne 0 ]]; then
exit 1
fi
local patch_file_contents=$(printf '[\n%s\n]' "$patches")
echo
echo "I'm about to write ${integration_dir}/patches.json with the following contents"
echo "and then upload the patch file to Gerrit:"
echo
echo "$patch_file_contents"
echo
prompt-or-exit "Do you want to continue?"
write-patches-json "$integration_dir" "$patch_file_contents"
if create-git-commit-and-upload "$integration_dir" "$message"; then
print-after-instructions
else
echo
echo "ERROR: could not push your patch change to Gerrit. See details above."
echo "Once you have resolve the error, you can push the change to Gerrit "
echo "manually by invoking: "
echo
echo "git -C integration push origin HEAD:refs/for/master"
fi
}
main "$@"