1#!/usr/bin/env bash
2
3# intialize a new worktree from a PR number:
4#
5# - creates a new remote using the fork's clone URL
6# - creates a local branch tracking the remote branch
7# - creates a new worktree in a parent folder, suffixed with "-pr-$PR"
8#
9# sample usage:
10# ./scripts/pr2wt.sh 12345
11# ./scripts/pr2wt.sh 12345 opencode
12# ./scripts/pr2wt.sh 12345 "cmake -B build && cmake --build build"
13# ./scripts/pr2wt.sh 12345 "bash -l"
14
15function usage() {
16 echo "usage: $0 <pr_number> [cmd]"
17 exit 1
18}
19
20# check we are in the right directory
21if [[ ! -f "scripts/pr2wt.sh" ]]; then
22 echo "error: this script must be run from the root of the repository"
23 exit 1
24fi
25
26if [[ $# -lt 1 || $# -gt 2 ]]; then
27 usage
28fi
29
30PR=$1
31[[ "$PR" =~ ^[0-9]+$ ]] || { echo "error: PR number must be numeric"; exit 1; }
32
33url_origin=$(git config --get remote.origin.url) || {
34 echo "error: no remote named 'origin' in this repository"
35 exit 1
36}
37
38org_repo=$(echo $url_origin | cut -d/ -f4-)
39org_repo=${org_repo%.git}
40
41echo "org/repo: $org_repo"
42
43meta=$(curl -sSLf -H "Accept: application/vnd.github+json" "https://api.github.com/repos/$org_repo/pulls/$PR")
44
45url_remote=$(echo "$meta" | jq -r '.head.repo.clone_url')
46head_ref=$(echo "$meta" | jq -r '.head.ref')
47
48echo "url: $url_remote"
49echo "head_ref: $head_ref"
50
51url_remote_cur=$(git config --get "remote.pr/$PR.url" 2>/dev/null || true)
52
53if [[ "$url_remote_cur" != "$url_remote" ]]; then
54 git remote rm pr/$PR 2> /dev/null
55 git remote add pr/$PR "$url_remote"
56fi
57
58git fetch "pr/$PR" "$head_ref"
59
60dir=$(basename $(pwd))
61
62git branch -D pr/$PR 2> /dev/null
63git worktree add -b pr/$PR ../$dir-pr-$PR pr/$PR/$head_ref 2> /dev/null
64
65wt_path=$(cd ../$dir-pr-$PR && pwd)
66
67echo "git worktree created in $wt_path"
68
69cd $wt_path
70git branch --set-upstream-to=pr/$PR/$head_ref
71git pull --ff-only || {
72 echo "error: failed to pull pr/$PR"
73 exit 1
74}
75
76if [[ $# -eq 2 ]]; then
77 echo "executing: $2"
78 eval "$2"
79fi