#!/usr/bin/env zsh # Recommended: hg >= 1.0 PDIR="$HOME/packages" PKG_ROOT="ssh://derf.homelinux.org/var/packages_root" VCS_CMD="hg" VCS_OPTIONS="--quiet" VCS_ADD="clone" VCS_INCOMING="incoming" VCS_STATUS="status" VCS_UPDATE="pull" VCS_UPDATE_OPTIONS="--update" CL_OPTIONS="-q" info=$'\e[0;36m' error=$'\e[0;31m' reset=$'\e[0m' info () { echo -ne "${info}$*${reset}" } warn () { echo -ne "${error}$*${reset}" } die () { echo -ne "${error}$*${reset}" exit 100 } check_sed () { QUUX=$(echo foox | sed -r 's/^fo{2}(.)$/quu\1/' 2> /dev/null) if ([ "$QUUX" != 'quux' ]) { warn "sed is not working properly. This may produce unexpected behaviour.\n" } } if ([ -f $HOME/.pkg.conf ]) { . $HOME/.pkg.conf } if ([ ! -d $PDIR ]) { die "$PDIR not found!!" } check_deps () { [ -r $PDIR/$1/dependencies ] || return 0 DEPS=($(cat $PDIR/$1/dependencies)) INSTALL=() for dep in $DEPS; { if ([ "$dep" = "$1" ]) { warn "This package depends on itself. Therefore, I'm considering it borked. Not installing.\n" return 100 } if ([ ! -d $PDIR/$dep ]) { echo -n "$1 depends on $dep. Install dependency? [Y/n] " read if ([ ! "$REPLY" = 'n' ]) { INSTALL+="$dep" } } } if ([ -n "$INSTALL" ]) { for pkg in $INSTALL; { pkg_add "$pkg" } } } pkg_add () { if ([ -d $PDIR/$1 ]) { info "Package '$1' is already installed!\n" return 100 } cd $PDIR || return 255 info "Retrieving package $1...\n" $VCS_CMD $VCS_OPTIONS $VCS_ADD $PKG_ROOT/$1 || return 255 if ([ -f $PDIR/$1/hooks/post-add ]) { info 'Executing post-add hook\n' . $PDIR/$1/hooks/post-add } check_deps "$1" info 'Checking symlinks...\n' cd $PDIR/$1 checklinks $CL_OPTIONS return 0 } pkg_remove () { if ([ ! -d $PDIR/$1 ]) { info "Package '$1' is not installed!\n" return 100 } cd $PDIR/$1 if ([ -r priority ]) { if ([ $(cat priority) -gt 3 ]) { warn "Package '$1' is $(real_priority $(cat priority)). Really remove? [y/N] " read [ "$REPLY" = 'y' ] || return } } if ([ -f $PDIR/$1/hooks/pre-remove ]) { info 'Executing pre-remove hook\n' . $PDIR/$1/hooks/pre-remove } rm -r $PDIR/$1 info "Package removed.\n" } pkg_update () { cd $PDIR/$1 info "Checking package $1..." NEW=$($VCS_CMD $VCS_OPTIONS $VCS_INCOMING) if ([ $? = 0 ]) { info "\rUpdating package $1 to $(echo $NEW | tail -n 1)" $VCS_CMD $VCS_OPTIONS $VCS_UPDATE $VCS_UPDATE_OPTIONS info "\rUpdated package $1 to $(echo $NEW | tail -n 1) \n" checklinks $CL_OPTIONS if ([ -f hooks/post-update ]) { info 'Executing post-update hook\n' . hooks/post-update } } else { info "\r \r" } cd $PDIR } pkg_update_wrapper () { if ([ -n "$1" ]) { pkg_update "$1" } else { cd $PDIR for i in *(/); { pkg_update "$i" } } } pkg_changesrc () { cd $PDIR for i in *(/); { if ([ -f $i/.hg/hgrc ]) { sed -i "s!default = [^:]*://.*\$!default = $1/$i!" $i/.hg/hgrc } } } pkg_list_installed () { =ls -1 $PDIR } pkg_list_available () { if (echo "$PKG_ROOT" | grep "^ssh" &> /dev/null) { ssh -q $(echo "$PKG_ROOT" | sed 's!^ssh://!!' | sed -r 's!^([^/]*)/.*$!\1!') ls -1 $(echo "$PKG_ROOT" | sed 's!^ssh://[^/]*/!!') } } pkg_status () { cd $PDIR/$1 info "Checking $1 status..." check_deps $1 STATUS=$($VCS_CMD $VCS_STATUS) if ([ -n "$STATUS" ]) { info "\rLocally modified in $1:\n" echo "$STATUS" } else { info "\r \r" } } pkg_status_wrapper () { if ([ -n "$1" ]) { pkg_status "$1" } else { cd $PDIR for i in *(/); { pkg_status "$i" } } } real_priority () { case "$1" in 6) echo "essential" ;; 5) echo "important" ;; 4) echo "required" ;; 3) echo "standard" ;; 2) echo "optional" ;; 1) echo "extra" ;; *) echo ;; esac } pkg_info () { cd $PDIR/$1 || return info "Package: " echo "$1" info "Priority: " real_priority $(cat priority 2> /dev/null || echo 0) LOG=$(hg log) info "Version: " echo $LOG | grep -m1 'changeset:' | grep -E -o '[0-9]{1,}:[0-9a-f]*' info "Date: " echo $LOG | grep -m1 'date:' | grep -Eo '[A-Z][a-z]{2}.*' if ([ -r dependencies ]) { info "Depends: " cat dependencies | tr "\n" " " | sed 's/ /, /g' echo } if ([ -r tags ]) { info "Tags: " cat tags | tr "\n" " " | sed 's/ /, /g' echo } if ([ -d hooks ]) { info "Hooks: " ls hooks } info "Repository size: " du -sh .hg | grep -o '.*[KMG]' if ([ -r description ]) { info "Description:\n" cat description } } check_sed case "$1" in add) pkg_add "$2" ;; changeroot) pkg_changesrc "$2" ;; delete) pkg_remove "$2" ;; info) pkg_info "$2" ;; install) pkg_add "$2" ;; list) pkg_list_installed ;; list-all) pkg_list_available ;; remove) pkg_remove "$2" ;; status) pkg_status_wrapper "$2" ;; update) pkg_update_wrapper "$2" ;; esac