Skip to content

Commit 08acabd

Browse files
committed
add script to cherry-pick
1 parent 15e1389 commit 08acabd

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

cherry-pick-stable.sh

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Parse arguments
6+
DRY_RUN=false
7+
while [[ $# -gt 0 ]]; do
8+
case $1 in
9+
--dry-run|-d)
10+
DRY_RUN=true
11+
shift
12+
;;
13+
--help|-h)
14+
echo "Usage: $0 [OPTIONS]"
15+
echo ""
16+
echo "Cherry-pick commits from PRs labeled 'stable-nominated' to current branch"
17+
echo ""
18+
echo "Options:"
19+
echo " -d, --dry-run Show what would be done without making changes"
20+
echo " -h, --help Show this help message"
21+
exit 0
22+
;;
23+
*)
24+
echo "Unknown option: $1"
25+
echo "Use --help for usage information"
26+
exit 1
27+
;;
28+
esac
29+
done
30+
31+
if [ "$DRY_RUN" = true ]; then
32+
echo "[DRY RUN MODE - No changes will be made]"
33+
echo ""
34+
fi
35+
36+
current_branch=$(git branch --show-current)
37+
echo "Current branch: $current_branch"
38+
echo "Fetching PRs with 'stable-nominated' label..."
39+
echo ""
40+
41+
# Get PRs with stable-nominated label that are merged
42+
# Sort by merge date (oldest first) to preserve merge order and avoid conflicts
43+
# Format: PR number, title, merge commit SHA
44+
prs=$(gh pr list --state merged --label stable-nominated --json number,title,mergeCommit,mergedAt --jq 'sort_by(.mergedAt) | .[] | "\(.number)|\(.title)|\(.mergeCommit.oid)"')
45+
46+
if [ -z "$prs" ]; then
47+
echo "No PRs found with 'stable-nominated' label."
48+
exit 0
49+
fi
50+
51+
# Arrays to track results
52+
declare -a successful
53+
declare -a failed
54+
declare -a skipped
55+
56+
echo "Found PRs to cherry-pick:"
57+
echo ""
58+
59+
# Process each PR
60+
while IFS='|' read -r pr_number title commit_sha; do
61+
echo "----------------------------------------"
62+
echo "PR #${pr_number}: ${title}"
63+
echo "Commit: ${commit_sha}"
64+
65+
# Check if commit already exists in current branch
66+
if git branch --contains "$commit_sha" 2>/dev/null | grep -q "^\*"; then
67+
echo "⏭ Already cherry-picked, skipping"
68+
skipped+=("PR #${pr_number}: ${title}")
69+
echo ""
70+
continue
71+
fi
72+
73+
# Cherry-pick with -xe flags as specified
74+
if [ "$DRY_RUN" = true ]; then
75+
echo "Would cherry-pick with: git cherry-pick -xe $commit_sha"
76+
echo "Would add backport note: (backport https://github.com/rust-lang/libc/pull/$pr_number)"
77+
successful+=("PR #${pr_number}: ${title} (${commit_sha:0:8})")
78+
else
79+
if git cherry-pick -xe "$commit_sha" 2>&1; then
80+
# Add backport note before the cherry-pick note as per CONTRIBUTING.md
81+
current_msg=$(git log -1 --format=%B)
82+
backport_line="(backport https://github.com/rust-lang/libc/pull/$pr_number)"
83+
84+
# Insert backport line before "(cherry picked from commit" line
85+
new_msg=$(echo "$current_msg" | sed "/^(cherry picked from commit/i\\
86+
$backport_line\\
87+
")
88+
89+
# Amend the commit with the new message
90+
git commit --amend -m "$new_msg"
91+
92+
echo "✓ Successfully cherry-picked with backport note"
93+
successful+=("PR #${pr_number}: ${title} (${commit_sha:0:8})")
94+
else
95+
echo "✗ Failed to cherry-pick"
96+
failed+=("PR #${pr_number}: ${title} (${commit_sha:0:8})")
97+
# Abort the failed cherry-pick
98+
git cherry-pick --abort 2>/dev/null || true
99+
fi
100+
fi
101+
echo ""
102+
done <<< "$prs"
103+
104+
# Print summary
105+
echo "========================================"
106+
if [ "$DRY_RUN" = true ]; then
107+
echo "SUMMARY (DRY RUN)"
108+
else
109+
echo "SUMMARY"
110+
fi
111+
echo "========================================"
112+
echo ""
113+
114+
if [ ${#successful[@]} -gt 0 ]; then
115+
if [ "$DRY_RUN" = true ]; then
116+
echo "Would cherry-pick (${#successful[@]}):"
117+
else
118+
echo "Successfully cherry-picked (${#successful[@]}):"
119+
fi
120+
for item in "${successful[@]}"; do
121+
echo "$item"
122+
done
123+
echo ""
124+
fi
125+
126+
if [ ${#skipped[@]} -gt 0 ]; then
127+
echo "Skipped (${#skipped[@]}):"
128+
for item in "${skipped[@]}"; do
129+
echo "$item"
130+
done
131+
echo ""
132+
fi
133+
134+
if [ ${#failed[@]} -gt 0 ]; then
135+
echo "Failed (${#failed[@]}):"
136+
for item in "${failed[@]}"; do
137+
echo "$item"
138+
done
139+
echo ""
140+
if [ "$DRY_RUN" = false ]; then
141+
echo "Please resolve conflicts manually and re-run if needed."
142+
fi
143+
exit 1
144+
fi
145+
146+
if [ "$DRY_RUN" = true ]; then
147+
echo "Dry run complete! Run without --dry-run to apply changes."
148+
else
149+
echo "All done!"
150+
fi

0 commit comments

Comments
 (0)