python-pathvalidate: bump version to 0.14.1
[buildroot-gz.git] / support / scripts / apply-patches.sh
blob7ccb39dd8f7ed1a144dd2ac6bc988b0b98295a4f
1 #!/usr/bin/env bash
2 # A little script I whipped up to make it easy to
3 # patch source trees and have sane error handling
4 # -Erik
6 # (c) 2002 Erik Andersen <andersen@codepoet.org>
8 # Parameters:
9 # - "-s", optional. Silent operation, don't print anything if there
10 # isn't any error.
11 # - the build directory, optional, default value is '.'. The place where are
12 # the package sources.
13 # - the patch directory, optional, default '../kernel-patches'. The place
14 # where are the scripts you want to apply.
15 # - other parameters are the patch name patterns, optional, default value is
16 # '*'. Pattern(s) describing the patch names you want to apply.
18 # The script will look recursively for patches from the patch directory. If a
19 # file named 'series' exists then the patches mentioned in it will be applied
20 # as plain patches, regardless of their file name. If no 'series' file exists,
21 # the script will look for file names matching pattern(s). If the name
22 # ends with '.tar.*', '.tbz2' or '.tgz', the file is considered as an archive
23 # and will be uncompressed into a directory named
24 # '.patches-name_of_the_archive-unpacked'. It's the turn of this directory to
25 # be scanned with '*' as pattern. Remember that scanning is recursive. Other
26 # files than series file and archives are considered as a patch.
28 # Once a patch is found, the script will try to apply it. If its name doesn't
29 # end with '.gz', '.bz', '.bz2', '.xz', '.zip', '.Z', '.diff*' or '.patch*',
30 # it will be skipped. If necessary, the patch will be uncompressed before being
31 # applied. The list of the patches applied is stored in '.applied_patches_list'
32 # file in the build directory.
34 set -e
36 silent=
37 if [ "$1" = "-s" ] ; then
38 # add option to be used by the patch tool
39 silent=-s
40 shift
43 # Set directories from arguments, or use defaults.
44 builddir=${1-.}
45 patchdir=${2-../kernel-patches}
46 shift 2
47 patchpattern=${@-*}
49 # use a well defined sorting order
50 export LC_COLLATE=C
52 if [ ! -d "${builddir}" ] ; then
53 echo "Aborting. '${builddir}' is not a directory."
54 exit 1
56 if [ ! -d "${patchdir}" ] ; then
57 echo "Aborting. '${patchdir}' is not a directory."
58 exit 1
61 # Remove any rejects present BEFORE patching - Because if there are
62 # any, even if patches are well applied, at the end it will complain
63 # about rejects in builddir.
64 find ${builddir}/ '(' -name '*.rej' -o -name '.*.rej' ')' -print0 | \
65 xargs -0 -r rm -f
67 function apply_patch {
68 path="${1%%/}"
69 patch="${2}"
70 case "${path}" in
71 /*) ;;
72 *) path="$PWD/${path}";;
73 esac
74 if [ "$3" ]; then
75 type="series"; uncomp="cat"
76 else
77 case "$patch" in
78 *.gz)
79 type="gzip"; uncomp="gunzip -dc"; ;;
80 *.bz)
81 type="bzip"; uncomp="bunzip -dc"; ;;
82 *.bz2)
83 type="bzip2"; uncomp="bunzip2 -dc"; ;;
84 *.xz)
85 type="xz"; uncomp="unxz -dc"; ;;
86 *.zip)
87 type="zip"; uncomp="unzip -d"; ;;
88 *.Z)
89 type="compress"; uncomp="uncompress -c"; ;;
90 *.diff*)
91 type="diff"; uncomp="cat"; ;;
92 *.patch*)
93 type="patch"; uncomp="cat"; ;;
95 echo "Unsupported file type for ${path}/${patch}, skipping";
96 return 0
98 esac
100 if [ -z "$silent" ] ; then
101 echo ""
102 echo "Applying $patch using ${type}: "
104 if [ ! -e "${path}/$patch" ] ; then
105 echo "Error: missing patch file ${path}/$patch"
106 exit 1
108 existing="$(grep -E "/${patch}\$" ${builddir}/.applied_patches_list || true)"
109 if [ -n "${existing}" ]; then
110 echo "Error: duplicate filename '${patch}'"
111 echo "Conflicting files are:"
112 echo " already applied: ${existing}"
113 echo " to be applied : ${path}/${patch}"
114 exit 1
116 echo "${path}/${patch}" >> ${builddir}/.applied_patches_list
117 ${uncomp} "${path}/$patch" | patch -g0 -p1 -E -d "${builddir}" -t -N $silent
118 if [ $? != 0 ] ; then
119 echo "Patch failed! Please fix ${patch}!"
120 exit 1
124 function scan_patchdir {
125 local path=$1
126 shift 1
127 patches=${@-*}
129 # If there is a series file, use it instead of using ls sort order
130 # to apply patches. Skip line starting with a dash.
131 if [ -e "${path}/series" ] ; then
132 # The format of a series file accepts a second field that is
133 # used to specify the number of directory components to strip
134 # when applying the patch, in the form -pN (N an integer >= 0)
135 # We assume this field to always be -p1 whether it is present
136 # or missing.
137 series_patches="`grep -Ev "^#" ${path}/series | cut -d ' ' -f1 2> /dev/null`"
138 for i in $series_patches; do
139 apply_patch "$path" "$i" series
140 done
141 else
142 for i in `cd $path; ls -d $patches 2> /dev/null` ; do
143 if [ -d "${path}/$i" ] ; then
144 scan_patchdir "${path}/$i"
145 elif echo "$i" | grep -q -E "\.tar(\..*)?$|\.tbz2?$|\.tgz$" ; then
146 unpackedarchivedir="$builddir/.patches-$(basename $i)-unpacked"
147 rm -rf "$unpackedarchivedir" 2> /dev/null
148 mkdir "$unpackedarchivedir"
149 tar -C "$unpackedarchivedir" -xaf "${path}/$i"
150 scan_patchdir "$unpackedarchivedir"
151 else
152 apply_patch "$path" "$i"
154 done
158 touch ${builddir}/.applied_patches_list
159 scan_patchdir "$patchdir" "$patchpattern"
161 # Check for rejects...
162 if [ "`find $builddir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ] ; then
163 echo "Aborting. Reject files found."
164 exit 1
167 # Remove backup files
168 find $builddir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \;