diff --git a/contrib/source-control-tools/autopatch.sh b/contrib/source-control-tools/autopatch.sh index 901cffb75..ddcef9e83 100755 --- a/contrib/source-control-tools/autopatch.sh +++ b/contrib/source-control-tools/autopatch.sh @@ -1,102 +1,104 @@ #!/usr/bin/env bash -# Copyright (c) 2019 The Bitcoin developers +# Copyright (c) 2019-2020 The Bitcoin developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. export LC_ALL=C.UTF-8 set -euxo pipefail -DEFAULT_PATCH_ARGS="--skip-dependencies" +# --force is necessary to skip the "sanity check" step, which conflicts with +# stacked revisions that contain already-landed dependencies. +DEFAULT_PATCH_ARGS="--skip-dependencies --force" DEFAULT_REMOTE="origin" DEFAULT_BRANCH="master" help_message() { set +x echo "Apply a patch from Phabricator cleanly on latest master." echo "" echo "Options:" echo "-b, --branch The git branch to fetch and rebase onto. Default: '${DEFAULT_BRANCH}'" echo "-h, --help Display this help message." echo "-o, --remote The git remote to fetch latest from. Default: '${DEFAULT_REMOTE}'" echo "-p, --patch-args Args to pass to 'arc patch'. Default: '${DEFAULT_PATCH_ARGS}'" echo "-r, --revision The Differential revision ID used in Phabricator that you want to land. (ex: D1234)" echo " This argument is required if --patch-args does not specify a revision or diff ID." set -x } BRANCH="${DEFAULT_BRANCH}" PATCH_ARGS="${DEFAULT_PATCH_ARGS}" REMOTE="${DEFAULT_REMOTE}" REVISION="" # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in -b|--branch) BRANCH="$2" shift # shift past argument shift # shift past value ;; -h|--help) help_message exit 0 shift # shift past argument ;; -o|--remote) REMOTE="$2" shift # shift past argument shift # shift past value ;; -p|--patch-args) PATCH_ARGS="$2" shift # shift past argument shift # shift past value ;; -r|--revision) REVISION="$2" shift # shift past argument shift # shift past value ;; *) echo "Unknown argument: $1" help_message exit 1 shift # shift past argument ;; esac done PATCH_ARGS="${REVISION} ${PATCH_ARGS}" # Make sure there are no unstaged changes, just in case this script is being run locally if [ -n "$(git status --porcelain)" ]; then echo "Error: The source tree has unexpected changes. Clean up any changes (try 'git stash') and try again." exit 10 fi # Fetch and checkout latest changes, bailing if the branch isn't an ancestor of the remote branch. REMOTE_AND_BRANCH="${REMOTE}/${BRANCH}" git fetch "${REMOTE}" "${BRANCH}" git checkout "${BRANCH}" git merge-base --is-ancestor "${BRANCH}" "${REMOTE_AND_BRANCH}" || { echo "Error: Branch '${BRANCH}' is not an ancestor of '${REMOTE_AND_BRANCH}'" exit 11 } git pull "${REMOTE}" "${BRANCH}" ( # If arc fails, there may be a dangling branch. Clean it up before exiting. cleanup() { CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) git checkout "${BRANCH}" git branch -D "${CURRENT_BRANCH}" || true } trap "cleanup" ERR # Note: `: | arc ...` pipes an empty string to stdin incase arcanist prompts # for user input. This fails and is treated as an error. : | arc patch ${PATCH_ARGS} ) git rebase "${BRANCH}"