scripts/patch-rework.sh
author Remy Bohmer <linux@bohmer.net>
Thu May 27 23:18:19 2010 +0200 (2010-05-27)
changeset 2060 51e4597b07fc
child 2147 0ec4491d6496
permissions -rwxr-xr-x
scripts: add option to strip all toolchain executables

To reduce filesizes of the toolchain and even improve build times
of projects to be build with this toolchain it is usefull to strip
the delivered toolchain executables. Since it is not likely that we
will debug the toolchain executables itself we do not need the
debug information inside the executables itself.

Signed-off-by: Remy Bohmer <linux@bohmer.net>
     1 #!/bin/sh
     2 
     3 # Get our required options
     4 base="$1"
     5 src="$2"
     6 dst="$3"
     7 shift 3
     8 
     9 # The remainder is for diff
    10 diff="$@"
    11 
    12 # This function checks that the files listed in the file in "$1"
    13 # do exist, at the given depth-stripping level (aka diff -p#)
    14 do_check_files_at_depth() {
    15   local flist="$1"
    16   local depth="$2"
    17   local ok=0  # 0: OK,  !0: KO
    18 
    19   exec 6<&0
    20   exec 7<"${flist}"
    21 
    22   while read -u7 f; do
    23     f="$( echo "${f}" |sed -r -e "s:^([^/]+/){${depth}}::;" )"
    24     [ -f "${f}" ] || ok=1
    25   done
    26 
    27   exec 7<&-
    28   exec <&6
    29 
    30   return ${ok}
    31 }
    32 
    33 mkdir -p "${dst}"
    34 dst="$( cd "${dst}"; pwd )"
    35 
    36 # Iterate through patches
    37 for p in "${src}/"*.patch; do
    38   pname="$( basename "${p}" )"
    39 
    40   printf "Handling patch '${pname}'...\n"
    41 
    42   printf "  creating reference..."
    43   cp -a "${base}" "${base}.orig"
    44   printf " done\n"
    45 
    46   printf "  retrieving patch comment..."
    47   comment="$( awk '
    48 BEGIN { mark=0; }
    49 $0~/^diff --/ { nextfile; }
    50 $1=="---" { mark=1; next; }
    51 $1=="+++" && mark==1 { nextfile; }
    52 { mark=0; print; }
    53 ' "${p}" )"
    54   printf " done\n"
    55 
    56   printf "  creating patched file list..."
    57   diffstat -f 4 -r 2 -u -p 0 "${p}"                         \
    58   |head -n -1                                               \
    59   |awk '{ for(i=NF;i>=NF-5;i--) { $(i) = ""; } print; }'    \
    60   |sort                                                     \
    61   >"diffstat.orig"
    62   printf " done\n"
    63 
    64   pushd "${base}" >/dev/null 2>&1
    65 
    66   # Check all files exist, up to depth 3
    67   printf "  checking depth:"
    68   for((d=0;d<4;d++)); do
    69     printf " ${d}"
    70     if do_check_files_at_depth "../diffstat.orig" ${d}; then
    71       printf " ok, using depth '${d}'\n"
    72       break
    73     fi
    74   done
    75   if [ ${d} -ge 4 ]; then
    76     printf "\n"
    77     printf "  checking depth failed\n"
    78     read -p "  --> enter patch depth (or Ctrl-C to abort): " d
    79   fi
    80 
    81   # Store the original list of fiels touched by the patch,
    82   # removing the $d leading components
    83   sed -r -e "s:^([^/]+/){${d}}::;" "../diffstat.orig" >"${dst}/${pname}.diffstat.orig"
    84 
    85   # Apply the patch proper, and check it applied cleanly.
    86   # We can't check with --dry-run because of patches that
    87   # contain multiple accumulated patches onto a single file.
    88   printf "  applying patch..."
    89   if ! patch -g0 -F1 -f -p${d} <"${p}" >"../patch.out" 2>&1; then
    90     printf " ERROR\n"
    91     # Revert the patch
    92     popd >/dev/null 2>&1
    93     printf "  restoring '${base}'..."
    94     rm -f "diffstat.tmp"
    95     rm -rf "${base}"
    96     mv "${base}.orig" "${base}"
    97     printf " done\n\n"
    98     printf "There was an error while applying:\n  -->  ${p}  <--\n"
    99     printf "'${base}' was restored to the state it was prior to applying this faulty patch.\n"
   100     printf "Here's the 'patch' command, and its output:\n"
   101     printf "  ----8<----\n"
   102     printf "  patch -g0 -F1 -f -p${d} <'${p}'\n"
   103     cat "patch.out" |(IFS=$(printf "\n"); while read line; do printf "  ${line}\n"; done)
   104     rm -f "patch.out"
   105     printf "  ----8<----\n"
   106     exit 1
   107   fi
   108   printf " done\n"
   109 
   110   printf "  removing '.orig' files..."
   111   find . -type f -name '*.orig' -exec rm -f {} +
   112   printf " done\n"
   113 
   114   popd >/dev/null 2>&1
   115 
   116   printf "  re-diffing the patch..."
   117   printf "%s\n\n" "${comment}" >"${dst}/${pname}"
   118   diff -durN "${base}.orig" "${base}" >>"${dst}/${pname}"
   119   printf " done\n"
   120 
   121   if [ -n "${diff}" ]; then
   122     printf "  applying diff filter..."
   123     filterdiff -x "${diff}" "${dst}/${pname}" >"tmp-diff"
   124     mv "tmp-diff" "${dst}/${pname}"
   125     printf " done\n"
   126   fi
   127 
   128   printf "  creating new patched file list..."
   129   diffstat -f 4 -r 2 -u -p 1 "${dst}/${pname}"              \
   130   |head -n -1                                               \
   131   |awk '{ for(i=NF;i>=NF-5;i--) { $(i) = ""; } print; }'    \
   132   |sort                                                     \
   133   >"${dst}/${pname}.diffstat.new"
   134   printf " done\n"
   135 
   136   printf "  removing temporary files/dirs..."
   137   rm -f "patch.out"
   138   rm -f "diffstat.tmp"
   139   rm -rf "${base}.orig"
   140   printf " done\n"
   141 done
   142 
   143 # Scan all new patches to see if they touch
   144 # more files than the original patches
   145 printf "\nChecking resulting patchset:\n"
   146 for p in "${dst}/"*.patch; do
   147   pname="$( basename "${p}" )"
   148 
   149   if ! cmp "${p}.diffstat.orig" "${p}.diffstat.new" >/dev/null; then
   150     printf "  --> '${pname}' differ in touched files <--\n"
   151   fi
   152 done
   153 printf "  done.\n"