tazpkg view modules/install @ rev 846

Remove "busybox" "prefixes" (thanks llev)
We used "busybox wget", etc. to be sure we called Busybox's "wget", not any other "wget". Workaround already done in "getenv" module.
author Aleksej Bobylev <al.bobylev@gmail.com>
date Fri Oct 09 13:14:01 2015 +0300 (2015-10-09)
parents ce7009ff237b
children 21ac83abe572
line source
1 #!/bin/sh
2 # TazPkg - Tiny autonomous zone packages manager, hg.slitaz.org/tazpkg
3 # install - TazPkg module
4 # Install packages
7 # Connect function libraries
8 . /lib/libtaz.sh
9 . /usr/lib/slitaz/libpkg.sh
12 # Get TazPkg working environment
13 . @@MODULES@@/getenv
14 # $CACHE_DIR will change, it based on unchanged value of $SAVE_CACHE_DIR
15 SAVE_CACHE_DIR="$CACHE_DIR"
18 . @@MODULES@@/find-depends
23 # Log TazPkg activity
25 log_pkg() {
26 debug "\nlog_pkg('$1')\n PACKAGE='$PACKAGE'\n VERSION='$VERSION'\n EXTRAVERSION='$EXTRAVERSION'"
28 local extra
30 [ "$1" == 'Installed' ] && \
31 extra=" - $(fgrep " $PACKAGE-$VERSION" "$PKGS_DB/installed.$SUM" | awk '{print $1}')"
32 debug " extra='$extra'"
34 [ -w "$LOG" ] &&
35 echo "$(date +'%F %T') - $1 - $PACKAGE ($VERSION$EXTRAVERSION)$extra" >> $LOG
36 }
39 # get an already installed package from packages.equiv
41 equivalent_pkg() {
42 # input: $1 = package name (like "nano")
43 local i rep rules rule out
45 rules=$(for rep in $PRIORITY; do
46 grep -hs "^$1=" "$rep/packages.equiv"
47 done | sed "s|^$1=||")
48 debug " >rules='$rules'"
50 for rule in $rules; do
51 debug " >rule='$rule'"
52 case $rule in
53 *:*)
54 debug '-- x:x'
55 # format 'alternative:newname'
56 # if alternative is installed then substitute newname
57 out="${rule#*:}"
58 awk -F$'\t' -vp="${rule%:*}" '$1==p{exit 1}' "$PKGS_DB/installed.info" || break
59 debug '-- x:x /'
60 ;;
61 *)
62 debug '-- x'
63 # unconditional substitution
64 out="$rule"
65 awk -F$'\t' -vp="$rule" '$1==p{exit 1}' "$PKGS_DB/installed.info" || break
66 debug '-- x /'
67 ;;
68 esac
69 unset out
70 done
71 debug '--'
72 # if not found in packages.equiv then no substitution
73 echo "${out:-$1}"
74 }
77 # Check and install all missing deps.
78 # Auto install or ask user then install all missing deps from local dir, CD-ROM,
79 # media or from the mirror.
81 install_all_deps() {
82 # input: $1 = package file to check/install missing dependencies
83 # ROOT READY
84 # dep: equivalent_pkg.
86 debug "\ninstall_all_deps('$1')"
88 local TMP_DIR DEPENDS num missing_packages equiv pkg answer dir found pkgfile
90 # Check for missing deps listed in a receipt packages.
92 # Get the receipt's variable DEPENDS
93 DEPENDS=$(
94 TMP_DIR=$(mktemp -d); cd "$TMP_DIR"
95 cpio --quiet -i receipt >/dev/null 2>&1
96 . receipt; echo $DEPENDS
97 rm -rf "$TMP_DIR"
98 ) < "$1"
100 unset num missing_packages
101 for depend in $DEPENDS; do
102 debug " depend='$depend'"
103 equiv=$(equivalent_pkg $depend)
104 debug " equiv='$equiv'\n"
105 if [ ! -d "$INSTALLED/$equiv" ]; then
106 missing_packages="$missing_packages $equiv"
107 num=$((num+1))
108 elif [ ! -f "$INSTALLED/$equiv/receipt" ]; then
109 _ 'WARNING! Dependency loop between "%s" and "%s".' "$PACKAGE" "$equiv"
110 fi
111 done
113 # Nothing to install, exit function
114 [ -z "$num" ] && return
117 title "$(_ 'Tracking dependencies for package "%s"' "$PACKAGE")"
119 # Individual messages for each missing package
120 for pkg in $missing_packages; do
121 _ 'Missing package "%s"' "$pkg"
122 done
124 footer "$(_p \
125 '%s missing package to install.' \
126 '%s missing packages to install.' "$num" \
127 "$num")"
130 if [ "$AUTO_INSTALL_DEPS" == 'yes' ]; then
131 answer=0
132 else
133 newline
134 confirm "$(_ 'Install all missing dependencies? (y/N)')"
135 answer=$?
136 newline
137 fi
138 debug " answer='$answer'"
140 dir="$(dirname "$1")"
141 debug " dir='$dir'"
143 # We can install packages from /home/boot/packages at a boot time
144 # Also we can prefer local packages over mirrored/cached using '--local' option
145 [ "$dir" == '/home/boot/packages' ] && local='yes'
146 debug " local='$local'"
147 [ -n "$local" ] && tazpkg mkdb "$dir" --forced >/dev/null
150 # "--nodeps" option prevents to install dependencies
151 if [ "$answer" -eq 0 -a -z "$nodeps" ]; then
152 debug " let's install missing packages"
153 for pkg in $missing_packages; do
154 debug " pkg='$pkg'"
155 if [ ! -d "$INSTALLED/$pkg" ]; then
156 # Package not installed
158 found='0'
159 # Prefer local packages
160 if [ -n "$local" ]; then
161 _ 'Checking if package "%s" exists in local list...' "$pkg"
162 pkgfile=$(awk -F$'\t' -vp="$pkg" '
163 $1==p{printf "%s-%s.tazpkg", $1, $2; exit 1}
164 ' "$dir/packages.info")
165 if [ -n "$pkgfile" ]; then
166 found='1'
167 tazpkg install "$dir/$pkgfile"
168 fi
169 fi
170 debug " found='$found'"
172 # Install package from the mirror
173 [ "$found" -eq 0 ] && tazpkg get-install "$pkg"
174 fi
175 done
176 else
177 # Answered 'No' to install dependencies, or '--nodeps' option given
178 newline
179 _ 'Leaving dependencies for package "%s" unresolved.' "$PACKAGE"
180 _ 'The package will be installed but will probably not work.'
181 newline
182 fi
183 }
186 # Extract a package with cpio and gzip/lzma.
188 extract_package() {
189 # input: $1 - path to package to be extracted; package should be in the current dir
190 # ROOT INDEPENDENT
191 action 'Extracting package...'
193 # Extract "outer layer": cpio; remove the original package file
194 cpio -idm --quiet < "$1" && rm -f "$1"
196 # "Inner layer" may vary
197 if [ -f fs.cpio.lzma ]; then
198 # "Plain" cpio.lzma
199 unlzma < fs.cpio.lzma | cpio -idm --quiet && rm fs.cpio.lzma
200 elif [ -f fs.cpio.gz ]; then
201 # "Fast" cpio.gz (used to pack-then-install process in most of get-packages)
202 zcat fs.cpio.gz | cpio -idm --quiet && rm fs.cpio.gz
203 fi
205 status
206 }
209 # Print short package description
211 print_short_description() {
212 # TODO: undigest repo support? priority...
213 # ROOT READY
214 local short_desc=''
216 # Try to find localized short description
217 for LC in $LANG ${LANG%_*}; do
218 [ -e "$PKGS_DB/packages-desc.$LC" ] &&
219 short_desc=$(awk -F$'\t' -vp="$1" '$1==p{print $2; exit}' "$PKGS_DB/packages-desc.$LC")
220 done
222 # Try to find short description for mirrored package
223 [ -z "$short_desc" -a -s "$PKGS_DB/packages.info" ] &&
224 short_desc=$(awk -F$'\t' -vp="$1" '$1==p{print $4; exit}' "$PKGS_DB/packages.info")
226 [ -z "$short_desc" ] && short_desc="$SHORT_DESC"
228 longline "$short_desc"
229 }
232 grepesc() {
233 sed 's/\[/\\[/g'
234 }
239 #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*
241 # Block of receipt function callers
242 # Why? "Bad" receipt sourcing can redefine some vital TazPkg variables.
243 # Few receipts function should be patched now.
245 # Input: $1 = path to the receipt to be processed
247 # Pre-install commands
248 call_pre_install() {
249 local tmp
250 if grep -q '^pre_install()' "$1"; then
251 action 'Execute pre-install commands...'
252 tmp="$(mktemp)"
253 cp "$1" "$tmp"
254 sed -i 's|$1/*$INSTALLED|$INSTALLED|g' "$tmp"
255 ( . "$tmp"; pre_install "$root" )
256 status
257 rm "$tmp"
258 fi
260 }
261 # Post-install commands
262 call_post_install() {
263 local tmp
264 if grep -q '^post_install()' "$1"; then
265 action 'Execute post-install commands...'
266 tmp="$(mktemp)"
267 cp "$1" "$tmp"
268 sed -i 's|$1/*$INSTALLED|$INSTALLED|g' "$tmp"
269 ( . "$tmp"; post_install "$root" )
270 status
271 rm "$tmp"
272 fi
273 }
276 #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*
279 # This function installs a package in the rootfs.
281 install_package() {
282 # input: $1 = path to package to be installed
283 # dep: install_all_deps, print_short_description, extract_package, grepesc.
285 debug "\ninstall_package('$1')"
286 local dir
288 PACKAGE_FILE="$1"
289 TMP_DIR="$(mktemp -d)"
291 # Get receipt's variables and functions
292 { cd "$TMP_DIR"; cpio --quiet -i receipt >/dev/null 2>&1; } < "$PACKAGE_FILE"
293 # Why next code? "Bad" receipt sourcing can redefine some vital TazPkg variables.
294 (
295 . "$TMP_DIR/receipt"
296 cat > "$TMP_DIR/receipt.var" <<EOT
297 PACKAGE="$PACKAGE"
298 VERSION="$VERSION"
299 EXTRAVERSION="$EXTRAVERSION"
300 CATEGORY="$CATEGORY"
301 SHORT_DESC="$SHORT_DESC"
302 WEB_SITE="$WEB_SITE"
303 TAGS="$TAGS"
304 DEPENDS="$DEPENDS"
305 CONFIG_FILES="$CONFIG_FILES"
306 PACKED_SIZE="$PACKED_SIZE"
307 UNPACKED_SIZE="$UNPACKED_SIZE"
308 EOT
309 rm "$TMP_DIR/receipt"
310 )
311 . "$TMP_DIR/receipt.var"
314 # Make sure folder exists on new installs or upgrades
315 mkdir -p "$INSTALLED/$PACKAGE"
317 # Keep "modifiers" and "files.list" on upgrade
318 find "$INSTALLED/$PACKAGE" -type f \( ! -name modifiers ! -name files.list \) -delete
320 # Update "installed.md5"
321 # TODO: discontinue using 'installed.md5'
322 touch "$PKGS_DB/installed.$SUM"
323 sed -i "/ $(basename "$PACKAGE_FILE")$/d" "$PKGS_DB/installed.$SUM" 2>/dev/null
324 cd "$(dirname "$PACKAGE_FILE")"
325 $CHECKSUM "$(basename "$PACKAGE_FILE")" >> "$PKGS_DB/installed.$SUM"
327 # Resolve package dependencies before package installation
328 install_all_deps "$PACKAGE_FILE"
331 # TODO: why this list-processed in the $PKGS_DB?
332 #[ -n "$INSTALL_LIST" ] && echo "$PACKAGE_FILE" >> "$PKGS_DB/$INSTALL_LIST-processed"
334 if [ -n "$sequence" ]; then
335 title 'Installation of package "%s" (%s)' "$PACKAGE" "$sequence"
336 else
337 title 'Installation of package "%s"' "$PACKAGE"
338 fi
340 print_short_description "$PACKAGE"
341 separator '-'
343 action 'Copying package...'
344 cp "$PACKAGE_FILE" "$TMP_DIR"
345 status
347 cd "$TMP_DIR"
348 extract_package "$(basename "$PACKAGE_FILE")"
350 # Include temporary receipt to get the right variables
351 . "$TMP_DIR/receipt.var"
353 cd "$INSTALLED"
356 # Get files to remove if upgrading
357 # IFS here modified temporarily for processing filenames with spaces
358 IFS=$'\n'
359 if [ -f "$PACKAGE/files.list" ]; then
360 while read file; do
361 grep -q "^$(echo "$file" | grepesc)$" "$TMP_DIR/files.list" && continue
362 for i in $(cat "$PACKAGE/modifiers" 2>/dev/null;
363 fgrep -sl "$PACKAGE" */modifiers | cut -d/ -f1); do
364 grep -qs "^$(echo "$file" | grepesc)$" "$i/files.list" && continue 2
365 done
366 echo "$file"
367 done < "$PACKAGE/files.list" > "$TMP_DIR/files2remove.list"
368 fi
369 unset IFS
372 # Remember modified packages
373 action 'Remember modified packages...'
374 {
375 check=false
376 # TODO: why '[' the special?
377 # FIXME: we have files with spaces in our packages!
378 for i in $(fgrep -v [ $TMP_DIR/files.list); do
379 [ -e "$root$i" ] || continue
380 [ -d "$root$i" ] && continue
381 echo "- $i"
382 check=true
383 done ;
384 $check && \
385 for i in *; do
386 [ "$i" == "$PACKAGE" ] && continue
387 [ -s "$i/files.list" ] || continue
388 awk "{ printf \"$i %s\\n\",\$1 }" < "$i/files.list"
389 done;
390 } | awk '
391 {
392 if ($1 == "-" || file[$2] != "") {
393 file[$2] = file[$2] " " $1
394 if ($1 != "-") {
395 if (pkg[$1] == "") all = all " " $1
396 pkg[$1] = pkg[$1] " " $2
397 }
398 }
399 }
400 END {
401 for (i = split(all, p, " "); i > 0; i--)
402 for (j = split(pkg[p[i]], f, " "); j > 0; j--)
403 printf "%s %s\n",p[i],f[j];
404 }
405 ' | while read dir file; do
406 if grep -qs "^$dir$" "$PACKAGE/modifiers"; then
407 # Do not overload an overloaded file !
408 rm "$TMP_DIR/$file" 2>/dev/null
409 continue
410 fi
411 grep -qs "^$PACKAGE$" "$dir/modifiers" && continue
412 if [ -s "$dir/volatile.cpio.gz" ]; then
413 # We can modify backed up files without notice
414 zcat "$dir/volatile.cpio.gz" | cpio -t --quiet | \
415 grep -q "^${file#/}$" && continue
416 fi
417 echo "$PACKAGE" >> "$dir/modifiers"
418 done
419 status
422 cd "$TMP_DIR"
423 # Copy receipt, etc.
424 for file in receipt files.list description.txt $CHECKSUM; do
425 [ -f "$file" ] && cp "$file" "$INSTALLED/$PACKAGE"
426 done
429 # Pre-install commands
430 call_pre_install "$INSTALLED/$PACKAGE/receipt"
433 if [ -n "$CONFIG_FILES" ]; then
434 # Save "official" configuration files
435 action 'Saving configuration files...'
436 debug "\n"
438 cd fs
439 local config_file
440 for config_file in $CONFIG_FILES; do
441 debug " config_file: '$config_file'"
442 find ${config_file#/} -type f 2>/dev/null
443 done | cpio -o -H newc --quiet | gzip -9 > "$INSTALLED/$PACKAGE/volatile.cpio.gz"
444 cd ..
446 if [ -z "$newconf" ]; then
447 debug " no '--newconf': clean official config files"
448 # Keep user configuration files: remove "official" from fs tree
449 for config_file in $CONFIG_FILES; do
450 debug " remove '$config_file'"
451 [ -d "fs$config_file" ] && rm -r "fs$config_file"
452 [ -e "fs$config_file" ] && rm "fs$config_file"
453 done
454 fi
455 # always '[ Done ]' status, unless '--newconf' is passed or not
456 :; status
457 fi
460 if [ -n "$(ls fs/* 2>/dev/null)" ]; then
461 action 'Installing package...'
463 debug '\n resolving destination links in source'
464 IFS=$'\n'
465 for dir in $(find fs -type d | sed 's|^fs||;/^$/d'); do
466 if ldir=$(readlink -n $root$dir); then
467 debug " * mv 'fs$dir'\n -> 'fs${dir%/*}/$ldir'"
468 mkdir -p "fs${dir%/*}/${ldir%/*}"
469 mv "fs$dir" "fs${dir%/*}/$ldir"
470 fi
471 done
472 unset IFS
474 debug ' copying folders and files to destination'
475 cp -af fs/* "$root/"
476 status
477 fi
480 if [ -s files2remove.list ]; then
481 action 'Removing old files...'
482 while read file; do
483 dir="$root$file"
484 # Remove specified file
485 rm -f "$dir"
486 # Recursive remove non-empty up-dirs
487 while [ "$dir" != "$root/" ]; do
488 dir=$(dirname "$dir")
489 rmdir "$dir" 2>/dev/null || break
490 done
491 done < files2remove.list
492 true
493 status
494 fi
497 # Remove the temporary random directory.
498 action "Removing all tmp files..."
499 cd ..; rm -rf "$TMP_DIR"
500 status
503 # Post install commands
504 call_post_install "$INSTALLED/$PACKAGE/receipt"
509 # Update system databases
510 # Updating DBs is important process, so not to hide such errors (localized):
511 # chroot: can't execute '/usr/bin/***': No such file or directory
513 local fl="$INSTALLED/$PACKAGE/files.list" upd=0 ud um ui us uk
515 fgrep /usr/share/applications/ "$fl" | fgrep -q .desktop && udesk='yes'
516 fgrep -q /usr/share/mime "$fl" && umime='yes'
517 fgrep -q /usr/share/icon/hicolor "$fl" && uicon='yes'
518 fgrep -q /usr/share/glib-2.0/schemas "$fl" && uschm='yes'
519 fgrep /usr/lib/gdk-pixbuf "$fl" | fgrep -q .so && upixb='yes'
520 fgrep -q /lib/modules "$fl" && ukrnl='yes'
522 if [ -n "$udesk$umime$uicon$uschm$upixb$ukrnl" ]; then
523 action 'Update system databases...'
524 upd=1
525 fi
527 # package 'desktop-file-utils'
528 [ -n "$udesk" ] && chroot "$root/" /usr/bin/update-desktop-database /usr/share/applications
529 # package 'shared-mime-info'
530 [ -n "$umime" ] && chroot "$root/" /usr/bin/update-mime-database /usr/share/mime
531 # packages 'gtk+', 'gtk+3'
532 [ -n "$uicon" ] && chroot "$root/" /usr/bin/gtk-update-icon-cache /usr/share/icons/hicolor
533 # package 'glib'
534 [ -n "$uschm" ] && chroot "$root/" /usr/bin/glib-compile-schemas /usr/share/glib-2.0/schemas
535 # package 'gdk-pixbuf'
536 [ -n "$upixb" ] && chroot "$root/" /usr/bin/gdk-pixbuf-query-loaders --update-cache
537 # packages 'busybox', 'kmod', 'depmod'
538 [ -n "$ukrnl" ] && chroot "$root/" /sbin/depmod -a
540 [ "$upd" -eq 1 ] && status
545 # Update installed.info
546 SIZES=$(echo $PACKED_SIZE $UNPACKED_SIZE | sed 's|\.0||g')
547 # Remove newlines from some receipts
548 DEPENDS=$(echo $DEPENDS)
549 PKG_SUM="$(fgrep " $PACKAGE-$VERSION$EXTRAVERSION.tazpkg" "$PKGS_DB/installed.$SUM" | cut -d' ' -f1)"
550 ii="$PKGS_DB/installed.info"
551 # Remove old entry
552 sed -i "/^$PACKAGE /d" "$ii"
553 cat >> "$ii" <<EOT
554 $PACKAGE $VERSION$EXTRAVERSION $CATEGORY $SHORT_DESC $WEB_SITE $TAGS $SIZES $DEPENDS $PKG_SUM
555 EOT
556 #awk -F$'\t' -vp="$PACKAGE" '$1==p' "$PKGS_DB/packages.info" > $ii
557 TEMP_FILE="$(mktemp)"
558 sort "$ii" > "$TEMP_FILE"; mv -f "$TEMP_FILE" "$ii"; chmod a+r "$ii"; unset ii
560 cd "$CUR_DIR"
561 footer "$(_ 'Package "%s" (%s) is installed.' "$PACKAGE" "$VERSION$EXTRAVERSION")"
563 # Log this activity
564 log_pkg Installed
566 # Remove package from upgrade list
567 [ -s "$UP_LIST" ] && sed -i "/^$PACKAGE\$/d" "$UP_LIST"
568 }
573 #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*
576 PACKAGE=$(
577 tmp_dir=$(mktemp -d); cd "$tmp_dir"
578 cpio --quiet -i receipt >/dev/null 2>&1
579 . receipt; echo $PACKAGE
580 rm -rf "$tmp_dir"
581 ) < "$1"
583 if [ -z "$forced" ]; then
584 # Check if a package is already installed
585 debug "\ncheck for installed package '$PACKAGE'"
587 awk -F$'\t' -vpv="$PACKAGE" '$1==pv { exit 1 }' "$PKGS_DB/installed.info"
589 if [ "$?" -eq 1 ]; then
590 newline
591 _ '"%s" package is already installed.' "$(colorize 34 "$PACKAGE")"
592 longline "$(_ 'You can use the --forced option to force installation.')"
593 newline
594 exit 1
595 fi
596 fi
598 install_package "$(realpath "$1")"