#!/usr/bin/env bash

set -e

usage() {
    cat >&2 <<EOF
usage: $0 PULL_REQUEST_ID COMMIT_COUNT [REMOTE]

Fetch the given GitHub pull request branch and backport it to
the current branch using 'git cherry-pick -x'.

Typical usage is:
  git fetch upstream
  git checkout -b 8.x upstream/8.x
  $0 FIRST_PR_ID
  $0 SECOND_PR_ID
  git push origin +HEAD:backport-changes
EOF
    exit 1
}

pr_id="$1"

if [ -z "$pr_id" ]; then
    usage
fi

fail() {
    echo "$1"
    exit 1
}

type gh >/dev/null 2>&1 \
    || fail "The 'gh' CLI tool is not installed; see https://cli.github.com/"
gh auth status 2>/dev/null || fail "Not authenticated to github"

# Find the last commit that was merged.  We will look back in `main`
# for other commits from the same PR.
# shellcheck disable=SC2016
merge_commit="$(
    gh api graphql \
        -q '.data.repository.pullRequest.timelineItems.nodes[0].commit.oid' \
        -F pr_id="$1" \
        -f query='
query($pr_id:Int!) {
  repository(name: "zulip", owner: "zulip") {
    pullRequest(number:$pr_id) {
      timelineItems(last:1, itemTypes: [MERGED_EVENT]) {
        nodes {
          ... on MergedEvent {
            commit {
              oid
            }
          }
        }
      }
    }
  }
}
'
)"

# We cannot trust the "commits" count on the PR, since only part of it
# may get merged, or it may have commits squashed during the merge.
# Walk backwards on `main` from the merge commit we found, checking
# that each of those commits is still associated with the same PR.
commit_id="$merge_commit"
while true; do
    # shellcheck disable=SC2016
    this_pr="$(gh api graphql -F "commit_id=$commit_id 0" \
        --jq '.data.repository.ref.target.history.edges[].node.associatedPullRequests.nodes[].number' \
        -f query='
query($commit_id: String!) {
  repository(owner: "zulip", name:"zulip") {
    ref(qualifiedName:"main") {
      target {
        ... on Commit {
          history(first:1, after: $commit_id) {
            edges {
              node {
                oid
                associatedPullRequests(first: 1) {
                  nodes {
                    number
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}')"
    if [ "$this_pr" != "$pr_id" ]; then
        break
    fi
    commit_id="$(git rev-parse "$commit_id"~)"
done

set -x
git cherry-pick -x "$commit_id~..$merge_commit"
