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 |