tazpkg view modules/remove @ rev 860

remove: using "rmdir -p" instead of loop (thanks Lucas Levrel)
author Aleksej Bobylev <al.bobylev@gmail.com>
date Sat Nov 14 14:41:30 2015 +0200 (2015-11-14)
parents d62dc010e0ee
children 1362693564d1
line source
1 #!/bin/sh
2 # TazPkg - Tiny autonomous zone packages manager, hg.slitaz.org/tazpkg
3 # remove - TazPkg module
4 # Remove packages
7 # Connect function libraries
8 . /lib/libtaz.sh
10 # Get TazPkg working environment
11 . @@MODULES@@/getenv
16 # Log activity
18 log_pkg() {
19 [ -w "$LOG" ] &&
20 echo "$(date +'%F %T') - $1 - $PACKAGE ($VERSION$EXTRAVERSION)" >> "$LOG"
21 }
24 # Interactive mode
26 im() { tty -s; }
29 # Block of receipt function callers
30 # Why? "Bad" receipt sourcing can redefine some vital TazPkg variables.
31 # Few receipts function should be patched now.
33 # Input: $1 = path to the receipt to be processed
35 call_pre_remove() {
36 local tmp
37 if grep -q '^pre_remove()' "$1"; then
38 action 'Execute pre-remove commands...'
39 tmp="$(mktemp)"
40 cp "$1" "$tmp"
41 sed -i 's|$1/*$INSTALLED|$INSTALLED|g' "$tmp"
42 ( . "$tmp"; pre_remove "$root" )
43 status
44 rm "$tmp"
45 fi
46 }
48 call_post_remove() {
49 local tmp
50 if grep -q '^post_remove()' "$1"; then
51 action 'Execute post-remove commands...'
52 tmp="$(mktemp)"
53 cp "$1" "$tmp"
54 sed -i 's|$1/*$INSTALLED|$INSTALLED|g' "$tmp"
55 ( . "$tmp"; post_remove "$root" )
56 status
57 rm "$tmp"
58 fi
59 }
64 PACKAGE="$1"
66 if [ ! -f "$INSTALLED/$PACKAGE/receipt" ]; then
67 newline; _ 'Package "%s" is not installed.' "$PACKAGE"
68 exit 1
69 fi
71 . "$INSTALLED/$PACKAGE/receipt"
73 # Info #1: dependent packages (to be processed later)
74 ALTERED="$(awk -F$'\t' -vp=" $PACKAGE " 'index(" " $8 " ", p) { printf " %s\n", $1 }' "$PKGS_DB/installed.info")"
76 if [ -n "$ALTERED" ]; then
77 _ 'The following packages depend on package "%s":' "$PACKAGE"
78 echo "$ALTERED"
79 fi
81 # Info #2: changed packages (to be processed later)
82 REFRESH=$(cd "$INSTALLED"; grep -sl "^$PACKAGE$" */modifiers)
84 if [ -n "$REFRESH" ]; then
85 _ 'The following packages have been modified by package "%s":' "$PACKAGE"
86 for i in $REFRESH; do
87 echo " ${i%/modifiers}"
88 done
89 fi
91 # Confirmation
92 if im && [ -z "$auto" ]; then
93 confirm "$(_ 'Remove package "%s" (%s)? (y/N)' "$PACKAGE" "$VERSION$EXTRAVERSION")"
94 if [ "$?" -ne 0 ]; then
95 newline; _ 'Uninstallation of package "%s" cancelled.' "$PACKAGE"
96 exit 0
97 fi
98 fi
99 # We are here: non-interactive mode, or --auto, or answer 'y'
101 # Removing package
102 title 'Removing package "%s"' "$PACKAGE"
104 # [1/4] Pre-remove commands
105 call_pre_remove "$INSTALLED/$PACKAGE/receipt"
108 # [2/4] Removing files
109 action 'Removing all files installed...'
111 # NOTE: package 'faenza-icon-theme' install time: 12s; removing time ~ 11min on my system o_O
112 # After optimization: 3s! (Long) for-loops are (big) evil ;)
114 # NOTE: many packages contains filenames with spaces:
115 # lzcat /var/lib/tazpkg/files.list.lzma | awk -F" " '{if(NF>2)print $1}' | sed 's|:$||' | uniq
116 # Redefine IFS to only-new-line field separator:
117 IFS=$'\n'
119 files2remove="$(mktemp)"
121 debug '\nDetermine which files to remove...'
122 if [ -f "$INSTALLED/$PACKAGE/modifiers" ]; then
123 debug ' (modifiers detected)'
125 mods="$(mktemp)"
126 for mod in $(cat "$INSTALLED/$PACKAGE/modifiers"); do
127 cat "$INSTALLED/$mod/files.list" >> "$mods" 2>/dev/null
128 done
130 awk -vroot="$root" -vfl="$INSTALLED/$PACKAGE/files.list" '
131 {
132 if (FILENAME == fl)
133 f[$0] = 1;
134 else
135 f[$0] = "";
136 }
137 END {
138 for (i in f) {
139 if (f[i] == 1) printf "%s%s\n", root, i;
140 }
141 }' "$INSTALLED/$PACKAGE/files.list" "$mods" > "$files2remove"
142 rm "$mods"
143 else
144 debug ' (modifiers not detected)'
146 awk -vroot="$root" '{ printf "%s%s\n", root, $0; }' \
147 "$INSTALLED/$PACKAGE/files.list" > "$files2remove"
148 fi
150 debug 'Removing files...'
151 xargs rm -f < "$files2remove"
153 debug 'Removing folders...'
154 awk '
155 BEGIN {
156 FS = "/"; OFS = "/";
157 }
158 {
159 # removing filename beyond the last "/"
160 $NF = "";
161 if (! a[$0]) {
162 a[$0] = 1; print;
163 }
164 }' "$files2remove" | xargs rmdir -p 2>/dev/null
166 rm "$files2remove"
167 unset IFS
169 status
171 # [3/4] Post-remove commands
172 call_post_remove "$INSTALLED/$PACKAGE/receipt"
174 # [4/4] Remove package receipt and remove it from databases
175 action 'Removing package receipt...'
176 rm -rf "$INSTALLED/$PACKAGE"
177 sed -i "/ $PACKAGE-$VERSION$EXTRAVERSION.tazpkg$/d" "$PKGS_DB/installed.$SUM"
178 sed -i "/^$PACKAGE /d" "$PKGS_DB/installed.info"
179 status
181 footer "$(_ 'Package "%s" (%s) removed.' "$PACKAGE" "$VERSION$EXTRAVERSION")"
183 # Log this activity
184 log_pkg Removed
186 # Stop if non-interactive mode and no --auto option
187 if ! im && [ -z "$auto" ]; then exit 0; fi
189 # Process dependent packages
190 if [ -n "$ALTERED" ]; then
191 if [ -n "$auto" ]; then
192 answer=0
193 else
194 confirm "$(_ 'Remove packages depending on package "%s"? (y/N)' "$PACKAGE")"
195 answer=$?
196 fi
197 if [ "$answer" -eq 0 ]; then
198 for i in $ALTERED; do
199 if [ -d "$INSTALLED/$i" ]; then
200 tazpkg remove $i
201 fi
202 done
203 fi
204 fi
206 # Process changed packages
207 if [ -n "$REFRESH" ]; then
208 if [ -n "$auto" ]; then
209 answer=0
210 else
211 confirm "$(_ 'Reinstall packages modified by package "%s"? (y/N)' "$PACKAGE")"
212 answer=$?
213 fi
214 if [ "$answer" -eq 0 ]; then
215 for i in $REFRESH; do
216 if [ "$(wc -l < "$INSTALLED/$i")" -gt 1 ]; then
217 _ 'Package "%s" was modified by "%s" and other packages. It will not be reinstalled.' \
218 "${i%/modifiers}" "$PACKAGE"
219 _ 'Check "%s" for reinstallation.' "$INSTALLED/$i"
221 continue
222 fi
223 rm -r "$INSTALLED/$i"
224 tazpkg get-install ${i%/modifiers} --forced
225 done
226 fi
227 fi