Commit | Line | Data |
---|---|---|
9ac667e6 SR |
1 | #!/bin/bash |
2 | # | |
3 | # rejmerge (pkgutils) | |
4 | # | |
5 | # Copyright (c) 2000-2005 Per Liden | |
6 | # | |
7 | # This program is free software; you can redistribute it and/or modify | |
8 | # it under the terms of the GNU General Public License as published by | |
9 | # the Free Software Foundation; either version 2 of the License, or | |
10 | # (at your option) any later version. | |
11 | # | |
12 | # This program is distributed in the hope that it will be useful, | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | # GNU General Public License for more details. | |
16 | # | |
17 | # You should have received a copy of the GNU General Public License | |
18 | # along with this program; if not, write to the Free Software | |
19 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
20 | # USA. | |
21 | # | |
22 | ||
23 | info_n() { | |
24 | echo -n "=======> $1" | |
25 | } | |
26 | ||
27 | info() { | |
28 | info_n "$1" | |
29 | echo | |
30 | } | |
31 | ||
32 | interrupted() { | |
33 | echo "" | |
34 | info "Aborted." | |
35 | exit 1 | |
36 | } | |
37 | ||
38 | atexit() { | |
39 | if [ -e "$TMPFILE" ]; then | |
40 | rm -f "$TMPFILE" | |
41 | fi | |
42 | } | |
43 | ||
44 | rejmerge_diff() { | |
45 | diff -u "$1" "$2" > "$3" | |
46 | } | |
47 | ||
48 | rejmerge_merge() { | |
49 | diff --old-group-format="%<" \ | |
50 | --new-group-format="%>" \ | |
51 | --changed-group-format="<<<<< MERGE CONFLICT $1 >>>>> | |
52 | %<<<<<< MERGE CONFLICT $2 >>>>> | |
53 | %><<<<< END MERGE CONFLICT >>>>> | |
54 | " \ | |
55 | "$1" "$2" > "$3" | |
56 | ||
57 | REJMERGE_MERGE_INFO="$(grep -c '^<<<<< END MERGE CONFLICT >>>>>$' "$3") merge conflict(s)." | |
58 | } | |
59 | ||
60 | permissions_menu() { | |
61 | while true; do | |
62 | info "Access permissions $1" | |
63 | stat -c '%A %U %G %n' "$1" | |
64 | stat -c '%A %U %G %n' "$2" | |
65 | while true; do | |
66 | info_n "[K]eep [U]pgrade [D]iff [S]kip? " | |
67 | read -n1 CMD | |
68 | echo | |
69 | ||
70 | case "$CMD" in | |
71 | k|K) chown --reference="$1" "$2" | |
72 | chmod --reference="$1" "$2" | |
73 | break 2 | |
74 | ;; | |
75 | u|U) chown --reference="$2" "$1" | |
76 | chmod --reference="$2" "$1" | |
77 | break 2 | |
78 | ;; | |
79 | d|D) break 1 | |
80 | ;; | |
81 | s|S) break 2 | |
82 | ;; | |
83 | esac | |
84 | done | |
85 | done | |
86 | } | |
87 | ||
88 | merge_menu() { | |
89 | rejmerge_merge "$1" "$2" "$TMPFILE" | |
90 | ||
91 | while true; do | |
92 | info "Merged $1" | |
93 | cat "$TMPFILE" | more | |
94 | ||
95 | if [ "$REJMERGE_MERGE_INFO" ]; then | |
96 | info "$REJMERGE_MERGE_INFO" | |
97 | unset REJMERGE_MERGE_INFO | |
98 | fi | |
99 | ||
100 | while true; do | |
101 | info_n "[I]nstall [E]dit [V]iew [S]kip? " | |
102 | read -n1 CMD | |
103 | echo | |
104 | ||
105 | case "$CMD" in | |
106 | i|I) chmod --reference="$1" "$TMPFILE" | |
107 | mv -f "$TMPFILE" "$1" | |
108 | rm -f "$2" | |
109 | break 2 | |
110 | ;; | |
111 | e|E) $EDITOR "$TMPFILE" | |
112 | break 1 | |
113 | ;; | |
114 | v|V) break 1 | |
115 | ;; | |
116 | s|S) break 2 | |
117 | ;; | |
118 | esac | |
119 | done | |
120 | done | |
121 | ||
122 | : > "$TMPFILE" | |
123 | } | |
124 | ||
125 | diff_menu() { | |
126 | rejmerge_diff "$1" "$2" "$TMPFILE" | |
127 | ||
128 | while true; do | |
129 | info "$1" | |
130 | cat "$TMPFILE" | more | |
131 | while true; do | |
132 | info_n "[K]eep [U]pgrade [M]erge [D]iff [S]kip? " | |
133 | read -n1 CMD | |
134 | echo | |
135 | ||
136 | case "$CMD" in | |
137 | k|K) rm -f "$2" | |
138 | break 2 | |
139 | ;; | |
140 | u|U) mv -f "$2" "$1" | |
141 | break 2 | |
142 | ;; | |
143 | m|M) merge_menu "$1" "$2" | |
144 | break 2 | |
145 | ;; | |
146 | d|D) break 1 | |
147 | ;; | |
148 | s|S) break 2 | |
149 | ;; | |
150 | esac | |
151 | done | |
152 | done | |
153 | ||
154 | : > "$TMPFILE" | |
155 | } | |
156 | ||
157 | file_menu() { | |
158 | while true; do | |
159 | info "$1" | |
160 | file "$1" "$2" | |
161 | while true; do | |
162 | info_n "[K]eep [U]pgrade [D]iff [S]kip? " | |
163 | read -n1 CMD | |
164 | echo | |
165 | ||
166 | case "$CMD" in | |
167 | k|K) rm -f "$2" | |
168 | break 2 | |
169 | ;; | |
170 | u|U) mv -f "$2" "$1" | |
171 | break 2 | |
172 | ;; | |
173 | d|D) break 1 | |
174 | ;; | |
175 | s|S) break 2 | |
176 | ;; | |
177 | esac | |
178 | done | |
179 | done | |
180 | } | |
181 | ||
182 | print_help() { | |
183 | echo "usage: $REJMERGE_COMMAND [options]" | |
184 | echo "options:" | |
185 | echo " -r, --root <path> specify alternative root" | |
186 | echo " -v, --version print version and exit " | |
187 | echo " -h, --help print help and exit" | |
188 | } | |
189 | ||
190 | parse_options() { | |
191 | while [ "$1" ]; do | |
192 | case $1 in | |
193 | -r|--root) | |
194 | if [ ! "$2" ]; then | |
195 | echo "$REJMERGE_COMMAND: option $1 requires an argument" | |
196 | exit 1 | |
197 | fi | |
198 | REJMERGE_ROOT="$2" | |
199 | REJMERGE_CONF="$2$REJMERGE_CONF" | |
200 | REJECTED_DIR="$2$REJECTED_DIR" | |
201 | shift ;; | |
202 | -v|--version) | |
203 | echo "$REJMERGE_COMMAND (pkgutils) $REJMERGE_VERSION" | |
204 | exit 0 ;; | |
205 | -h|--help) | |
206 | print_help | |
207 | exit 0 ;; | |
208 | *) | |
209 | echo "$REJMERGE_COMMAND: invalid option $1" | |
210 | exit 1 ;; | |
211 | esac | |
212 | shift | |
213 | done | |
214 | ||
215 | if [ ! -d "$REJECTED_DIR" ]; then | |
216 | echo "$REJMERGE_COMMAND: $REJECTED_DIR not found" | |
217 | exit 1 | |
218 | fi | |
219 | } | |
220 | ||
221 | files_regular() { | |
222 | local STAT_FILE1=$(stat -c '%F' "$1") | |
223 | local STAT_FILE2=$(stat -c '%F' "$2") | |
224 | ||
225 | if [ "$STAT_FILE1" != "regular file" ]; then | |
226 | return 1 | |
227 | fi | |
228 | ||
229 | if [ "$STAT_FILE2" != "regular file" ]; then | |
230 | return 1 | |
231 | fi | |
232 | ||
233 | return 0 | |
234 | } | |
235 | ||
236 | main() { | |
237 | parse_options "$@" | |
238 | ||
239 | if [ "$UID" != "0" ]; then | |
240 | echo "$REJMERGE_COMMAND: only root can merge rejected files" | |
241 | exit 1 | |
242 | fi | |
243 | ||
244 | # Read configuration | |
245 | if [ -f "$REJMERGE_CONF" ]; then | |
246 | . "$REJMERGE_CONF" | |
247 | fi | |
248 | ||
249 | REJECTED_FILES_FOUND="no" | |
250 | ||
251 | # Check files | |
252 | for REJECTED_FILE in $(find $REJECTED_DIR ! -type d); do | |
253 | INSTALLED_FILE="$REJMERGE_ROOT${REJECTED_FILE##$REJECTED_DIR}" | |
254 | ||
255 | # Remove rejected file if there is no installed version | |
256 | if [ ! -e "$INSTALLED_FILE" ]; then | |
257 | rm -f "$REJECTED_FILE" | |
258 | continue | |
259 | fi | |
260 | ||
261 | # Check permissions | |
262 | local STAT_FILE1=$(stat -c '%A %U %G' "$INSTALLED_FILE") | |
263 | local STAT_FILE2=$(stat -c '%A %U %G' "$REJECTED_FILE") | |
264 | ||
265 | if [ "$STAT_FILE1" != "$STAT_FILE2" ]; then | |
266 | REJECTED_FILES_FOUND="yes" | |
267 | permissions_menu "$INSTALLED_FILE" "$REJECTED_FILE" | |
268 | fi | |
269 | ||
270 | # Check file types | |
271 | if files_regular "$INSTALLED_FILE" "$REJECTED_FILE"; then | |
272 | # Both files are regular | |
273 | if cmp -s "$INSTALLED_FILE" "$REJECTED_FILE"; then | |
274 | rm -f "$REJECTED_FILE" | |
275 | else | |
276 | REJECTED_FILES_FOUND="yes" | |
277 | diff_menu "$INSTALLED_FILE" "$REJECTED_FILE" | |
278 | fi | |
279 | else | |
280 | # At least one file is non-regular | |
281 | REJECTED_FILES_FOUND="yes" | |
282 | file_menu "$INSTALLED_FILE" "$REJECTED_FILE" | |
283 | fi | |
284 | done | |
285 | ||
286 | # Remove empty directories | |
287 | for DIR in $(find $REJECTED_DIR -depth -type d); do | |
288 | if [ "$DIR" != "$REJECTED_DIR" ]; then | |
289 | rmdir "$DIR" &> /dev/null | |
290 | fi | |
291 | done | |
292 | ||
293 | if [ "$REJECTED_FILES_FOUND" = "no" ]; then | |
294 | echo "Nothing to merge" | |
295 | fi | |
296 | ||
297 | exit 0 | |
298 | } | |
299 | ||
300 | trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM | |
301 | trap "atexit" EXIT | |
302 | ||
303 | export LC_ALL=POSIX | |
304 | ||
305 | readonly REJMERGE_VERSION="#VERSION#" | |
306 | readonly REJMERGE_COMMAND="${0##*/}" | |
307 | REJMERGE_ROOT="" | |
308 | REJMERGE_CONF="/etc/rejmerge.conf" | |
309 | REJECTED_DIR="/var/lib/pkg/rejected" | |
310 | EDITOR=${EDITOR:-vi} | |
311 | TMPFILE=$(mktemp) || exit 1 | |
312 | ||
313 | main "$@" | |
314 | ||
315 | # End of file |