From 3906acc00779dd31df84d4f555ecbc0d920e89f3 Mon Sep 17 00:00:00 2001 From: Alexey Neyman Date: Mon, 20 Mar 2017 23:01:44 -0700 Subject: Move some scripts to a new directory, maintainer ... which are not of much interest to the end user. Signed-off-by: Alexey Neyman --- maintainer/patch-rework.sh | 196 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100755 maintainer/patch-rework.sh (limited to 'maintainer/patch-rework.sh') diff --git a/maintainer/patch-rework.sh b/maintainer/patch-rework.sh new file mode 100755 index 00000000..d05d2c18 --- /dev/null +++ b/maintainer/patch-rework.sh @@ -0,0 +1,196 @@ +#!/bin/sh + +# Get our required options +base="$1" +src="$2" +dst="$3" +shift 3 + +# The remainder is for diff +diff="$@" + +do_help() { + cat <<-_EOF_ + ${0##*/}: transform a patchset of non-p1 patches into -p1 patches + + Usage: + ${0##*/} [diffopts ...] + + Where: + basedir + points to the directory of the component to patch + + src + points to the directory containing the existing patchset + to transform + + dst + points to the directory where to put transformed patches + + diffopts + optional options to pass to diff, for debug purposes. You + should not need it + + Example: + Transform Gentoo patches against gcc-4.4.2 (some of which are + -p0, -p1 or even -p2 patches) into all -p1 patches: + + tar xjf gcc-4.4.2.tar.bz2 + patch-rework.sh gcc-4.4.2 \\ + /path/to/gentoo/gcc/patches \\ + gcc-4.4.2.patches + _EOF_ +} + +# Sanity checks +if [ -z "${base}" \ + -o ! -d "${base}" \ + -o ! -d "${src}" \ + -o -e "${dst}" -a ! -d "${dst}" \ + ]; then + do_help + exit 1 +fi + +mkdir -p "${dst}" +base="${base%%/}" +src="$( cd "${src}"; pwd )" +dst="$( cd "${dst}"; pwd )" + +# This function checks that the files listed in the file in "$1" +# do exist, at the given depth-stripping level (aka diff -p#) +do_check_files_at_depth() { + local flist="$1" + local depth="$2" + local ret=0 # 0: OK, !0: KO + + exec 6<&0 + exec 7<"${flist}" + + while read f; do + f="$( echo "${f}" |sed -r -e "s:^([^/]+/){${depth}}::;" )" + [ -f "${f}" ] || ret=1 + done =NF-5;i--) { $(i) = ""; } print; }' \ + |sort \ + >"diffstat.orig" + printf " done\n" + + cd "${base}" + + # Check all files exist, up to depth 3 + printf " checking depth:" + d=0 + while [ $d -lt 4 ]; do + printf " ${d}" + if do_check_files_at_depth "../diffstat.orig" ${d}; then + printf " ok, using depth '${d}'\n" + break + fi + d=$((d + 1)) + done + if [ ${d} -ge 4 ]; then + printf "\n" + printf " checking depth failed\n" + read -p " --> enter patch depth (or Ctrl-C to abort): " d + fi + + # Store the original list of files touched by the patch, + # removing the $d leading components + sed -r -e "s:^([^/]+/){${d}}::;" "../diffstat.orig" >"${dst}/${pname}.diffstat.orig" + + # Apply the patch proper, and check it applied cleanly. + # We can't check with --dry-run because of patches that + # contain multiple accumulated patches onto a single file. + printf " applying patch..." + if ! patch -g0 -F1 -f -p${d} <"${p}" >"../patch.out" 2>&1; then + printf " ERROR\n\n" + cd - >/dev/null + printf "There was an error while applying:\n --> ${p} <--\n" + printf "'${base}' was restored to the state it was prior to applying this faulty patch.\n" + printf "Here's the 'patch' command, and its output:\n" + printf " ----8<----\n" + printf " patch -g0 -F1 -f -p${d} <'${p}'\n" + sed -r -e 's/^/ /;' "patch.out" + printf " ----8<----\n" + exit 1 + fi + printf " done\n" + + printf " removing '.orig' files..." + find . -type f -name '*.orig' -exec rm -f {} + + printf " done\n" + + cd - >/dev/null + + printf " re-diffing the patch..." + printf "%s\n\n" "${comment}" >"${dst}/${pname}" + diff -durN "${base}.orig" "${base}" >>"${dst}/${pname}" + printf " done\n" + + if [ -n "${diff}" ]; then + printf " applying diff filter..." + filterdiff -x "${diff}" "${dst}/${pname}" >"tmp-diff" + mv "tmp-diff" "${dst}/${pname}" + printf " done\n" + fi + + printf " creating new patched file list..." + diffstat -f 4 -r 2 -u -p 1 "${dst}/${pname}" \ + |head -n -1 \ + |awk '{ for(i=NF;i>=NF-5;i--) { $(i) = ""; } print; }' \ + |sort \ + >"${dst}/${pname}.diffstat.new" + printf " done\n" + + printf " removing temporary files/dirs..." + rm -f "patch.out" + rm -f "diffstat.tmp" + rm -f "diffstat.orig" + rm -rf "${base}.orig" + printf " done\n" +done + +# Scan all new patches to see if they touch +# more files than the original patches +printf "\nChecking resulting patchset:\n" +for p in "${dst}/"*.patch; do + pname="$( basename "${p}" )" + + if ! cmp "${p}.diffstat.orig" "${p}.diffstat.new" >/dev/null; then + printf " --> '${pname}' differ in touched files <--\n" + else + rm -f "${p}.diffstat.orig" "${p}.diffstat.new" + fi +done +printf " done.\n" -- cgit v1.2.3