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