-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeb-add-patch
More file actions
executable file
·132 lines (120 loc) · 5.33 KB
/
Copy pathdeb-add-patch
File metadata and controls
executable file
·132 lines (120 loc) · 5.33 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
#!/usr/bin/env bash
#
# deb-add-patch — add source patch(es) to the gbp patch queue across active
# distro branches.
#
# NOTE: this is for changes to the *upstream source* (they become debian/patches
# entries via the gbp patch queue). For a change to the *packaging* itself (a
# debian/ file — rules, control.in, ci-upload.sh, …) use deb-pkg-update instead,
# which cherry-picks the commit directly onto each branch (and has --no-bump for a
# changelog-free propagation).
#
# Usage: ./deb-add-patch <repo> <commit> [<commit>...] -m "<message>" [--only <glob>[,…]]...
# ./deb-add-patch <repo> <commit> [<commit>...] --no-bump [--only <glob>[,…]]...
#
# <repo> managed checkout directory (e.g. liboxenmq)
# <commit> one or more commit-ish to cherry-pick into the patch queue
# -m MSG changelog/commit message (required unless --no-bump)
# --only <glob> restrict to distro branches matching <glob> (e.g. debian/sid,
# a bare codename like sid, or 'debian/*'), for a fix only some
# distros need. Repeatable and comma-separated.
# --no-bump apply the patch(es) with NO version bump and NO changelog entry
# (just re-export the patch queue and commit). Use when the current
# version was never built/published, so the fix needs no new version
# to distinguish it — e.g. fixing a build error on the distros whose
# build failed. Takes no -m; combine with --only to target them.
#
# For each branch it imports the patch queue, cherry-picks the commit(s), exports
# the patches back, and commits. Unless --no-bump, it then updates the changelog,
# regenerates debian/control, and re-commits (no push; use deb-push).
#
# Version: a full run bumps the debian revision (<upstream>-<N+1><suffix>). An
# --only run instead appends/increments a +M (<version>+M) and leaves -N alone —
# a per-distro -N bump would outrank newer distros' packages and break
# distro-upgrade ordering. --no-bump changes the version not at all.
#
# On a cherry-pick conflict it stops with resume instructions; fix it and re-run
# the same command to continue.
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib.bash"
INVOCATION="$0 $*"
[ $# -ge 1 ] || usage
case "$1" in -h|--help) usage 0 ;; esac
repo="$1"; shift
resolve_repo "$repo"
begin_or_resume add-patch
if [ "$RESUMING" = 0 ]; then
COMMIT_MSG=""
NOBUMP=0
commit_args=()
only_globs=()
while [ $# -gt 0 ]; do
case "$1" in
-m) shift; [ $# -gt 0 ] || die "-m requires a message"; COMMIT_MSG="$1" ;;
-m*) COMMIT_MSG="${1#-m}" ;;
--no-bump) NOBUMP=1 ;;
--only) shift; [ $# -gt 0 ] || die "--only needs a distro glob"; mapfile -t -O "${#only_globs[@]}" only_globs < <(expand_distro_spec "$1") ;;
--only=*) mapfile -t -O "${#only_globs[@]}" only_globs < <(expand_distro_spec "${1#--only=}") ;;
-h|--help) usage 0 ;;
-*) die "unknown option: $1" ;;
*) commit_args+=("$1") ;;
esac
shift
done
[ "${#commit_args[@]}" -ge 1 ] || die "at least one commit to cherry-pick is required"
if [ "$NOBUMP" = 1 ]; then
[ -z "$COMMIT_MSG" ] || die "--no-bump writes no changelog entry, so it doesn't take -m"
else
[ -n "$COMMIT_MSG" ] || die "a changelog message (-m) is required"
fi
require_clean_tree
msg "Fetching origin..."
git fetch -q origin
# --only: restrict to matching branches. In bump mode use a +M bump (leaves -N
# intact); --no-bump leaves the version untouched entirely.
if [ "${#only_globs[@]}" -gt 0 ]; then
[ "$NOBUMP" = 1 ] || PARTIAL=1
hits=""
for g in "${only_globs[@]}"; do
m=""
for b in "${distros[@]}"; do case "$b" in $g) m+=" $b" ;; esac; done
[ -n "$m" ] || die "no active branch matches '$g'"
hits+="$m"
done
TARGET="$(printf '%s\n' $hits | awk 'NF && !seen[$0]++' | tr '\n' ' ')"
fi
require_branches
# Resolve commit-ish to stable hashes now (before switching branches).
COMMITS=()
for c in "${commit_args[@]}"; do
h="$(git rev-parse --verify -q "$c^{commit}")" || die "unknown commit: $c"
COMMITS+=("$h")
done
if [ "$NOBUMP" = 1 ]; then
msg "Patching (no bump) $(cpkg "${TARGET:-${distros[*]}}"): ${#COMMITS[@]} commit(s)"
elif [ "${PARTIAL:-0}" = 1 ]; then
msg "Patching (--only) $(cpkg "$TARGET"): +M bump, ${#COMMITS[@]} commit(s)"
else
cur="$(changelog_version "$(branch_ref debian/sid)")"
VERSION_BASE="$(bump_revision "$cur")"
msg "Revision bump: $cur -> $VERSION_BASE (${#COMMITS[@]} commit(s))"
fi
save_state "" ""
fi
proc_patch() {
local b="$1"
if [ -z "$RESUME_PHASE" ]; then
checkout_uptodate "$b"
gbp pq import --force # leaves us on the patch-queue branch
save_state "$b" cherry-pick
git cherry-pick "${COMMITS[@]}" ||
conflict_halt "$b" cherry-pick "cherry-picking onto the $b patch queue"
else
ensure_resolved "$b" "$RESUME_PHASE"
fi
gbp pq export --commit
# --no-bump: the exported-patch commit is the whole change; no changelog/version.
[ "${NOBUMP:-0}" = 1 ] || finalize_branch "$b"
}
run_multibranch proc_patch
push_hint