1#! @BASH@
2
3# This is a wrapper to GNU patch that recognizes the most common
4# options and mimics GNU patch's behavior and output, and creates the
5# quilt metadata as if quilt push was used to apply the patches.  When
6# options are used that this wrapper does not recognize, GNU patch is
7# used directly, and no quilt metadata will get created.
8
9PATCH=@PATCH@
10original_options=("$@")
11
12# GNU patch recognizes these environment variables
13if [ -n "$SIMPLE_BACKUP_SUFFIX" ]
14then
15    set -- --suffix "$SIMPLE_BACKUP_SUFFIX" "$@"
16fi
17if [ -n "$PATCH_VERSION_CONTROL" ]
18then
19    set -- --version-control "$PATCH_VERSION_CONTROL" "$@"
20elif [ -n "$VERSION_CONTROL" ]
21then
22    set -- --version-control "$VERSION_CONTROL" "$@"
23fi
24if [ -n "$POSIXLY_CORRECT" ]
25then
26    set -- --posix "$@"
27fi
28
29backup_files()
30{
31    declare dir=${QUILT_PC:-.pc}/$name
32
33    if [ "$backup_mode" = --backup-if-mismatch ]
34    then
35	awk '
36	/^patching file / \
37	    { file=$0
38	      sub(/^patching file /, "", file)
39	    }
40	/^Hunk #[0-9]* / \
41	    { if (!(file in backup)) {
42	        backup[file] = 1
43	        #print "ln -f "dir"/"file" "prefix file suffix > "/dev/stderr"
44	        system("ln -f "dir"/"file" "prefix file suffix)
45	      }
46	    }
47	    { if (!silent)
48	        print
49	    }
50	' dir="${dir//\\/\\\\}" \
51	  prefix="${opt_prefix//\\/\\\\}" \
52	  suffix="${opt_suffix//\\/\\\\}" \
53	  silent="${opt_silent:+1}"
54    elif [ -n "$opt_silent" ]; then
55	cat > /dev/null
56    fi
57    if [ "$backup_mode" = --backup -a -d "$dir" ]
58    then
59	for file in $(find "$dir" -type f -a ! -path "$path/.timestamp")
60	do
61	    dest=$opt_prefix${file#$dir/}$opt_suffix
62	    mkdir -p $(dirname "$dest")
63	    ln -f $file $dest
64	done
65    fi
66}
67
68find_pipe_patch()
69{
70    declare patch=$1
71    patch=${patch//\[/\\[}
72    patch=${patch//\]/\\]}
73    set -- $(stat -c $'%a %N\n' /proc/*/fd/* 2>/dev/null \
74	     | sed -nre "s,^300 \`(/proc/.*/fd)/.*' -> \`$patch'$,\\1,p")
75    set -- $(stat -c $'%a %N\n' $1/* 2>/dev/null \
76	     | sed -nre "s,^500 \`.*' -> \`(.*)',\\1,p")
77    [ $# -eq 1 ] || set -- "$patch"
78    echo "$1"
79}
80
81options=`getopt -q -o bsB:z:i:p:d: \
82		   --long quiet,silent,backup,backup-if-mismatch \
83		   --long no-backup-if-mismatch,prefix: \
84		   --long suffix:,posix,input:,strip:,directory: -- "$@"`
85if [ $? -ne 0 ]
86then
87    cannot_handle=1
88else
89	case "${LC_ALL:-${LC_MESSAGES:-${LANG}}}" in
90	''|C|POSIX|en*)
91		;;
92	*)	cannot_handle=1
93		;;
94	esac
95fi
96if [ -z "$cannot_handle" ]; then
97    eval set -- "$options"
98
99    backup_mode=--backup-if-mismatch
100    opt_prefix=
101    opt_suffix=
102    opt_silent=
103    opt_input=
104    opt_strip=
105    opt_directory=$PWD
106
107    while :
108    do
109	case "$1" in
110	-b|--backup)
111	    backup_mode=--backup
112	    ;;
113	--backup-if-mismatch)
114	    backup_mode=--backup-if-mismatch
115	    ;;
116	-d|--directory)
117	    cd "$2" || exit 1
118	    shift
119	    ;;
120	-i|--input)
121	    opt_input=$2
122	    new_options[${#new_options[@]}]=$1
123	    new_options[${#new_options[@]}]=$2
124	    shift
125	    ;;
126	--no-backup-if-mismatch)
127	    backup_mode=--no-backup-if-mismatch
128	    ;;
129	-B|--prefix)
130	    opt_prefix=$2
131	    new_options[${#new_options[@]}]=$1
132	    new_options[${#new_options[@]}]=$2
133	    shift
134	    ;;
135	-s|--silent|--quiet)
136	    opt_silent=--silent
137	    ;;
138	-p|--strip)
139	    opt_strip=-p$2
140	    new_options[${#new_options[@]}]=-p$2
141	    shift
142	    ;;
143	-z|--suffix)
144	    opt_suffix=$2
145	    new_options[${#new_options[@]}]=$1
146	    new_options[${#new_options[@]}]=$2
147	    shift
148	    ;;
149	--posix)
150	    backup_mode=--no-backup-if-mismatch
151	    new_options[${#new_options[@]}]=$1
152	    ;;
153	--)
154	    shift
155	    break
156	    ;;
157	*)
158	    new_options[${#new_options[@]}]=$1
159	    ;;
160	esac
161	shift
162    done
163
164    [ -n "$opt_prefix$opt_suffix" ] || opt_suffix=.orig
165    if [ -z "$opt_strip" -o $# -ne 0 ]
166    then
167	cannot_handle=1
168    fi
169fi
170
171if [ -z "$cannot_handle" ]
172then
173    if [ -n "$opt_input" ]
174    then
175	patch=$opt_input
176    elif [ ! -e /proc/self ]
177    then
178	echo "patch-wrapper: /proc not mounted!" >&2
179	exit 1
180    elif [ -e /proc/self/fd/0 ]
181    then
182	patch=$(readlink /proc/self/fd/0)
183	case "$patch" in
184	pipe:*)
185		patch=$(find_pipe_patch "$patch")
186		;;
187	esac
188    fi
189    patch=${patch#$PWD/}
190
191    if [ ! -e "$patch" ]
192    then
193	cannot_handle=1
194    fi
195fi
196
197if [ -n "$cannot_handle" ]
198then
199    $PATCH "${original_options[@]}"
200    exit
201fi
202
203quilt_patches=${QUILT_PATCHES:-patches}
204
205if [ "${patch#$RPM_SOURCE_DIR}" != "$patch" ]
206then
207    name=SOURCES/${patch#$RPM_SOURCE_DIR/}
208    if [ ! -e "$quilt_patches/SOURCES" ]
209    then
210	mkdir -p "$quilt_patches"
211	ln -s $RPM_SOURCE_DIR "$quilt_patches/SOURCES"
212    fi
213elif [ "${patch#$RPM_BUILD_DIR}" != "$patch" ]
214then
215    name=BUILD/${patch#$RPM_BUILD_DIR/}
216    if [ ! -e "$quilt_patches/BUILD" ]
217    then
218	mkdir -p "$quilt_patches"
219	ln -s $RPM_BUILD_DIR "$quilt_patches/BUILD"
220    fi
221else
222    name=${patch#/}
223    dir=$(dirname "$quilt_patches/$name")
224    mkdir -p "$dir"
225
226    if [ "${patch:0:1}" = / ]
227    then
228	ln -s "$patch" "$quilt_patches/${name#/}"
229    else
230	while ! [ "$dir/$updir$name" -ef "$patch" ]
231	do
232	    updir=$updir../
233	    [ ${#updir} -gt 96 ] && break
234	done
235	if [ "$dir/$updir$name" -ef "$patch" ]
236	then
237	    ln -s "$updir$patch" "$quilt_patches/$name"
238	fi
239    fi
240fi
241
242if [ "$opt_strip" = -p1 ]; then
243    echo "$name"
244else
245    echo "$name $opt_strip"
246fi >> $quilt_patches/series
247
248$PATCH "${new_options[@]}" --backup --prefix "${QUILT_PC:-.pc}/$name/" \
249    | backup_files
250status=${PIPESTATUS[0]}
251if [ $status -eq 0 ]
252then
253    dir=${QUILT_PC:-.pc}/$name
254    if [ ! -e "$dir" ]
255    then
256	mkdir -p "$dir"
257    fi
258    echo -n "" > $dir/.timestamp
259    if [ ! -e ${QUILT_PC:-.pc}/.version ]
260    then
261	echo 2 > ${QUILT_PC:-.pc}/.version
262    fi
263    echo "$name" >> "${QUILT_PC:-.pc}/applied-patches"
264fi
265exit $status
266