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