sync-upstream: Simplify

This commit is contained in:
Tim Ruffing
2026-04-24 11:27:36 +02:00
parent 99fab529bd
commit f0ff45f3ab

View File

@@ -3,112 +3,109 @@
set -eou pipefail set -eou pipefail
help() { help() {
echo "Sync merge commits from bitcoin-core/secp256k1 into secp256k1-zkp." cat <<EOT
echo $0: Prepare a pull request that syncs a branch with upstream
echo "Usage:"
echo " $0 [-b <branch>] <pr_branch>" Usage:
echo " Find every merge commit present in upstream/master and missing in <branch> (default: master)." $0 <base-branch> <upstream-ref>
echo
echo "This tool prepares the title and body for a sync PR" This script creates a sync local branch pointing to <upstream-ref>. Moreover, it
echo "and generates a helper script contrib/gh-pr-create.sh." generates a helper script for opening a pull request (PR) merging the created
echo local branch into <base-branch>.
echo "Setup:"
echo " Requires a remote named 'upstream' pointing to bitcoin-core/secp256k1." The synced upstream PRs are listed in the title and the description of the PR.
echo (This relies on upstream merging PRs using merge commits with titles of the form
echo "Listing upstream merge commits:" "Merge <repo>#<prnum>: ...".)
echo " To list merge commits in upstream/master that are missing from <branch> (oldest first):"
echo " git log --oneline --topo-order --reverse --merges \$(git merge-base upstream/master <branch>)..upstream/master" Arguments:
exit 1 <base-branch>: The branch to sync with upstream
<upstream-ref>: The upstream ref to merge into <base-branch>
Usage examples:
$0 master upstream/master
$0 master abc1234
$0 --switch origin/master upstream/master
To find candidate merge commits from <upstream-ref> (oldest first), use:
git log --oneline --topo-order --reverse --merges \$(git merge-base <upstream-ref> <base-branch>)..<upstream-ref>
EOT
} }
REMOTE=upstream ### Parse arguments
REMOTE_BRANCH="$REMOTE/master" if [ "$#" -ne 2 ]; then
LOCAL_BRANCH="master"
if ! git remote get-url "$REMOTE" &> /dev/null; then
echo "Error: Remote '$REMOTE' not found."
echo "Add it with: git remote add upstream git@github.com:bitcoin-core/secp256k1.git"
echo "Then run: git fetch upstream"
exit 1
fi
range() {
RANGESTART_COMMIT=$(git merge-base "$REMOTE_BRANCH" "$LOCAL_BRANCH")
RANGEEND_COMMIT=$(git rev-parse "$REMOTE_BRANCH")
COMMITS=$(git --no-pager log --pretty=format:%H --topo-order --reverse --merges "$RANGESTART_COMMIT".."$RANGEEND_COMMIT")
}
# Process -b <branch> and -h arguments
while getopts "b:h" opt; do
case $opt in
b)
LOCAL_BRANCH=$OPTARG
;;
h)
help
;;
*)
echo
help
;;
esac
done
# Shift off the processed options
shift $((OPTIND -1))
if [ "$#" -lt 1 ]; then
echo "Error: <pr_branch> argument is required." >&2
echo
help help
exit 1 exit 1
fi fi
BASE_BRANCH="$1"
UPSTREAM_REF="$2"
# Extract the PR branch argument ### Create PR metadata
PR_BRANCH=$1
range
TITLE="Upstream PRs" TITLE="Upstream PRs"
BODY="${GITHUB_ACTIONS+This PR has been created by a GitHub Actions workflow without human involvement.}"$'\n' RANGESTART_COMMIT=$(git merge-base "$UPSTREAM_REF" "$BASE_BRANCH")
for COMMIT in $COMMITS RANGEEND_COMMIT=$(git rev-parse "$UPSTREAM_REF")
do COMMITS=$(git --no-pager log --pretty=format:%H --topo-order --reverse --merges "$RANGESTART_COMMIT".."$RANGEEND_COMMIT")
PRNUM=$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\).*'/'\2'/) # If there are no commits, exit successfully
if [ -z "$COMMITS" ]; then
echo "No merge commits in range ${RANGESTART_COMMIT}..${RANGEEND_COMMIT}" >&2
exit 0
fi
BODY="${GITHUB_ACTIONS+*Note: This PR has been created by a GitHub Actions workflow without human involvement.*
}"
BODY+="This PR syncs the following upstream PRs:"
for COMMIT in $COMMITS; do
PRNUM=$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge .*#\([0-9]*\):.*'/'\1'/)
TITLE="$TITLE $PRNUM," TITLE="$TITLE $PRNUM,"
BODY=$(printf "%s\n%s" "$BODY" "$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\)'/'[bitcoin-core\/secp256k1#\2]'/)") BODY=$(printf "%s\n * %s" "$BODY" "$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge '//)")
LAST_COMMIT="$COMMIT"
done done
# Remove trailing "," # Remove trailing ","
TITLE=${TITLE%?} TITLE=${TITLE%?}
BODY+=$(cat <<EOF BODY+=$(cat <<'EOF'
Tips: Usage hints:
* Use \`git show --remerge-diff <pr-branch>\` to show the conflict resolution in the merge commit. * If this PR has merge conflicts, resolve these by switching to the PR branch and merging the base branch into it using `git merge <base-branch>`.
* Use \`git read-tree --reset -u <pr-branch>\` to replay these resolutions during the conflict resolution stage when recreating the PR branch locally. * To show the conflict resolution diff from an existing merge commit, use `git show --remerge-diff <merge-commit>`.
* In case you are recreating the PR branch locally, you can (during the conflict resolution state) replay this conflict resolution diff using `git read-tree --reset -u <merge-commit>`.
Be aware that this may discard your index as well as the uncommitted changes and untracked files in your worktree. Be aware that this may discard your index as well as the uncommitted changes and untracked files in your worktree.
EOF EOF
) )
### Create a sync branch locally.
SYNC_BRANCH="sync-$(git rev-parse --short "$UPSTREAM_REF")"
# This will error out if the branch already exists, which is what we want.
git branch --no-track "$SYNC_BRANCH" "$UPSTREAM_REF"
### Print the PR metadata
echo "-----------------------------------" echo "-----------------------------------"
echo "$TITLE" echo "$TITLE"
echo "-----------------------------------" echo "-----------------------------------"
echo "$BODY" echo "$BODY"
echo "-----------------------------------" echo "-----------------------------------"
# Escape single quote ### Generate the helper script for creating the PR
# ' -> '\'' FNAME="gh-pr-create.sh"
# Escape single quote ' -> '\''
quote() { quote() {
local quoted=${1//\'/\'\\\'\'} local quoted=${1//\'/\'\\\'\'}
printf "%s" "$quoted" printf "%s" "$quoted"
} }
TITLE=$(quote "$TITLE") TITLE=$(quote "$TITLE")
BODY=$(quote "$BODY") BODY=$(quote "$BODY")
BASEDIR=$(dirname "$0")
FNAME="$BASEDIR/gh-pr-create.sh"
cat <<EOT > "$FNAME" cat <<EOT > "$FNAME"
#!/bin/sh #!/bin/sh
gh pr create -t '$TITLE' -b '$BODY' --base '$LOCAL_BRANCH' --head '$PR_BRANCH' TITLE='$TITLE'
BODY='$BODY'
SYNC_BRANCH='$SYNC_BRANCH'
BASE_BRANCH='$BASE_BRANCH'
gh pr create --base "\$BASE_BRANCH" --head "\$SYNC_BRANCH" --title "\$TITLE" --body "\$BODY" "\$@"
EOT EOT
chmod +x "$FNAME" chmod +x "$FNAME"
echo "Generated $FNAME for creating a pull request with the above title and body."
echo "Successfully created local sync branch $SYNC_BRANCH starting at $UPSTREAM_REF."
echo
echo "You can now:"
echo " 1. Optionally resolve merge conflicts by merging $BASE_BRANCH into $SYNC_BRANCH."
echo " 2. Push $SYNC_BRANCH to some GitHub remote."
echo " 3. Run ./$FNAME to create a pull request. (Tip: Pass --dry-run first.)"