apkg (24083B)
1 #!/bin/sh 2 # ______ ______ __ __ ______ 3 # /\ __ \ /\ == \/\ \/ / /\ ___\ 4 # \ \ __ \\ \ _-/\ \ _"-.\ \ \__ \ 5 # \ \_\ \_\\ \_\ \ \_\ \_\\ \_____\ 6 # \/_/\/_/ \/_/ \/_/\/_/ \/_____/ 7 # 8 # APKG - Alice Package Manager (C) 2023-2025 Emmett1 9 # 10 11 fetch_src() { 12 [ "$source" ] || return 0 13 for i in $source; do 14 i=${i%::noextract} 15 case $i in 16 *::*) sn=${i%::*};; 17 *) sn=${i##*/};; 18 esac 19 case ${i#*::} in 20 http://*|https://*|ftp://*) 21 if [ ! -f $APKG_SOURCE_DIR/$sn ]; then 22 [ -f $APKG_SOURCE_DIR/$sn.tmp ] && resume="-C -" 23 msg "fetching ${i#*::}" 24 curl $resume --fail --retry 3 --retry-delay 3 -L -o $APKG_SOURCE_DIR/$sn.tmp ${i#*::} || { 25 msg "Failed downloading source '$sn'." 26 exit 1 27 } 28 mv $APKG_SOURCE_DIR/$sn.tmp $APKG_SOURCE_DIR/$sn 29 fi;; 30 esac 31 done 32 } 33 34 extract_src() { 35 prepare_workdir 36 [ "$source" ] || return 0 37 checksource 38 for i in $source; do 39 case $i in 40 */*) S=$APKG_SOURCE_DIR;; 41 *) S=$HERE;; 42 esac 43 case ${i%::noextract} in 44 *::*) sn=${i%%::*};; 45 *) sn=${i##*/}; sn=${sn%::noextract};; 46 esac 47 case $i in 48 *::noextract) 49 i=${i%::noextract} 50 cp $S/$sn $SRC || { 51 msg "Failed copy '$S/$sn' to '$SRC'." 52 ret 1 53 };; 54 *.tar.bz2|*.tar.gz|*.tar.lz|*.tar.lzma|*.tar.lzo|*.tar.xz|*.tar.Z|*.tb2|*.tbz|*.tbz2|*.tz2|*.taz|*.tgz|*.tlz|*.txz|*.tZ|*.taZ) 55 msg "Unpacking '$S/$sn'..." 56 tar -p -o -C $SRC -xf $S/$sn || { 57 msg "Failed unpacking source '${i##*/}'." 58 ret 1 59 };; 60 *) 61 i=${i%::noextract} 62 cp $S/$sn $SRC || { 63 msg "Failed copy '$S/$sn' to '$SRC'." 64 ret 1 65 };; 66 esac 67 done 68 } 69 70 prepare_workdir() { 71 export SRC=$APKG_WORK_DIR/apkg-src-${PWD##*/} 72 export PKG=$APKG_WORK_DIR/apkg-pkg-${PWD##*/} 73 74 remove_workdir 75 mkdir -p "$PKG" "$SRC" 76 } 77 78 remove_workdir() { 79 rm -rf "$PKG" "$SRC" 80 } 81 82 ret() { 83 [ "$APKG_KEEP_WORKDIR" ] || remove_workdir 84 exit $1 85 } 86 87 detect_buildtype() { 88 if [ -f meson.build ]; then 89 build_type=meson_build 90 elif [ -f configure ]; then 91 build_type=configure_build 92 elif [ -f CMakeLists.txt ]; then 93 build_type=cmake_build 94 elif [ -f setup.py ]; then 95 build_type=python_build 96 elif [ -f Makefile.PL ]; then 97 build_type=perlmodule_build 98 elif [ -f Makefile ] || [ -f makefile ] || [ -f GNUmakefile ]; then 99 build_type=makefile_build 100 else 101 msg "failed to detect buildtype" 102 ret 1 103 fi 104 } 105 106 _makefile_build() { 107 make \ 108 PREFIX=/usr \ 109 prefix=/usr \ 110 SYSCONFDIR=/etc \ 111 sysconfdir=/etc \ 112 MANDIR=/usr/share/man \ 113 mandir=/usr/share/man \ 114 LIBDIR=/usr/lib \ 115 PKGCONFIGDIR=/usr/lib/pkgconfig 116 make \ 117 PREFIX=/usr \ 118 prefix=/usr \ 119 SYSCONFDIR=/etc \ 120 sysconfdir=/etc \ 121 MANDIR=/usr/share/man \ 122 mandir=/usr/share/man \ 123 LIBDIR=/usr/lib \ 124 PKGCONFIGDIR=/usr/lib/pkgconfig \ 125 DESTDIR=$PKG install 126 } 127 128 _perlmodule_build() { 129 perl Makefile.PL 130 make 131 make DESTDIR=$PKG install 132 } 133 134 _cmake_build() { 135 mkdir -p cmakebuild 136 cd cmakebuild 137 cmake \ 138 -DCMAKE_INSTALL_PREFIX=/usr \ 139 -DCMAKE_INSTALL_SYSCONFDIR=/etc \ 140 -DCMAKE_INSTALL_LIBDIR=lib \ 141 -DCMAKE_BUILD_TYPE=Release \ 142 -DFETCHCONTENT_FULLY_DISCONNECTED=ON \ 143 -DCMAKE_C_FLAGS_RELEASE="$CFLAGS" \ 144 -DCMAKE_CXX_FLAGS_RELEASE="$CXXFLAGS" \ 145 $build_opt \ 146 -B build .. 147 if [ -f build.ninja ]; then 148 ninja 149 DESTDIR=$PKG ninja install 150 else 151 cmake --build build 152 DESTDIR=$PKG cmake --install build 153 fi 154 } 155 156 _python_build() { 157 python3 setup.py build 158 python3 setup.py install --prefix=/usr --root=$PKG --optimize=1 $build_opt 159 } 160 161 _configure_build() { 162 ./configure \ 163 --prefix=/usr \ 164 --sysconfdir=/etc \ 165 --localstatedir=/var \ 166 --libdir=/usr/lib \ 167 --infodir=/usr/share/info \ 168 --mandir=/usr/share/man \ 169 $build_opt 170 make 171 make DESTDIR=$PKG install 172 } 173 174 _meson_build() { 175 meson setup \ 176 -Dprefix=/usr \ 177 -Dlibdir=/usr/lib \ 178 -Dincludedir=/usr/include \ 179 -Ddatadir=/usr/share \ 180 -Dmandir=/usr/share/man \ 181 -Dinfodir=/usr/share/info \ 182 -Dlocaledir=/usr/share/locale \ 183 -Dsysconfdir=/etc \ 184 -Dlocalstatedir=/var \ 185 -Dsharedstatedir=/var/lib \ 186 -Dbuildtype=plain \ 187 -Dauto_features=auto \ 188 -Dwrap_mode=nodownload \ 189 -Db_lto=true \ 190 -Db_pie=true \ 191 $build_opt \ 192 build 193 ninja -C build 194 DESTDIR=$PKG meson install -C build 195 } 196 197 apply_patch() { 198 [ "$skip_patch" ] && { 199 unset skip_patch # allowing manual patch in build() using apply_patch 200 return 0 201 } 202 if [ "$source" ]; then 203 for p in $source; do 204 case ${p%::noextract} in 205 *::*) pn=${p%::*};; 206 *) pn=${p##*/};; 207 esac 208 case $pn in 209 *.patch|*.diff) 210 msg "applying path '$SRC/$pn'." 211 patch ${patch_opt:--p1} -t -i $SRC/$pn || ret 1;; 212 esac 213 done 214 fi 215 } 216 217 msg() { 218 # Don't bother if we're not in a terminal 219 if [ -t 1 ]; then 220 ttysize=$(stty size 2>/dev/null | awk '{print $2}' || echo "80") 221 fi 222 printf "%s\n" "[${name:-...}] $@" | fold -sw ${ttysize:-80} 223 } 224 225 buildstatus() { 226 [ "$?" = 0 ] || { 227 msg "build package '$name-$version-$release' failed on '$1'." 228 ret 1 229 } 230 } 231 232 build_src() { 233 cd $SRC 234 235 if [ "$build_dir" ]; then 236 if [ ! -d "$build_dir" ]; then 237 msg "Source directory '$build_dir' not found." 238 ret 1 239 fi 240 elif [ -d $name-$version ]; then 241 build_dir=$name-$version 242 elif [ -d "$(ls -1 --group-directories-first | head -n1)" ]; then 243 build_dir=$(ls -1 --group-directories-first | head -n1) 244 fi 245 246 # cd into extracted source directory 247 if [ "$build_dir" ]; then 248 cd $build_dir 249 fi 250 251 apply_patch 252 253 export CARGO_HOME=${CARGO_HOME:-$SRC/.cargo} 254 export GOCACHE=${GOCACHE:-$SRC/.go} 255 export DESTDIR=$PKG 256 export DEST_DIR=$PKG # p7zip 257 export INSTALLROOT=$PKG # syslinux 258 export install_root=$PKG # glibc 259 export INSTALL_ROOT=$PKG # qt5 260 261 if [ ! "$source" ]; then 262 # dummy pkg 263 mkdir -p $PKG/usr 264 elif [ "$(command -v build)" ]; then 265 (set -e -x; build) 266 buildstatus build 267 else 268 if [ "$(command -v prebuild)" ]; then 269 (set -e -x; prebuild) 270 buildstatus prebuild 271 fi 272 if [ ! "${build_type}" ]; then 273 detect_buildtype 274 fi 275 (set -e -x; _${build_type}) 276 buildstatus ${build_type} 277 if [ "$(command -v postbuild)" ]; then 278 (set -e -x; postbuild) 279 buildstatus postbuild 280 fi 281 fi 282 283 msg "build $name-$version-$release success" 284 285 # compress man pages 286 if [ -d $PKG/usr/share/man ]; then 287 # only keep man[1-8] man pages 288 for m in $PKG/usr/share/man/*; do 289 case ${m##*/} in 290 man[1-8]) continue;; 291 esac 292 rm -rf $m 293 done 294 for i in $(find $PKG/usr/share/man -type f); do 295 [ $i = ${i%%.gz} ] || continue 296 gzip -9 $i 297 done 298 for i in $(find $PKG/usr/share/man -type l) ; do 299 ln -s $(readlink $i).gz ${i%.gz}.gz 300 rm $i 301 done 302 fi 303 304 # compress info pages 305 if [ -d $PKG/usr/share/info ]; then 306 rm -f $PKG/usr/share/info/dir 307 find $PKG/usr/share/info -type f -exec gzip -9 {} \; 308 fi 309 310 # possible conflicts 311 find $PKG -name "fonts.dir" -exec rm {} \; 312 find $PKG -name "fonts.scale" -exec rm {} \; 313 find $PKG -name "perllocal.pod" -exec rm {} \; 314 find $PKG -name "charset.alias" -exec rm {} \; 315 316 if [ ! "$keep_static" ]; then 317 find $PKG -name "*.a" -exec rm {} \; 318 fi 319 320 if [ ! "$keep_libtool" ]; then 321 find $PKG -name "*.la" -exec rm {} \; 322 fi 323 324 if [ ! "$keep_locale" ]; then 325 rm -rf $PKG/usr/share/locale 326 rm -rf $PKG/usr/lib/locale 327 fi 328 329 if [ ! "$keep_doc" ]; then 330 rm -rf $PKG/usr/share/doc 331 rm -rf $PKG/usr/doc 332 fi 333 334 # strip binaries and libraries 335 if [ ! "$no_strip" ]; then 336 find $PKG | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs ${CROSS_COMPILE}strip --strip-all 2>/dev/null 337 find $PKG | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs ${CROSS_COMPILE}strip --strip-unneeded 2>/dev/null 338 find $PKG | xargs file | grep "current ar archive" | cut -f 1 -d : | xargs ${CROSS_COMPILE}strip --strip-debug 2>/dev/null 339 fi 340 341 # usrmerge 342 if [ "$APKG_BINMERGE" ]; then 343 for b in bin sbin usr/sbin; do 344 if [ -d $PKG/$b ]; then 345 mkdir -p $PKG/usr/bin 346 mv $PKG/$b/* $PKG/usr/bin 347 rm -rf $PKG/$b 348 fi 349 done 350 fi 351 352 # runit service 353 for s in $sv; do 354 [ -f $SRC/$s ] || ret 1 355 case $s in 356 run) install -Dm755 $SRC/$s $PKG/etc/sv/$name/run 357 ln -s ../../../run/runit/supervise.$name $PKG/etc/sv/$name/supervise;; 358 finish) install -Dm755 $SRC/$s $PKG/etc/sv/$name/finish;; 359 *.run) install -Dm755 $SRC/$s $PKG/etc/sv/${s%.*}/run 360 ln -s ../../../run/runit/supervise.${s%.*} $PKG/etc/sv/${s%.*}/supervise;; 361 *.finish) install -Dm755 $SRC/$s $PKG/etc/sv/${s%.*}/finish;; 362 *.*) install -Dm644 $SRC/$s $PKG/etc/sv/${s%%.*}/${s#*.};; 363 *) install -Dm644 $SRC/$s $PKG/etc/sv/$name/$s;; 364 esac 365 done 366 367 if [ ! "$(ls -1 $PKG)" ]; then 368 msg "\$PKG is empty" 369 ret 1 370 fi 371 372 # temporary: for backward compatibility 373 if [ "$(grep '#MARKER' /usr/bin/spm)" ]; then 374 cd $PKG 375 spm -b $packagefile || { 376 msg "Failed packaging $packagefile" 377 ret 1 378 } 379 else 380 cd $APKG_PACKAGE_DIR 381 spm -b $PKG && { 382 mv package.spm $packagefile 383 } || { 384 msg "Failed packaging $packagefile" 385 ret 1 386 } 387 fi 388 389 if [ ! -f "$HERE"/.files ] || [ "$HERE"/abuild -nt "$HERE"/.files ]; then 390 pkg_updatefiles 391 fi 392 393 cd $HERE 394 remove_workdir 395 } 396 397 pkg_updatefiles() { 398 if [ ! -f "$packagefile" ]; then 399 msg "Package '$packagefile' not found." 400 ret 1 401 fi 402 msg "filelist updated." 403 tar -tvf $packagefile | awk '{$3=$4=$5=""; print $0}' | sort -k 3 > "$HERE"/.files 404 } 405 406 pkg_path() { 407 for p in $@; do 408 for r in $APKG_REPO; do 409 [ -f $r/$p/abuild ] && { 410 printf "%s\n" $r/$p 411 break 412 } 413 done 414 done 415 } 416 417 die() { 418 [ "$1" ] && printf "%s\n" "error: $1" 419 ret 1 420 } 421 422 checkdep() { 423 [ "$(pkg_path $1)" ] || return 424 # track processed pkg to avoid cycle deps 425 process="$process $1" 426 for ii in $(pkg_depends $1); do 427 # if already installed, skip 428 if [ "$skip_installed" ]; then 429 [ -s $SPM_PKGDB/$ii ] && continue 430 fi 431 # if deps already in process list, skip, cycle deps detected 432 printf "%s\n" $process | tr ' ' '\n' | grep -qx $ii && continue 433 # skip if itself in depends list 434 [ "$ii" = "$1" ] && continue 435 # skip if pkg already in deps list 436 printf "%s\n" $DEPS | tr ' ' '\n' | grep -x $ii && continue 437 # check deps 438 checkdep $ii 439 done 440 # will go here if no deps anymore to check, add it to list deps 441 DEPS="$DEPS $1" 442 } 443 444 pkg_deplist() { 445 for i in $@; do 446 # if already have in list deps, dont check again 447 if [ ! $(printf "%s\n" $DEPS | tr ' ' '\n' | grep -x $i) ]; then 448 checkdep $i 449 fi 450 done 451 printf "%s\n" $DEPS | tr ' ' '\n' 452 } 453 454 pkg_fsearch() { 455 for r in $APKG_REPO; do 456 rr="$rr $r/*/.files" 457 done 458 grep $1 $rr 2>/dev/null | tr ':' ' ' | awk '{print $1,$4}' | sed 's,/.files,,g' 459 } 460 461 pkg_dependents() { 462 for r in $APKG_REPO; do 463 rr="$rr $r/*/depends" 464 done 465 grep -x $1 $rr 2>/dev/null | rev | cut -d / -f 2 | rev 466 } 467 468 pkg_depends() { 469 _path=$(pkg_path $1) || return 1 470 [ -s $_path/depends ] || return 471 solve_alias $(grep -Ev ^'(#|$)' $_path/depends | awk '{print $1}') 472 } 473 474 solve_alias() { 475 [ "$APKG_ALIAS" ] || { 476 printf "%s\n" $@ 477 return 478 } 479 while [ "$1" ]; do 480 d=$(printf "%s\n" $APKG_ALIAS | tr ' ' '\n' | grep ^$1:* | head -n1 | awk -F : '{print $2}') 481 printf "%s\n" ${d:-$1} 482 shift 483 done 484 } 485 486 pkg_outdate() { 487 verbose=1 pkg_allinstalled | while read -r n v; do 488 [ "$APKG_MASK" ] && { 489 printf "%s\n" "$APKG_MASK" | tr ' ' '\n' | grep -xq $n && continue 490 } 491 [ "$(pkg_path $n)" ] || continue 492 nv="$(grep ^version= $(pkg_path $n)/abuild | tail -n1 | awk -F = '{print $2}')-$(grep ^release= $(pkg_path $n)/abuild | awk -F = '{print $2}')" 493 [ "$nv" ] || continue 494 [ "$v" = "$nv" ] || printf "%s\n" "$n $v -> $nv" 495 done 496 } 497 498 pkg_remove() { 499 needroot 500 for i in $@; do 501 SPM_ROOT=$APKG_ROOT spm -r $i 502 done 503 } 504 505 pkg_sysup() { 506 needroot 507 msg "Checking for outdated packages..." 508 od=$(pkg_outdate | awk '{print $1}') 509 if [ ! "$od" ]; then 510 msg "No outdated packages." 511 exit 0 512 else 513 msg "Solving dependencies..." 514 for p in $(pkg_deplist $od); do 515 [ -s $SPM_PKGDB/$p ] || ni="$ni $p" 516 printf "%s\n" $od | tr ' ' '\n' | grep -qx $p && pu="$pu $p" 517 done 518 if [ "$ni" ]; then 519 newpkg=$(printf "%s\n" $ni | tr ' ' '\n' | wc -l) 520 msg "Installing $newpkg new package(s): $ni" 521 fi 522 totalpkg=$(printf "%s\n" $pu | tr ' ' '\n' | wc -l) 523 msg "Upgrading $totalpkg package(s): $pu" 524 prompt_user 525 if [ "$ni" ]; then 526 $APKG -i $ni || die 527 fi 528 $APKG -u $pu || die 529 fi 530 } 531 532 pkg_search() { 533 if [ ! "$APKG_REPO" ]; then 534 msg "No repo configured." 535 exit 1 536 fi 537 if [ "$pkg" ]; then 538 for p in $pkg; do 539 grep="$grep -e $p" 540 done 541 grep="grep $grep" 542 else 543 grep=cat 544 fi 545 [ "$verbose" ] && { 546 find $APKG_REPO -type f -name abuild 2>/dev/null | sed 's|/abuild||' | rev | awk -F / '{print $1}' | rev | $grep | while read line; do printf "$line "; awk -F'=' '/^version/ {print $2}' $($APKG -p $line)/abuild ; done 547 } || { 548 find $APKG_REPO -type f -name abuild 2>/dev/null | sed 's|/abuild||' | rev | awk -F / '{print $1}' | rev | $grep 549 } 550 } 551 552 pkg_depinstalll() { 553 needroot 554 for p in $@; do 555 if [ -s $SPM_PKGDB/$p ]; then 556 msg "Package '$p' is installed" 557 continue 558 fi 559 if [ ! "$(pkg_path $p)" ]; then 560 msg "Package '$p' not found" 561 continue 562 fi 563 pkg="$pkg $p" 564 done 565 [ "$pkg" ] || exit 0 566 set -- $pkg 567 msg "Solving dependencies..." 568 for p in $(skip_installed=1 pkg_deplist $@); do 569 [ -s $SPM_PKGDB/$p ] && continue 570 installthis="$installthis $p" 571 done 572 if [ ! "$installthis" ]; then 573 msg "Nothing to install. Exiting..." 574 exit 0 575 fi 576 totalpkg=$(printf "%s\n" $installthis | tr ' ' '\n' | wc -l) 577 msg "Installing $totalpkg package(s): $installthis" 578 prompt_user 579 $APKG -i $installthis || die 580 } 581 582 _trigger_fccache() { 583 command -v fc-cache >/dev/null || return 0 584 spm -l $1 | grep -q ^usr/share/fonts/$ && { 585 msg "Updating fontconfig cache..." 586 fc-cache -sf 587 } 588 } 589 590 _trigger_gdkpixbufcache() { 591 command -v gdk-pixbuf-query-loaders >/dev/null || return 0 592 spm -l $1 | grep -q ^usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/$ && { 593 msg "Probing GDK-Pixbuf loader modules..." 594 gdk-pixbuf-query-loaders --update-cache 595 } 596 } 597 598 _trigger_giomodules() { 599 command -v gio-querymodules >/dev/null || return 0 600 spm -l $1 | grep -q ^usr/lib/gio/modules/$ && { 601 msg "Updating GIO module cache..." 602 gio-querymodules /usr/lib/gio/modules 603 } 604 } 605 606 _trigger_glibschema() { 607 command -v glib-compile-schemas >/dev/null || return 0 608 spm -l $1 | grep -q ^usr/share/glib-2.0/schemas/$ && { 609 msg "Compiling GSettings XML schema files..." 610 glib-compile-schemas /usr/share/glib-2.0/schemas 611 } 612 } 613 614 _trigger_gtk2immodules() { 615 command -v gtk-query-immodules-2.0 >/dev/null || return 0 616 spm -l $1 | grep -q ^usr/lib/gtk-2.0/2.10.0/immodules/$ && { 617 msg "Probing GTK2 input method modules..." 618 gtk-query-immodules-2.0 --update-cache 619 } 620 } 621 622 _trigger_gtk3immodules() { 623 command -v gtk-query-immodules-3.0 >/dev/null || return 0 624 spm -l $1 | grep -q ^usr/lib/gtk-3.0/3.0.0/immodules/$ && { 625 msg "Probing GTK3 input method modules..." 626 gtk-query-immodules-3.0 --update-cache 627 } 628 } 629 630 _trigger_iconcache() { 631 command -v gtk-update-icon-cache >/dev/null || return 0 632 spm -l $1 | grep -q ^usr/share/icons/$ && { 633 msg "Updating icon theme caches..." 634 for dir in /usr/share/icons/* ; do 635 if [ -e $dir/index.theme ]; then 636 gtk-update-icon-cache -q $dir 2>/dev/null 637 else 638 rm -f $dir/icon-theme.cache 639 rmdir --ignore-fail-on-non-empty $dir 640 fi 641 done 642 } 643 } 644 645 _trigger_udevdb() { 646 command -v udevadm >/dev/null || return 0 647 spm -l $1 | grep -q ^etc/udev/hwdb.d/$ && { 648 msg "Updating hardware database..." 649 udevadm hwdb --update 650 } 651 } 652 653 _trigger_fontcache() { 654 command -v mkfontdir >/dev/null || return 0 655 command -v mkfontscale >/dev/null || return 0 656 spm -l $1 | grep -q ^usr/share/fonts/$ && { 657 msg "Updating X fontdir indices..." 658 for dir in $(find /usr/share/fonts -maxdepth 1 -type d \( ! -path /usr/share/fonts \)); do 659 rm -f $dir/fonts.scale $dir/fonts.dir $dir/.uuid 660 rmdir --ignore-fail-on-non-empty $dir 661 [ -d "$dir" ] || continue 662 mkfontdir $dir 663 mkfontscale $dir 664 done 665 } 666 } 667 668 _trigger_desktopdb() { 669 command -v update-desktop-database >/dev/null || return 0 670 spm -l $1 | grep -q ^usr/share/applications/$ && { 671 msg "Updating desktop file MIME type cache..." 672 update-desktop-database --quiet 673 } 674 } 675 676 _trigger_mimedb() { 677 command -v update-mime-database >/dev/null || return 0 678 spm -l $1 | grep -q ^usr/share/mime/$ && { 679 msg "Updating the MIME type database..." 680 update-mime-database /usr/share/mime 681 } 682 } 683 684 pkg_trigger() { 685 needroot 686 [ "$@" ] || set -- $($APKG -a) 687 for t in mimedb desktopdb fontcache fccache udevdb iconcache gtk3immodules gtk2immodules glibschema giomodules gdkpixbufcache; do 688 for p in $@; do 689 _trigger_$t $p && break 690 done 691 done 692 } 693 694 pkg_allinstalled() { 695 if [ "$pkg" ]; then 696 for p in $pkg; do 697 grep="$grep -e $p" 698 done 699 grep="grep $grep" 700 else 701 grep=cat 702 fi 703 [ "$verbose" ] && { 704 ls -1 $SPM_PKGDB | $grep | while read line; do printf "$line "; head -n1 $SPM_PKGDB/$line ; done 705 } || { 706 ls -1 $SPM_PKGDB | $grep 707 } 708 } 709 710 checksum_src() { 711 if [ ! -s "$checksum_file" ]; then 712 gencsum 713 else 714 b3sumcheck || return 0 715 printcsum > ${checksum_file}.tmp 716 diff -U 0 ${checksum_file} ${checksum_file}.tmp | \ 717 sed '/---/d;/+++/d;/@@/d' | \ 718 sed 's/^+/ new : /' | \ 719 sed 's/^-/ missing: /' > ${checksum_file}.diff 720 [ -s "${checksum_file}.diff" ] && { 721 cat ${checksum_file}.diff 722 msg "Checksum failed." 723 failed=1 724 } 725 rm -f ${checksum_file}.tmp ${checksum_file}.diff 726 [ "$failed" ] && ret 1 727 fi 728 } 729 730 printsource() { 731 # print out source full path 732 for printsource in $source; do 733 printsource=${printsource%::noextract} 734 case $printsource in 735 *::*) sourcename=${printsource%::*};; 736 *) sourcename=${printsource##*/};; 737 esac 738 case ${printsource#*::} in 739 */*) sourcenamefullpath=${APKG_SOURCE_DIR}/$sourcename;; 740 *) sourcenamefullpath=${HERE}/$sourcename;; 741 esac 742 printf "%s\n" $sourcenamefullpath 743 done 744 } 745 746 checksource() { 747 # check for source existence, exit non-zero if missing 748 for checksource in $(printsource); do 749 [ -f "$checksource" ] || { 750 msg "Source file '$checksource' not found." 751 failed=1 752 } 753 done 754 [ "$failed" ] && ret 1 755 } 756 757 b3sumcheck() { 758 command -v b3sum >/dev/null || { msg "'b3sum' not installed."; return 1; } 759 } 760 761 gencsum() { 762 checksource 763 b3sumcheck || return 0 764 rm -f .checksum 765 printcsum > .checksum 766 msg "Checksum file updated." 767 } 768 769 printcsum() { 770 for printcsum in $(printsource); do 771 [ -f "$printcsum" ] || continue 772 b3sum $printcsum | sed "s,$APKG_SOURCE_DIR/,,;s,$HERE/,," 773 done | sort -k 2 774 } 775 776 prompt_user() { 777 if [ ! "$APKG_NOPROMPT" ]; then 778 msg "Press ENTER to continue operation." 779 msg "Press Ctrl + C to abort." 780 read -r null 781 fi 782 } 783 784 runscript() { 785 if [ -x ./${1}install ]; then 786 msg "Running ${1}install script..." 787 if [ "$APKG_ROOT" ]; then 788 cat ./${1}install > "$APKG_ROOT"/.runscript 789 chmod +x "$APKG_ROOT"/.runscript 790 chroot "$APKG_ROOT" /.runscript 791 rm -f "$APKG_ROOT"/.runscript 792 else 793 ./${1}install 794 fi 795 fi 796 } 797 798 needroot() { 799 [ $(id -u) = 0 ] || { 800 msg 'This operation need root access' 801 exit 1 802 } 803 } 804 805 parsesubopt() { 806 # loop opts until found '-*' 807 shift; while [ "$1" ]; do 808 case $1 in 809 -*) break;; 810 *) printf "%s\n" "$1";; 811 esac 812 shift 813 done 814 } 815 816 updateopts() { 817 while [ "$1" ]; do 818 case $1 in 819 -*) newopt="$newopt $1";; 820 esac 821 shift 822 done 823 printf "%s\n" "$newopt" 824 } 825 826 parseopts() { 827 while [ "$1" ]; do 828 case $1 in 829 -I) pkg_depinstalll "$(parsesubopt "$@")"; exit 0;; 830 -D) pkg_deplist "$(parsesubopt "$@")"; exit 0;; 831 -r) pkg_remove "$(parsesubopt "$@")"; exit 0;; 832 -p) pkg_path "$(parsesubopt "$@")"; exit 0;; 833 -t) pkg_trigger "$(parsesubopt "$@")"; exit 0;; 834 -U) pkg_sysup; exit 0;; 835 -d) pkg_depends "$2"; exit 0;; 836 -s) search=1;; 837 -S) pkg_fsearch "$2"; exit 0;; 838 -j) pkg_dependents "$2"; exit 0;; 839 -a) allinstalled=1;; 840 -h) apkg_help; exit 0;; 841 -l) pkg_outdate; exit 0;; 842 -g) updatecsum=1;; 843 -k) updatefiles=1;; 844 -f) forcerebuild=1;; 845 -i) install=1;; 846 -u) upgrade=1;; 847 -o) downloadonly=1;; 848 -v) verbose=1;; 849 -*) msg "invalid option '$1'"; exit 1;; 850 *) pkg="$pkg $1";; 851 esac 852 shift 853 done 854 } 855 856 apkg_help() { 857 cat << EOF 858 usage: ${0##*/} <option> <arg(s)> 859 860 options: 861 -i <pkg(s)> install package(s) 862 -I <pkg(s)> install packages(s) with dependencies 863 -d <pkg> list <pkg> dependencies 864 -D <pkg(s)> list all dependencies 865 -j <pkg> list all dependents 866 -u <pkg(s)> upgrade package(s) 867 -r <pkg(s)> remove package(s) 868 -t [pkg(s)] trigger system cache/db updates 869 -U update system 870 -f force rebuild 871 -o <pkg(s)> download source 872 -p <pkg> print package path 873 -g <pkg> update package checksum 874 -k <pkg> update package files 875 -l list outdated packages 876 -s <pattern> search packages 877 -S <pattern> search files 878 -v be verbose 879 -h print this help message 880 881 environment variables: 882 APKG_ROOT override default root (${APKG_ROOT:-/}) location 883 APKG_CONF override default $APKG_CONF location 884 APKG_NOPROMPT set the variable for non-interactive use 885 APKG_LOG set the variable for logging the output to a file 886 887 EOF 888 exit 0 889 } 890 891 main() { 892 parseopts "$@" 893 set -- $(updateopts "$@") 894 895 if [ "$search" ]; then 896 pkg_search $@ 897 exit 0 898 fi 899 900 if [ "$allinstalled" ]; then 901 pkg_allinstalled $@ 902 exit 0 903 fi 904 905 for d in $APKG_PACKAGE_DIR $APKG_SOURCE_DIR $APKG_WORK_DIR $APKG_LOG_DIR; do 906 [ -d "$d" ] || { msg "Directory '$d' not exist"; exit 1; } 907 [ -w "$d" ] || { msg "Directory '$d' dont have write access"; exit 1; } 908 done 909 910 if [ "$pkg" ]; then 911 for p in $pkg; do 912 [ "$(pkg_path "$p")" ] || { 913 msg "Package '$p' not found" 914 continue 915 } 916 (cd "$(pkg_path "$p")" && $APKG "$@") || exit 1 917 done 918 exit 0 919 fi 920 921 if [ ! -f ./abuild ]; then 922 msg "'abuild' not found." 923 exit 1 924 fi 925 926 . ./abuild 927 [ "$name" ] || die "name is empty" 928 [ "$version" ] || die "version is empty" 929 [ "$release" ] || die "release is empty" 930 [ "$name" = "${PWD##*/}" ] || { 931 msg "'name' should be same as package directory name (${PWD##*/})." 932 exit 1 933 } 934 935 logfile="$APKG_LOG_DIR"/$name.log 936 packagefile="$APKG_PACKAGE_DIR"/$name#$version-$release.spm 937 938 if [ "$install" ] && [ -s "$SPM_PKGDB/${PWD##*/}" ]; then 939 msg "Package '${PWD##*/}' already installed." 940 exit 0 941 fi 942 943 if [ "$upgrade" ] && [ ! -s "$SPM_PKGDB/${PWD##*/}" ]; then 944 msg "Package '${PWD##*/}' not installed." 945 exit 0 946 fi 947 948 if [ "$updatecsum" ]; then 949 gencsum 950 exit 0 951 fi 952 953 if [ "$downloadonly" ]; then 954 fetch_src 955 exit 0 956 fi 957 958 if [ "$updatefiles" ]; then 959 pkg_updatefiles 960 exit 0 961 fi 962 963 if [ "$(id -u)" != 0 ]; then 964 msg "Packages need to build as root. Aborted." 965 exit 1 966 fi 967 968 if [ -f "$packagefile" ] && [ ! "$forcerebuild" ]; then 969 if [ ! "$install" ] && [ ! "$upgrade" ]; then 970 msg "Package '$packagefile' found." 971 fi 972 else 973 if [ "$install" ] || [ "$upgrade" ]; then 974 # run preinstall script before build 975 runscript pre 976 fi 977 fetch_src 978 checksum_src 979 extract_src 980 [ "$APKG_LOG" ] && { 981 build_src 2>&1 | tee -- "$logfile" 982 } || { 983 build_src 984 } 985 fi 986 987 if [ "$install" ]; then 988 SPM_ROOT=${APKG_ROOT%/} spm -i "$packagefile" || exit $? 989 elif [ "$upgrade" ]; then 990 SPM_ROOT=${APKG_ROOT%/} spm -u "$packagefile" || exit $? 991 fi 992 993 if [ "$install" ] || [ "$upgrade" ]; then 994 # run postinstall script after installed/upgraded 995 runscript post 996 [ "$APKG_ROOT" ] || pkg_trigger "$name" 997 fi 998 } 999 1000 umask 022 1001 1002 export HERE="$PWD" 1003 1004 APKG=$0 1005 SPM_PKGDB="${APKG_ROOT%/}/var/lib/spm/db" 1006 1007 # for apkg config, either override or default 1008 APKG_CONF="${APKG_CONF:-/etc/apkg.conf}" 1009 1010 ## NEED BETTER WAY TO DO THIS? 1011 # environment override 1012 O_APKG_REPO=$APKG_REPO 1013 O_APKG_PACKAGE_DIR=$APKG_PACKAGE_DIR 1014 O_APKG_SOURCE_DIR=$APKG_SOURCE_DIR 1015 O_APKG_WORK_DIR=$APKG_WORK_DIR 1016 O_APKG_LOG_DIR=$APKG_LOG_DIR 1017 1018 # default value 1019 APKG_REPO="$PWD" 1020 APKG_PACKAGE_DIR="$PWD" 1021 APKG_SOURCE_DIR="$PWD" 1022 APKG_WORK_DIR="$PWD" 1023 APKG_LOG_DIR="$PWD" 1024 1025 checksum_file="$HERE/.checksum" 1026 1027 # source config 1028 if [ -f "$APKG_CONF" ]; then 1029 . "$APKG_CONF" 1030 fi 1031 1032 # reset value, use override first, else either from config or use default 1033 APKG_REPO=${O_APKG_REPO:-$APKG_REPO} 1034 APKG_PACKAGE_DIR=${O_APKG_PACKAGE_DIR:-$APKG_PACKAGE_DIR} 1035 APKG_SOURCE_DIR=${O_APKG_SOURCE_DIR:-$APKG_SOURCE_DIR} 1036 APKG_WORK_DIR=${O_APKG_WORK_DIR:-$APKG_WORK_DIR} 1037 APKG_LOG_DIR=${O_APKG_LOG_DIR:-$APKG_LOG_DIR} 1038 1039 main "$@" 1040 1041 exit 0