364 lines
9.4 KiB
Bash
Executable File
364 lines
9.4 KiB
Bash
Executable File
#!/bin/sh -e
|
|
|
|
[ -n "$2" ] || { \
|
|
echo "
|
|
usage: $(basename $0) [--bootstrap=<path>] <command> <package> [<version>]
|
|
|
|
options:
|
|
--bootstrap=<path>
|
|
use <path> as the lowest layer in the overlay stack.
|
|
|
|
commands:
|
|
pl, pull
|
|
acquire and patch package source code.
|
|
|
|
cf, config, configure
|
|
configure the package.
|
|
|
|
mk, make
|
|
build the package.
|
|
|
|
in, inst, install
|
|
install the package to its overlay.
|
|
|
|
un, uninst, uninstall
|
|
remove the package overlay.
|
|
|
|
ad, add
|
|
pull, configure, make, and install the package to its overlay.
|
|
|
|
rm, remove
|
|
delete the package version's overlay, source code, and signature.
|
|
|
|
up [additional lmr flags]
|
|
symlink the package into the system root with lmr, passing along flags.
|
|
|
|
dn, down
|
|
remove the package symlinks from the system root with lmr.
|
|
|
|
do <cmd>
|
|
chroot into the package filesystem overlay and run <cmd>.
|
|
|
|
mt, mount <path>
|
|
mounts the package filesystem overlay at the given path.
|
|
|
|
um, umount <path>
|
|
unmounts the package filesystem overlay at the given path.
|
|
|
|
vr, ver, version
|
|
print the default version for the given package.
|
|
|
|
bl, built
|
|
list all built versions for the given package.
|
|
|
|
dp, deps, dependencies
|
|
list package dependencies and their inferred versions.
|
|
" && exit 0; }
|
|
|
|
# if this is running on an interactive terminal (as opposed to in a cron job,
|
|
# for example), if tput is installed, and if tput knows some color codes, then
|
|
# set the color values.
|
|
if [ -t 1 ] && [ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]; then
|
|
_clr="$(tput sgr0)"
|
|
_blu="$(tput setaf 6)"
|
|
_ylw="$(tput setaf 3)"
|
|
_red="$(tput setaf 1)"
|
|
fi
|
|
|
|
log() { echo "$_blu[LOG]$_clr $@"; }
|
|
wrn() { echo "$_ylw[WRN]$_clr $@" >&2; }
|
|
err() { echo "$_red[ERR]$_clr $@" >&2; exit 1; }
|
|
|
|
export LIXPREFIX="${LIXPREFIX:-${0%/bin/lix}}"
|
|
export LIXROOT="$(dirname "$(readlink -f "$0")")"
|
|
export HOWROOT="$(dirname "$(readlink -f "$(which how)")")"
|
|
export SRCREPO="${SRCREPO:-$LIXPREFIX/var/src}"
|
|
export SRCROOT="${SRCROOT:-${LIXROOT%/lix}/src}"
|
|
|
|
export cmd="$1"
|
|
export OP="$cmd"
|
|
export FAKEROOT=""
|
|
export CLEANUPFAKEROOT=""
|
|
export SUCCESS=""
|
|
|
|
# these are lowercase because they will be used in 'how' scripts.
|
|
export name
|
|
export version
|
|
|
|
[ -d "$SRCROOT" ] || err "$SRCROOT is not a directory!"
|
|
[ -d "$SRCREPO" ] || err "$SRCREPO is not a directory!"
|
|
[ -d "$LIXROOT" ] || err "$LIXROOT is not a directory!"
|
|
|
|
. "$LIXROOT/lib/pkg.sh"
|
|
. "$LIXROOT/lib/built.sh"
|
|
. "$LIXROOT/lib/dependencies.sh"
|
|
. "$LIXROOT/lib/lowerlayers.sh"
|
|
. "$LIXROOT/lib/guessver.sh"
|
|
|
|
# process command options
|
|
if [ "${cmd#--bootstrap}" != "$cmd" ]; then
|
|
if [ "$cmd" = "--bootstrap" ]; then
|
|
shift
|
|
export BSLAYER="$1"
|
|
else
|
|
export BSLAYER="$(echo "$cmd" | cut -d'=' -f2)"
|
|
fi
|
|
[ -d "$BSLAYER" ] || err "$BSLAYER is not a directory!"
|
|
|
|
shift
|
|
cmd="$1"
|
|
fi
|
|
|
|
case "$cmd" in
|
|
do)
|
|
docmd="$2"
|
|
shift
|
|
;;
|
|
|
|
mt|mnt|mount|um|umt|umnt|umount)
|
|
FAKEROOT="$2"
|
|
shift
|
|
;;
|
|
|
|
up)
|
|
while [ "${2#-}" != "$2" ]; do
|
|
upflags="$upflags $2"
|
|
shift
|
|
done
|
|
;;
|
|
|
|
sh|shell)
|
|
# maybe this should be its own utility.
|
|
[ "$1" ] || err "missing 'layer name' argument!"
|
|
[ -e "$2" ] || err "no such file as '$2'."
|
|
|
|
[ "$1" = "${1#lix/}" ] \
|
|
|| wrn "you are using the 'lix' namespace! this can be dangerous..."
|
|
|
|
layers="$(lowerlayers "$(dependencies "$(cat "$2")")" "$BSLAYER")"
|
|
lyr mk "$1"
|
|
|
|
chin "$(lyr up "$layers" "$1")" "${3:-sh}"
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
# get required positional arguments
|
|
name="$2"
|
|
|
|
[ -n "$3" ] \
|
|
&& version="$3" \
|
|
|| version="$(guessver "$name")"
|
|
|
|
[ -n "$version" ] || err "could not determine version for '$name'."
|
|
|
|
cleanup() {
|
|
[ -z "$PKGHOW" ] || umount "$PKGHOW" || true
|
|
[ -z "$FAKEROOT" ] || unmountpkg "$FAKEROOT" || true
|
|
[ -z "$CLEANUPFAKEROOT" ] || rmdir "$FAKEROOT" || true
|
|
[ -n "$SUCCESS" ] || err "$name $version '$OP' failed"
|
|
}
|
|
trap cleanup EXIT INT HUP
|
|
|
|
beginmsg() {
|
|
OP="$1"
|
|
log "starting '$OP' for $name $version"
|
|
}
|
|
|
|
successmsg() { log "completed '$OP' for $name $version"; }
|
|
|
|
expectsrc() {
|
|
[ -d "$(lyr upperdir lix/$name/$version/src)" ] \
|
|
|| err "'src' layer missing! did you run 'lix pull $name $version' first?"
|
|
}
|
|
|
|
pullcmd() {
|
|
beginmsg "pull"
|
|
|
|
# if `how` has specific instructions for this package but there is no
|
|
# `src` package, then this must be a "bundle" package or something.
|
|
# just create an empty source directory and call it a day. (but please
|
|
# consider finding a more elegant way to handle bundles. there must
|
|
# be one, but it will probably require a rewrite. design problems
|
|
# usually arise out of fundamentally flawed models. with the right
|
|
# model, a _clean_ solution becomes trivial.)
|
|
if { how $name $version | grep -q ':' ; } \
|
|
&& [ ! -d "$SRCROOT/pkg/$name" ]
|
|
then
|
|
wrn "no 'src' entry. assuming this is a 'sourceless' package..."
|
|
mkdir -p "$SRCREPO/$name/$version" # ew...
|
|
elif [ -e "$SRCREPO/$name/$version" ]; then
|
|
wrn "$SRCREPO/$name/$version already exists. skipping remote pull."
|
|
else
|
|
src "$name" "$version";
|
|
fi
|
|
|
|
if [ -d "$(lyr upperdir lix/$name/$version/src)" ]; then
|
|
wrn "source code upper layer already exists! skipping patch.sh."
|
|
else
|
|
loadpkgdeps
|
|
|
|
log "looking for a patch.sh from 'how' to run in $name's overlay."
|
|
pkgdo ". ../how/env.sh; ../how/patch.sh"
|
|
fi
|
|
|
|
successmsg
|
|
}
|
|
|
|
confcmd() {
|
|
beginmsg "configure"
|
|
|
|
pkgdo ". ../how/env.sh; ../how/conf.sh"
|
|
|
|
successmsg
|
|
}
|
|
|
|
makecmd() {
|
|
beginmsg "make"
|
|
|
|
pkgdo ". ../how/env.sh; ../how/make.sh"
|
|
|
|
# compile "built-with" list
|
|
mkdir -p -- "$LIXROOT/built-with/${name}"
|
|
echo "$deps" > "$LIXROOT/built-with/${name}/$version"
|
|
|
|
successmsg
|
|
}
|
|
|
|
instcmd() {
|
|
beginmsg "install"
|
|
|
|
upperdir="$(lyr upperdir lix/$name/$version)"
|
|
|
|
# clean out previous installation and make backup
|
|
if [ -d "$upperdir/fs" ]; then
|
|
log "making backup of package's existing 'fs' layer..."
|
|
|
|
fsbak="$upperdir/bak/$(basename "$(mktemp -u)")"
|
|
mkdir -p "$fsbak"
|
|
cp -a "$upperdir/fs/." "$fsbak/"
|
|
fi
|
|
|
|
# install. restore backup on failure. delete backup on success.
|
|
if { pkgdo ". ../how/env.sh; ../how/inst.sh"; }; then
|
|
log "removing backup of package's previous 'fs' layer..."
|
|
rm -fr "$fsbak"
|
|
rmdir "$(dirname "$fsbak")" 2> /dev/null || true
|
|
else
|
|
log "restoring backup of package's previous 'fs' layer..."
|
|
rm -fr "$upperdir/fs"
|
|
mv "$fsbak" "$upperdir/fs"
|
|
rmdir "$(dirname "$fsbak")" 2> /dev/null || true
|
|
exit 1
|
|
fi
|
|
|
|
successmsg
|
|
}
|
|
|
|
# commands can be invoked with their full name, with a two-letter short form
|
|
# composed of the first letter and the last consonant (e.g., 'mk' for 'make'),
|
|
# and with an assortment of one-off abbreviations that just make sense for each
|
|
# command. e.g., 'rm' for 'remove'.
|
|
|
|
case "$cmd" in
|
|
pl|pull) pullcmd ;;
|
|
|
|
cf|cr|cg|conf|config|configure)
|
|
expectsrc
|
|
confcmd
|
|
;;
|
|
|
|
mk|make)
|
|
expectsrc
|
|
makecmd
|
|
;;
|
|
|
|
in|il|inst|install)
|
|
expectsrc
|
|
instcmd
|
|
;;
|
|
|
|
ad|add)
|
|
pullcmd
|
|
|
|
expectsrc
|
|
confcmd
|
|
makecmd
|
|
instcmd
|
|
;;
|
|
|
|
cl|cn|clean)
|
|
rm -fr "$(lyr upperdir lix/$name/$version)/src" 2> /dev/null || true
|
|
rm -fr "$(lyr upperdir lix/$name/$version)/build" 2> /dev/null || true
|
|
;;
|
|
|
|
rm|rv|remove) lyr rm "lix/$name/$version" ;;
|
|
|
|
pg|purge)
|
|
rm -fr $SRCREPO/$name/$version
|
|
lyr rm "lix/$name/$version"
|
|
;;
|
|
|
|
up) lmr -s $upflags "$(lyr upperdir lix/$name/$version/fs)" / ;;
|
|
|
|
dn|down) lmr -s -u "$(lyr upperdir lix/$name/$version/fs)" / ;;
|
|
|
|
do)
|
|
expectsrc
|
|
beginmsg "do"
|
|
pkgdo ". ../how/env.sh; $docmd"
|
|
successmsg
|
|
;;
|
|
|
|
mt|mnt|mount)
|
|
beginmsg "mount"
|
|
[ -d "$mntpth" ] || err "no such directory: $mntpth"
|
|
|
|
expectsrc
|
|
|
|
mountpkg "$mntpth" >/dev/null \
|
|
|| err "failed to mount $name $version overlay."
|
|
|
|
successmsg
|
|
;;
|
|
|
|
um|ut|umt|umnt|umount|unmount)
|
|
unmountpkg "$mntpth" \
|
|
&& log "unmounted $name $version overlay at $mntpth" \
|
|
|| err "error unmounting $name $version overlay at $mntpth"
|
|
;;
|
|
|
|
vr|vn|ver|version) echo "$version" ;;
|
|
|
|
bl|built) built "$name" ;;
|
|
|
|
dp|deps|dependencies)
|
|
loadpkgdeps
|
|
|
|
cols=0
|
|
cols="$(echo "$PKGDEPS" | while read line; do
|
|
newcols="$(echo "$line" | awk '{ print $1 }' | wc -c)"
|
|
[ "$newcols" -ge "$cols" ] || continue
|
|
cols="$newcols"
|
|
echo "$cols"
|
|
done | tail -n1)"
|
|
|
|
# get a list of dependencies with resolved version numbers. if no
|
|
# version number could be resolved, the "version" column will be empty
|
|
# and a warning will be printed.
|
|
echo "$PKGDEPS" | while read line; do
|
|
[ "$line" ] || continue;
|
|
dep="$(echo "$line" | awk '{ print $1 }')"
|
|
depver="$(echo "$line" | awk '{ print $2 }')"
|
|
[ "$depver" ] || wrn "could not resolve dependency '$dep'!"
|
|
|
|
# pad-space each dependency name so the versions align in a column.
|
|
printf "%-${cols}s %s\n" "$dep" "$depver"
|
|
done
|
|
;;
|
|
|
|
*) err "unrecognized command '$cmd'";;
|
|
esac
|
|
|
|
SUCCESS="yes"
|