mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-02 03:28:28 -04:00
ee6c91e094
Port 1.5
(cherry picked from commit 406dcfe110)
120 lines
4.1 KiB
Bash
Executable File
120 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Port (cherry-pick -x) commits onto a release branch.
|
|
#
|
|
# Usage: port.sh <target-branch> <sha> [<sha>...]
|
|
#
|
|
# Already-ported commits are skipped. Conflicts get a port/<sha>-<ver>
|
|
# branch and a comment on the "Port status: <target>" tracking issue.
|
|
#
|
|
# Requires: full-history checkout, git identity, push access, gh auth.
|
|
# Env: PORT_SOURCE_PR - source PR number (optional, for reporting)
|
|
set -euo pipefail
|
|
|
|
TARGET="${1:?usage: port.sh <target-branch> <sha> [<sha>...]}"
|
|
shift
|
|
[ "$#" -ge 1 ] || { echo "error: no commits given" >&2; exit 1; }
|
|
|
|
REPO="${GITHUB_REPOSITORY:-$(gh repo view --json nameWithOwner --jq .nameWithOwner)}"
|
|
TRACKING_TITLE="Port status: ${TARGET}"
|
|
|
|
log() { echo "[port] $*" >&2; }
|
|
|
|
git fetch origin "refs/heads/${TARGET}:refs/remotes/origin/${TARGET}" --quiet ||
|
|
{ echo "error: branch origin/${TARGET} not found" >&2; exit 1; }
|
|
|
|
tracking_issue() {
|
|
local num
|
|
num=$(gh issue list --repo "$REPO" --state open --search "in:title \"${TRACKING_TITLE}\"" \
|
|
--json number,title --jq "map(select(.title == \"${TRACKING_TITLE}\")) | .[0].number // empty")
|
|
if [ -z "$num" ]; then
|
|
num=$(gh issue create --repo "$REPO" --title "${TRACKING_TITLE}" \
|
|
--body "Maintainer tracking issue for ports to \`${TARGET}\`. The port audit updates this body; the port engine reports conflicts as comments." \
|
|
| grep -oE '[0-9]+$')
|
|
fi
|
|
echo "$num"
|
|
}
|
|
|
|
already_ported() {
|
|
local sha="$1"
|
|
if git log "origin/${TARGET}" --grep="cherry picked from commit ${sha}" --format=%H | grep -q .; then
|
|
return 0
|
|
fi
|
|
# git cherry prints "- <sha>" when a patch-equivalent commit exists upstream
|
|
if git cherry "origin/${TARGET}" "$sha" "${sha}~1" 2>/dev/null | grep -q "^- "; then
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
report_conflict() {
|
|
local sha="$1" short subject branch issue
|
|
short=$(git rev-parse --short "$sha")
|
|
subject=$(git log -1 --format=%s "$sha")
|
|
local ver="${TARGET#stable-}"
|
|
branch="port/${short}-${ver}"
|
|
git push origin "refs/remotes/origin/${TARGET}:refs/heads/${branch}" 2>/dev/null ||
|
|
log "conflict branch ${branch} already exists"
|
|
issue=$(tracking_issue)
|
|
gh issue comment "$issue" --repo "$REPO" --body "$(cat <<EOF
|
|
:warning: **Conflict** porting \`${short}\` — ${subject}${PORT_SOURCE_PR:+ (from #${PORT_SOURCE_PR})} — to \`${TARGET}\`.
|
|
|
|
Resolve locally:
|
|
\`\`\`bash
|
|
git fetch origin
|
|
git switch ${branch}
|
|
git cherry-pick -x ${sha}
|
|
# resolve conflicts, git cherry-pick --continue, then:
|
|
git push origin ${branch}:${TARGET}
|
|
git push origin --delete ${branch}
|
|
\`\`\`
|
|
EOF
|
|
)"
|
|
log "conflict on ${short} reported to issue #${issue}"
|
|
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
|
|
echo ":warning: conflict porting \`${short}\` (${subject}) to \`${TARGET}\` — see tracking issue #${issue}" >> "$GITHUB_STEP_SUMMARY"
|
|
fi
|
|
}
|
|
|
|
WORK="_port_worktree_$$"
|
|
git worktree add --detach "$WORK" "origin/${TARGET}" >/dev/null
|
|
trap 'cd "${OLDPWD:-.}" 2>/dev/null; git worktree remove --force "$WORK" 2>/dev/null || true' EXIT
|
|
cd "$WORK"
|
|
|
|
picked=0
|
|
for ref in "$@"; do
|
|
sha=$(git rev-parse --verify "${ref}^{commit}") || { log "skip ${ref}: not a commit"; continue; }
|
|
short=$(git rev-parse --short "$sha")
|
|
|
|
if already_ported "$sha"; then
|
|
log "skip ${short}: already on ${TARGET}"
|
|
continue
|
|
fi
|
|
|
|
pick_args=(-x)
|
|
# PR merge commits need the mainline parent
|
|
if [ "$(git rev-list --no-walk --count --min-parents=2 "$sha")" -gt 0 ]; then
|
|
pick_args+=(-m 1)
|
|
fi
|
|
|
|
if git cherry-pick "${pick_args[@]}" "$sha"; then
|
|
log "picked ${short}"
|
|
picked=$((picked + 1))
|
|
else
|
|
git cherry-pick --abort || true
|
|
report_conflict "$sha"
|
|
fi
|
|
done
|
|
|
|
if [ "$picked" -gt 0 ]; then
|
|
if ! git push origin "HEAD:refs/heads/${TARGET}"; then
|
|
# another run may have advanced the branch; rebase our picks and retry once
|
|
git fetch origin "refs/heads/${TARGET}:refs/remotes/origin/${TARGET}"
|
|
git rebase "origin/${TARGET}"
|
|
git push origin "HEAD:refs/heads/${TARGET}"
|
|
fi
|
|
log "pushed ${picked} commit(s) to ${TARGET}"
|
|
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
|
|
echo ":white_check_mark: ported ${picked} commit(s) to \`${TARGET}\`" >> "$GITHUB_STEP_SUMMARY"
|
|
fi
|
|
fi
|