scripts/patch-rework.sh
author Remy Bohmer <linux@bohmer.net>
Mon Apr 19 23:42:31 2010 +0200 (2010-04-19)
changeset 1927 aede9b9a2ffa
child 2147 0ec4491d6496
permissions -rwxr-xr-x
scripts: check g++ only for host

g++ is only needed when building additonal libs on the HOST,
so check wheter g++ is available for the HOST compiler only

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