3 # Get our required options
9 # The remainder is for diff
14 ${0##*/}: transform a patchset of non-p1 patches into -p1 patches
17 ${0##*/} <basedir> <src> <dst> [diffopts ...]
21 points to the directory of the component to patch
24 points to the directory containing the existing patchset
28 points to the directory where to put transformed patches
31 optional options to pass to diff, for debug purposes. You
35 Transform Gentoo patches against gcc-4.4.2 (some of which are
36 -p0, -p1 or even -p2 patches) into all -p1 patches:
38 tar xjf gcc-4.4.2.tar.bz2
39 patch-rework.sh gcc-4.4.2 \\
40 /path/to/gentoo/gcc/patches \\
49 -o -e "${dst}" -a ! -d "${dst}" \
57 src="$( cd "${src}"; pwd )"
58 dst="$( cd "${dst}"; pwd )"
60 # This function checks that the files listed in the file in "$1"
61 # do exist, at the given depth-stripping level (aka diff -p#)
62 do_check_files_at_depth() {
65 local ret=0 # 0: OK, !0: KO
71 f="$( echo "${f}" |sed -r -e "s:^([^/]+/){${depth}}::;" )"
72 [ -f "${f}" ] || ret=1
81 # Iterate through patches
82 for p in "${src}/"*.patch; do
83 pname="$( basename "${p}" )"
85 printf "Handling patch '${pname}'...\n"
87 printf " creating reference..."
88 cp -a "${base}" "${base}.orig"
91 printf " retrieving patch comment..."
94 $0~/^diff --/ { nextfile; }
95 $1=="---" { mark=1; next; }
96 $1=="+++" && mark==1 { nextfile; }
101 printf " creating patched file list..."
102 diffstat -f 4 -r 2 -u -p 0 "${p}" \
104 |awk '{ for(i=NF;i>=NF-5;i--) { $(i) = ""; } print; }' \
109 pushd "${base}" >/dev/null 2>&1
111 # Check all files exist, up to depth 3
112 printf " checking depth:"
113 for((d=0;d<4;d++)); do
115 if do_check_files_at_depth "../diffstat.orig" ${d}; then
116 printf " ok, using depth '${d}'\n"
120 if [ ${d} -ge 4 ]; then
122 printf " checking depth failed\n"
123 read -p " --> enter patch depth (or Ctrl-C to abort): " d
126 # Store the original list of files touched by the patch,
127 # removing the $d leading components
128 sed -r -e "s:^([^/]+/){${d}}::;" "../diffstat.orig" >"${dst}/${pname}.diffstat.orig"
130 # Apply the patch proper, and check it applied cleanly.
131 # We can't check with --dry-run because of patches that
132 # contain multiple accumulated patches onto a single file.
133 printf " applying patch..."
134 if ! patch -g0 -F1 -f -p${d} <"${p}" >"../patch.out" 2>&1; then
137 printf "There was an error while applying:\n --> ${p} <--\n"
138 printf "'${base}' was restored to the state it was prior to applying this faulty patch.\n"
139 printf "Here's the 'patch' command, and its output:\n"
140 printf " ----8<----\n"
141 printf " patch -g0 -F1 -f -p${d} <'${p}'\n"
142 sed -r -e 's/^/ /;' "patch.out"
143 printf " ----8<----\n"
148 printf " removing '.orig' files..."
149 find . -type f -name '*.orig' -exec rm -f {} +
154 printf " re-diffing the patch..."
155 printf "%s\n\n" "${comment}" >"${dst}/${pname}"
156 diff -durN "${base}.orig" "${base}" >>"${dst}/${pname}"
159 if [ -n "${diff}" ]; then
160 printf " applying diff filter..."
161 filterdiff -x "${diff}" "${dst}/${pname}" >"tmp-diff"
162 mv "tmp-diff" "${dst}/${pname}"
166 printf " creating new patched file list..."
167 diffstat -f 4 -r 2 -u -p 1 "${dst}/${pname}" \
169 |awk '{ for(i=NF;i>=NF-5;i--) { $(i) = ""; } print; }' \
171 >"${dst}/${pname}.diffstat.new"
174 printf " removing temporary files/dirs..."
177 rm -f "diffstat.orig"
178 rm -rf "${base}.orig"
182 # Scan all new patches to see if they touch
183 # more files than the original patches
184 printf "\nChecking resulting patchset:\n"
185 for p in "${dst}/"*.patch; do
186 pname="$( basename "${p}" )"
188 if ! cmp "${p}.diffstat.orig" "${p}.diffstat.new" >/dev/null; then
189 printf " --> '${pname}' differ in touched files <--\n"
191 rm -f "${p}.diffstat.orig" "${p}.diffstat.new"