scripts/patch-rework.sh
author Daniel Price <daniel.price@gmail.com>
Tue Nov 20 16:59:17 2012 -0800 (2012-11-20)
changeset 3126 333d3e40cbd1
parent 2224 fc58927f24b8
permissions -rwxr-xr-x
scripts: refine static linking check to better guide the user

The current mechanism to check if static linking is possible, and the mesage
displayed on failure, can be puzzling to the unsuspecting user.

Also, the current implementation is not using the existing infrastructure,
and is thus difficult to enhance with new tests.

So, switch to using the standard CT_DoExecLog infra, and use four tests to
check for the host compiler:
- check we can run it
- check it can build a trivial program
- check it can statically link that program
- check if it statically link with libstdc++

That should cover most of the problems. Hopefully.

(At the same time, fix a typo in a comment)

Signed-off-by: Daniel Price <daniel.price@gmail.com>
[yann.morin.1998@free.fr: split original patch for self-contained changes]
[yann.morin.1998@free.fr: use steps to better see gcc's output]
[yann.morin.1998@free.fr: commit log]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Message-Id: <163f86b5216fc08c672a.1353459722@nipigon.dssd.com>
Patchwork-Id: 200536
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"