author | "Yann E. MORIN" <yann.morin.1998@free.fr> |
Sat Jan 04 16:19:18 2014 +0100 (2014-01-04) | |
changeset 3276 | 22239d19ad65 |
parent 2224 | fc58927f24b8 |
permissions | -rwxr-xr-x |
yann@1624 | 1 |
#!/bin/sh |
yann@1624 | 2 |
|
yann@1624 | 3 |
# Get our required options |
yann@1624 | 4 |
base="$1" |
yann@1624 | 5 |
src="$2" |
yann@1624 | 6 |
dst="$3" |
yann@1624 | 7 |
shift 3 |
yann@1624 | 8 |
|
yann@1624 | 9 |
# The remainder is for diff |
yann@1624 | 10 |
diff="$@" |
yann@1624 | 11 |
|
yann@2224 | 12 |
do_help() { |
yann@2224 | 13 |
cat <<-_EOF_ |
yann@2224 | 14 |
${0##*/}: transform a patchset of non-p1 patches into -p1 patches |
yann@2224 | 15 |
|
yann@2224 | 16 |
Usage: |
yann@2224 | 17 |
${0##*/} <basedir> <src> <dst> [diffopts ...] |
yann@2224 | 18 |
|
yann@2224 | 19 |
Where: |
yann@2224 | 20 |
basedir |
yann@2224 | 21 |
points to the directory of the component to patch |
yann@2224 | 22 |
|
yann@2224 | 23 |
src |
yann@2224 | 24 |
points to the directory containing the existing patchset |
yann@2224 | 25 |
to transform |
yann@2224 | 26 |
|
yann@2224 | 27 |
dst |
yann@2224 | 28 |
points to the directory where to put transformed patches |
yann@2224 | 29 |
|
yann@2224 | 30 |
diffopts |
yann@2224 | 31 |
optional options to pass to diff, for debug purposes. You |
yann@2224 | 32 |
should not need it |
yann@2224 | 33 |
|
yann@2224 | 34 |
Example: |
yann@2224 | 35 |
Transform Gentoo patches against gcc-4.4.2 (some of which are |
yann@2224 | 36 |
-p0, -p1 or even -p2 patches) into all -p1 patches: |
yann@2224 | 37 |
|
yann@2224 | 38 |
tar xjf gcc-4.4.2.tar.bz2 |
yann@2224 | 39 |
patch-rework.sh gcc-4.4.2 \\ |
yann@2224 | 40 |
/path/to/gentoo/gcc/patches \\ |
yann@2224 | 41 |
gcc-4.4.2.patches |
yann@2224 | 42 |
_EOF_ |
yann@2224 | 43 |
} |
yann@2224 | 44 |
|
yann@2224 | 45 |
# Sanity checks |
yann@2224 | 46 |
if [ -z "${base}" \ |
yann@2224 | 47 |
-o ! -d "${base}" \ |
yann@2224 | 48 |
-o ! -d "${src}" \ |
yann@2224 | 49 |
-o -e "${dst}" -a ! -d "${dst}" \ |
yann@2224 | 50 |
]; then |
yann@2224 | 51 |
do_help |
yann@2224 | 52 |
exit 1 |
yann@2224 | 53 |
fi |
yann@2224 | 54 |
|
yann@2224 | 55 |
mkdir -p "${dst}" |
yann@2224 | 56 |
base="${base%%/}" |
yann@2224 | 57 |
src="$( cd "${src}"; pwd )" |
yann@2224 | 58 |
dst="$( cd "${dst}"; pwd )" |
yann@2224 | 59 |
|
yann@1624 | 60 |
# This function checks that the files listed in the file in "$1" |
yann@1624 | 61 |
# do exist, at the given depth-stripping level (aka diff -p#) |
yann@1624 | 62 |
do_check_files_at_depth() { |
yann@1624 | 63 |
local flist="$1" |
yann@1624 | 64 |
local depth="$2" |
yann@2224 | 65 |
local ret=0 # 0: OK, !0: KO |
yann@1624 | 66 |
|
yann@1624 | 67 |
exec 6<&0 |
yann@1624 | 68 |
exec 7<"${flist}" |
yann@1624 | 69 |
|
yann@1624 | 70 |
while read -u7 f; do |
yann@1624 | 71 |
f="$( echo "${f}" |sed -r -e "s:^([^/]+/){${depth}}::;" )" |
yann@2224 | 72 |
[ -f "${f}" ] || ret=1 |
yann@1624 | 73 |
done |
yann@1624 | 74 |
|
yann@1624 | 75 |
exec 7<&- |
yann@1624 | 76 |
exec <&6 |
yann@1624 | 77 |
|
yann@2224 | 78 |
return ${ret} |
yann@1624 | 79 |
} |
yann@1624 | 80 |
|
yann@1624 | 81 |
# Iterate through patches |
yann@1624 | 82 |
for p in "${src}/"*.patch; do |
yann@1624 | 83 |
pname="$( basename "${p}" )" |
yann@1624 | 84 |
|
yann@1624 | 85 |
printf "Handling patch '${pname}'...\n" |
yann@1624 | 86 |
|
yann@1624 | 87 |
printf " creating reference..." |
yann@1624 | 88 |
cp -a "${base}" "${base}.orig" |
yann@1624 | 89 |
printf " done\n" |
yann@1624 | 90 |
|
yann@1624 | 91 |
printf " retrieving patch comment..." |
yann@1624 | 92 |
comment="$( awk ' |
yann@1624 | 93 |
BEGIN { mark=0; } |
yann@1624 | 94 |
$0~/^diff --/ { nextfile; } |
yann@1624 | 95 |
$1=="---" { mark=1; next; } |
yann@1624 | 96 |
$1=="+++" && mark==1 { nextfile; } |
yann@1624 | 97 |
{ mark=0; print; } |
yann@1624 | 98 |
' "${p}" )" |
yann@1624 | 99 |
printf " done\n" |
yann@1624 | 100 |
|
yann@1624 | 101 |
printf " creating patched file list..." |
yann@1624 | 102 |
diffstat -f 4 -r 2 -u -p 0 "${p}" \ |
yann@1624 | 103 |
|head -n -1 \ |
yann@1624 | 104 |
|awk '{ for(i=NF;i>=NF-5;i--) { $(i) = ""; } print; }' \ |
yann@1624 | 105 |
|sort \ |
yann@1624 | 106 |
>"diffstat.orig" |
yann@1624 | 107 |
printf " done\n" |
yann@1624 | 108 |
|
yann@1624 | 109 |
pushd "${base}" >/dev/null 2>&1 |
yann@1624 | 110 |
|
yann@1624 | 111 |
# Check all files exist, up to depth 3 |
yann@1624 | 112 |
printf " checking depth:" |
yann@1624 | 113 |
for((d=0;d<4;d++)); do |
yann@1624 | 114 |
printf " ${d}" |
yann@1624 | 115 |
if do_check_files_at_depth "../diffstat.orig" ${d}; then |
yann@1624 | 116 |
printf " ok, using depth '${d}'\n" |
yann@1624 | 117 |
break |
yann@1624 | 118 |
fi |
yann@1624 | 119 |
done |
yann@1624 | 120 |
if [ ${d} -ge 4 ]; then |
yann@1624 | 121 |
printf "\n" |
yann@1624 | 122 |
printf " checking depth failed\n" |
yann@1624 | 123 |
read -p " --> enter patch depth (or Ctrl-C to abort): " d |
yann@1624 | 124 |
fi |
yann@1624 | 125 |
|
antony@2564 | 126 |
# Store the original list of files touched by the patch, |
yann@1624 | 127 |
# removing the $d leading components |
yann@1624 | 128 |
sed -r -e "s:^([^/]+/){${d}}::;" "../diffstat.orig" >"${dst}/${pname}.diffstat.orig" |
yann@1624 | 129 |
|
yann@1624 | 130 |
# Apply the patch proper, and check it applied cleanly. |
yann@1624 | 131 |
# We can't check with --dry-run because of patches that |
yann@1624 | 132 |
# contain multiple accumulated patches onto a single file. |
yann@1624 | 133 |
printf " applying patch..." |
yann@1624 | 134 |
if ! patch -g0 -F1 -f -p${d} <"${p}" >"../patch.out" 2>&1; then |
yann@2147 | 135 |
printf " ERROR\n\n" |
yann@1624 | 136 |
popd >/dev/null 2>&1 |
yann@1624 | 137 |
printf "There was an error while applying:\n --> ${p} <--\n" |
yann@1624 | 138 |
printf "'${base}' was restored to the state it was prior to applying this faulty patch.\n" |
yann@1624 | 139 |
printf "Here's the 'patch' command, and its output:\n" |
yann@1624 | 140 |
printf " ----8<----\n" |
yann@1624 | 141 |
printf " patch -g0 -F1 -f -p${d} <'${p}'\n" |
yann@2147 | 142 |
sed -r -e 's/^/ /;' "patch.out" |
yann@1624 | 143 |
printf " ----8<----\n" |
yann@1624 | 144 |
exit 1 |
yann@1624 | 145 |
fi |
yann@1624 | 146 |
printf " done\n" |
yann@1624 | 147 |
|
yann@1624 | 148 |
printf " removing '.orig' files..." |
yann@1624 | 149 |
find . -type f -name '*.orig' -exec rm -f {} + |
yann@1624 | 150 |
printf " done\n" |
yann@1624 | 151 |
|
yann@1624 | 152 |
popd >/dev/null 2>&1 |
yann@1624 | 153 |
|
yann@1624 | 154 |
printf " re-diffing the patch..." |
yann@1624 | 155 |
printf "%s\n\n" "${comment}" >"${dst}/${pname}" |
yann@1624 | 156 |
diff -durN "${base}.orig" "${base}" >>"${dst}/${pname}" |
yann@1624 | 157 |
printf " done\n" |
yann@1624 | 158 |
|
yann@1624 | 159 |
if [ -n "${diff}" ]; then |
yann@1624 | 160 |
printf " applying diff filter..." |
yann@1624 | 161 |
filterdiff -x "${diff}" "${dst}/${pname}" >"tmp-diff" |
yann@1624 | 162 |
mv "tmp-diff" "${dst}/${pname}" |
yann@1624 | 163 |
printf " done\n" |
yann@1624 | 164 |
fi |
yann@1624 | 165 |
|
yann@1624 | 166 |
printf " creating new patched file list..." |
yann@1624 | 167 |
diffstat -f 4 -r 2 -u -p 1 "${dst}/${pname}" \ |
yann@1624 | 168 |
|head -n -1 \ |
yann@1624 | 169 |
|awk '{ for(i=NF;i>=NF-5;i--) { $(i) = ""; } print; }' \ |
yann@1624 | 170 |
|sort \ |
yann@1624 | 171 |
>"${dst}/${pname}.diffstat.new" |
yann@1624 | 172 |
printf " done\n" |
yann@1624 | 173 |
|
yann@1624 | 174 |
printf " removing temporary files/dirs..." |
yann@1624 | 175 |
rm -f "patch.out" |
yann@1624 | 176 |
rm -f "diffstat.tmp" |
yann@2147 | 177 |
rm -f "diffstat.orig" |
yann@1624 | 178 |
rm -rf "${base}.orig" |
yann@1624 | 179 |
printf " done\n" |
yann@1624 | 180 |
done |
yann@1624 | 181 |
|
yann@1624 | 182 |
# Scan all new patches to see if they touch |
yann@1624 | 183 |
# more files than the original patches |
yann@1624 | 184 |
printf "\nChecking resulting patchset:\n" |
yann@1624 | 185 |
for p in "${dst}/"*.patch; do |
yann@1624 | 186 |
pname="$( basename "${p}" )" |
yann@1624 | 187 |
|
yann@1624 | 188 |
if ! cmp "${p}.diffstat.orig" "${p}.diffstat.new" >/dev/null; then |
yann@1624 | 189 |
printf " --> '${pname}' differ in touched files <--\n" |
yann@2147 | 190 |
else |
yann@2147 | 191 |
rm -f "${p}.diffstat.orig" "${p}.diffstat.new" |
yann@1624 | 192 |
fi |
yann@1624 | 193 |
done |
yann@1624 | 194 |
printf " done.\n" |