-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcranky-reduce-debdiff
More file actions
executable file
·213 lines (180 loc) · 4.77 KB
/
cranky-reduce-debdiff
File metadata and controls
executable file
·213 lines (180 loc) · 4.77 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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#!/bin/bash -eu
#
# Reduce a derivative debdiff by filtering out master changes
#
function out()
{
local rc=${?}
trap - EXIT INT TERM HUP
if [ "${rc}" -ne 0 ] ; then
echo "Script failed" >&2
fi
exit "${rc}"
}
function find_master_commit()
{
local changelog=${1} version=${2}
local src tag found mversion
src=$(dpkg-parsechangelog -l "${changelog}" -S Source)
if [ "${src}" = "linux" ] ; then
tag=Ubuntu-${version//\~/_}
else
tag=Ubuntu${src#linux}-${version//\~/_}
fi
found=0
while IFS= read -r line ; do
case "${line}" in
"linux"*"(${version})"*)
found=1
;;
" [ Ubuntu: "*)
if [ ${found} -eq 1 ] ; then
mversion=${line##* Ubuntu: }
mversion=${mversion%% *}
git log --oneline "${tag}" | \
grep -m1 -P "^[0-9a-f]+ UBUNTU: Ubuntu.*-${mversion}$"
return
fi
;;
esac
done < <(cat "${changelog}")
}
function calc_patch_id()
{
local name=${1}
local patch_id
# File modes can be different in a debdiff due to 'reconstruct' and that
# screws up patch-id, so filter them out
patch_id=$(sed 's/file mode [0-9]*/file mode XXXXXX/' "${name}" | \
git patch-id)
echo "${patch_id% *}"
}
function usage()
{
cat <<EOF
Usage: $(basename "${0}") [-h] [-p PREV_VERSION]
Reduce a derivative debdiff by filtering out master changes.
Optional arguments:
-h, --help Show this help text and exit.
-p, --prev_version PREV_VERSION Use the previous version PREV_VERSION. If
not provided, determines it from the
debdiff.
EOF
}
prev_version=
while [ ${#} -ne 0 ] ; do
case "${1}" in
-h|--help)
usage
exit
;;
-p|--prev_version)
shift
prev_version=${1}
;;
*)
echo "Invalid argument: ${1}" >&2
exit 2
;;
esac
shift
done
if ! [ -e debian/debian.env ] ; then
echo "The current repo is not an Ubuntu kernel repo" >&2
exit 1
fi
# shellcheck disable=SC1091
. debian/debian.env
if [ "${DEBIAN}" = "debian.master" ] ; then
echo "The current repo is not a derivative kernel repo"
exit
fi
trap out EXIT INT TERM HUP
source=$(dpkg-parsechangelog -l "${DEBIAN}"/changelog -S Source)
version=$(dpkg-parsechangelog -l "${DEBIAN}"/changelog -S Version)
debdiff=../${source}_${version}.debdiff
reduced_debdiff=../${source}_${version}.reduced.debdiff
if ! [ -e "${debdiff}" ] ; then
echo "No such debdiff: ${debdiff}" >&2
exit 1
fi
echo "Reducing debdiff ${debdiff}"
if [ -z "${prev_version}" ] ; then
# Pull the previous version from the debdiff
prev_version=$(grep -m1 '^# HEADER Previous: ' "${debdiff}")
prev_version=${prev_version%.dsc}
prev_version=${prev_version%_source.changes}
prev_version=${prev_version#*_}
if [ -z "${prev_version}" ] ; then
echo "Failed to determine previous version from debdiff" >&2
exit 1
fi
fi
# Find the current master commit
master=$(find_master_commit "${DEBIAN}"/changelog "${version}")
if [ -z "${master}" ] ; then
echo "Unable to find master commit for version ${version}" >&2
exit 1
fi
# Find the previous master commit
master_prev=$(find_master_commit "${DEBIAN}"/changelog "${prev_version}")
if [ -z "${master_prev}" ] ; then
echo "Unable to find master commit for previous version ${prev_version}" >&2
exit 1
fi
# Create master diff hunks
echo "Creating master diff hunks for ${master_prev%% *}..${master%% *}" \
"(${master_prev##* }..${master##* })"
rm -rf .master.d
git diff --src-prefix=___AAA___/ --dst-prefix=___BBB___/ \
"${master_prev%% *}" "${master%% *}" | split-git-diff .master.d
# Fix the source and destination prefixes
prefix=${source}_${version}
prev_prefix=${source}_${prev_version}
for f in .master.d/* ; do
if grep -m1 -q '^--- /dev/null' "${f}" ; then
# Added
aaa=${prefix}
bbb=${prefix}
else
# Modified
aaa=${prev_prefix}
bbb=${prefix}
fi
sed -i -e "s/___AAA___/${aaa}/g" -e "s/___BBB___/${bbb}/g" "${f}"
done
# Create debdiff diff hunks
echo "Creating debdiff diff hunks"
rm -rf .debdiff.d
split-git-diff .debdiff.d < "${debdiff}"
# Collect patch IDs from master hunks
master_patch_ids=()
for name in .master.d/* ; do
patch_id=$(calc_patch_id "${name}")
if [ -z "${patch_id}" ] ; then
continue
fi
master_patch_ids+=("${patch_id}")
done
# Collect patch IDs from debdiff hunks
declare -A debdiffs=()
for name in .debdiff.d/* ; do
patch_id=$(calc_patch_id "${name}")
debdiffs[${name}]=${patch_id}
done
# Remove matching debdiff hunks
count=0
for master_patch_id in "${master_patch_ids[@]}" ; do
for name in .debdiff.d/* ; do
patch_id=${debdiffs[${name}]}
if [ "${patch_id}" = "${master_patch_id}" ] ; then
rm "${name}"
count=$((count + 1))
break
fi
done
done
echo "Removed ${count} matching master hunks"
# Assemble the reduced debdiff
cat .debdiff.d/*.diff > "${reduced_debdiff}"
echo "Wrote reduced debdiff ${reduced_debdiff}"