tazpkg view modules/remove @ rev 857

remove: speed up to a hundred times
author Aleksej Bobylev <al.bobylev@gmail.com>
date Thu Nov 12 20:13:00 2015 +0200 (2015-11-12)
parents b6daeaa95431
children b278bf56267b
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: 6s! (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)"
120 dirs2remove="$(mktemp)"
122 debug '\nDetermine which files to remove...'
123 if [ -f "$INSTALLED/$PACKAGE/modifiers" ]; then
124 debug ' (modifiers detected)'
126 mods="$(mktemp)"
127 for mod in $(cat "$INSTALLED/$PACKAGE/modifiers"); do
128 cat "$INSTALLED/$mod/files.list" >> "$mods" 2>/dev/null
129 done
131 awk -vroot="$root" -vfl="$INSTALLED/$PACKAGE/files.list" '
132 {
133 if (FILENAME == fl)
134 f[$0] = 1;
135 else
136 f[$0] = "";
137 }
138 END {
139 for (i in f) {
140 if (f[i] == 1) printf "%s%s\n", root, i;
141 }
142 }' "$INSTALLED/$PACKAGE/files.list" "$mods" > "$files2remove"
143 rm "$mods"
144 else
145 debug ' (modifiers not detected)'
147 awk -vroot="$root" '{ printf "%s%s\n", root, $0; }' \
148 "$INSTALLED/$PACKAGE/files.list" > "$files2remove"
149 fi
151 debug 'Removing files...'
152 xargs rm -f < "$files2remove"
154 debug 'Determine which folders to remove...'
155 awk '
156 BEGIN {
157 FS = "/"; OFS = "/";
158 }
159 {
160 # removing filename beyond the last "/"
161 $NF = "";
162 if (! a[$0]) {
163 a[$0] = 1; print;
164 }
165 }' "$files2remove" | sed 's|/$||' > "$dirs2remove"
167 debug 'Removing folders...'
168 for dir2r in $(cat "$dirs2remove"); do
169 dir="$dir2r"
170 while [ -n "$dir" ]; do
171 rmdir "$dir" 2>/dev/null || break
172 dir="${dir%/*}"
173 done
174 done
175 rm "$files2remove" "$dirs2remove"
176 unset IFS
178 status
180 # [3/4] Post-remove commands
181 call_post_remove "$INSTALLED/$PACKAGE/receipt"
183 # [4/4] Remove package receipt and remove it from databases
184 action 'Removing package receipt...'
185 rm -rf "$INSTALLED/$PACKAGE"
186 sed -i "/ $PACKAGE-$VERSION$EXTRAVERSION.tazpkg$/d" "$PKGS_DB/installed.$SUM"
187 sed -i "/^$PACKAGE /d" "$PKGS_DB/installed.info"
188 status
190 footer "$(_ 'Package "%s" (%s) removed.' "$PACKAGE" "$VERSION$EXTRAVERSION")"
192 # Log this activity
193 log_pkg Removed
195 # Stop if non-interactive mode and no --auto option
196 if ! im && [ -z "$auto" ]; then exit 0; fi
198 # Process dependent packages
199 if [ -n "$ALTERED" ]; then
200 if [ -n "$auto" ]; then
201 answer=0
202 else
203 confirm "$(_ 'Remove packages depending on package "%s"? (y/N)' "$PACKAGE")"
204 answer=$?
205 fi
206 if [ "$answer" -eq 0 ]; then
207 for i in $ALTERED; do
208 if [ -d "$INSTALLED/$i" ]; then
209 tazpkg remove $i
210 fi
211 done
212 fi
213 fi
215 # Process changed packages
216 if [ -n "$REFRESH" ]; then
217 if [ -n "$auto" ]; then
218 answer=0
219 else
220 confirm "$(_ 'Reinstall packages modified by package "%s"? (y/N)' "$PACKAGE")"
221 answer=$?
222 fi
223 if [ "$answer" -eq 0 ]; then
224 for i in $REFRESH; do
225 if [ "$(wc -l < "$INSTALLED/$i")" -gt 1 ]; then
226 _ 'Package "%s" was modified by "%s" and other packages. It will not be reinstalled.' \
227 "${i%/modifiers}" "$PACKAGE"
228 _ 'Check "%s" for reinstallation.' "$INSTALLED/$i"
230 continue
231 fi
232 rm -r "$INSTALLED/$i"
233 tazpkg get-install ${i%/modifiers} --forced
234 done
235 fi
236 fi