#!/bin/sh
-#package=${1:-$ZPMPACKAGE}
+# do one thing and do it well
+# this program installs packages from a package file
+# by default, it will install the latest version of each package
+# found in the file.
+
+# todo
+
+# if package specifiers are given as arguments after the package file
+# it will only install those packages.
+
+# package specifiers are of the form pkg[-ver[-rel]], i.e the
+# release can be omitted, and the version-release can be omitted.
+# examples:
+# zpm install -f foo-0.1-1.zpm
+# zpm install -f foo.zpm foo-0.1
+
+# todo: file tag handling
+
+# what we need to install a package:
+
+# recording repo: where we record what we've done
+# source: where we get the package and files from
+# install root: really just a prefix, but thought about differently,
+# and we might need to do a chroot
+# package name to install, could be "all" or "all most recent"
+# but for now, assume only one package in a file?
+
+# zpm install [options] <package ...>
+
pkgver=${ZPMPACKAGEVER:-1.0}
pkgrel=${ZPMPACKAGEREL:-1}
# TODO what's the difference between prefix and pkgroot
# need an option to not chown the files
# option to install but not merge/track
-while getopts :f:v:r:d:a:u:l:p:b:P:R: opt; do
+
+# options
+# -R install root, if installing as root, will chroot?
+# -C no chroot, even if root
+# -N no pre-scripts
+# -X no post-scripts
+# -f source repository file
+# -d local (recording) repository database
+# -D don't locally record
+# -t only files matching tags
+# -T exclude files matching tags
+
+chroot=1
+
+while getopts :R:CNXf:d:Dt:T:u:g: opt; do
case $opt in
R) pkgroot="$OPTARG" ;;
+ C) chroot=0 ;;
f) pkgfile="$OPTARG" ;;
- v) pkgver="$OPTARG" ;;
- r) pkgrel="$OPTARG" ;;
- d) description="$OPTARG" ;;
- a) arch="$OPTARG" ;;
- u) url="$OPTARG" ;;
- l) licenses="$OPTARG" ;;
- p) packager="$OPTARG" ;;
- b) builddate="$OPTARG" ;;
- P) prefix="$OPTARG" ;;
+ u) user="$OPTARG" ;;
+ g) group="$OPTARG" ;;
+ d) ZPMDB="$OPTARG" ;;
esac
done
+
shift $((OPTIND - 1))
+for cf in /etc/zpmrc ~/.zpmrc ./.zpmrc; do
+ test -r $cf && . $cf
+done
+
+: ${ZPMDB:=/var/lib/zpm/db.zpm}
+
+export ZPMDB
+
die() {
- echo $* 1>&2
+ printf 'zpm-install:' 1>&2
+ printf ' %s' $* 1>&2
+ printf '\n' 1>&2
exit 1
}
EOS
}
+# find a repo file for a given package
+findrepofor() {
+ false
+}
+
+installpkg() (
+ package="$1"
+)
+
+pkgname() {
+ # strip off a trailing release
+ nv=$(printf '%s' "$1" | sed -e 's/-[0-9]\+$//')
+ nv=$(printf '%s' "$nv" | sed -e 's/-[0-9][^-]*$//')
+ printf '%s' "$nv"
+}
+
+# TODO see if we're already installed
+# if we are, then bail...
+
+
+# how to do an upgrade?
+# paths to add
+# paths to remove
+# paths to replace
+
+newfiles() {
+ nv=$1
+ ov=$2
+# printf "zzz checking %s vs %s\n" "$1" "$2"
+# printf "zzz checking %s vs %s\n" "$nv" "$ov"
+ zpm shell $ZPMDB<<-EOS
+ select NV.path
+ from packagefiles NV
+ where
+ printf('%s-%s-%s', NV.package, NV.version, NV.release) = '$1'
+ except
+ select OV.path
+ from packagefiles OV
+ where
+ printf('%s-%s-%s', OV.package, OV.version, OV.release) = '$2'
+ ;
+ EOS
+}
+
+removedfiles() {
+ zpm shell $ZPMDB<<-EOS
+ select OV.path
+ from packagefiles OV
+ where
+ printf('%s-%s-%s', OV.package, OV.version, OV.release) = '$2'
+ except
+ select NV.path
+ from packagefiles NV
+ where
+ printf('%s-%s-%s', NV.package, NV.version, NV.release) = '$1'
+ ;
+ EOS
+}
+
+changedfiles() {
+ # add...
+ zpm shell $ZPMDB<<-EOS
+ select NV.path
+ from packagefiles OV
+ inner join packagefiles NV
+ on OV.path = NV.path
+ where
+ printf('%s-%s-%s', NV.package, NV.version, NV.release) = '$1'
+ and
+ printf('%s-%s-%s', OV.package, OV.version, OV.release) = '$2'
+ and NV.hash != OV.hash
+ ;
+ EOS
+}
+
+do_upgrade() {
+ newver=$1
+ oldver=$2
+
+ set -e
+ echo merging $newver
+ zpm merge $pkgfile $newver
+ zpm pkg $newver status installing
+
+ newct=$(newfiles "$newver" "$oldver" | wc -l)
+ echo newfiles $newct
+
+ if [ $newct -gt 0 ]; then
+ newfiles $newver $oldver
+ { newfiles "$newver" "$oldver"; } | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $nver
+ fi
+
+ ct=$(changedfiles $newver $oldver | wc -l)
+ echo changed $ct
+ if [ $ct -gt 0 ]; then
+ changedfiles $newver $oldver | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $pkg
+ fi
+
+ ct=$(removedfiles $newver $oldver | wc -l)
+ echo removed $ct
+ if [ $ct -gt 0 ]; then
+ removedfiles $newver $oldver | xargs rm
+ fi
+
+ zpm pkg $newver status installed
+ zpm pkg $oldver status upgraded
+
+ zpm shell $ZPMDB<<-EOS
+ delete from packages
+ where
+ printf('%s-%s-%s', package, version, release) = '$oldver';
+ EOS
+}
+
+conflicts() {
+ echo conflict check $pkg $pkgfile
+ #newver=$1
+ {
+ zpm shell $pkgfile<<-EOS
+ .separator " "
+ select hash,path from packagefiles
+ where package||'-'||version||'-'||release = '$pkg'
+ and filetype = 'r'
+ ;
+ EOS
+ } | while read hash path; do
+ rpath=$pkgroot$path
+ if [ -f $rpath ]; then
+ ihash=$(zpm hash $rpath)
+ if [ $ihash != $hash ]; then
+ die $path already exists
+ fi
+ elif [ -d $rpath ]; then
+ die $path already exists
+ fi
+ done
+
+ {
+ zpm shell $pkgfile<<-EOS
+ .separator " "
+ select path from packagefiles
+ where package||'-'||version||'-'||release = '$pkg'
+ and filetype = 'd'
+ ;
+ EOS
+ } | while read hash path; do
+ rpath=$pkgroot$path
+ if [ -f $rpath ]; then
+ die $path already exists
+ elif [ -d $rpath ]; then
+ die $path already exists
+ elif [ -e $rpath ]; then
+ die $path already exists
+ fi
+ done
+}
+
for pkg in $pkglist; do
+ pname=$(pkgname $pkg)
+ curver=$(zpm findpkg $ZPMDB $pname)
+ pkg=$(zpm findpkg $pkgfile $pkg)
+ upgrade='n'
+
+ if [ -n "$curver" ]; then
+ set +e
+ upgrade=$(zpm vercmp $pkg $curver)
+ fi
+
+ case $upgrade in
+ 0) die 'already installed' $curver;;
+ 1) do_upgrade $pkg $curver ; exit 0 ;;
+ -1) die 'would be downgrade' $curver '->' $pkg ;;
+ n) printf 'ok to install %s\n' $pkg ;;
+ esac
+
+ zpm merge $pkgfile $pkg
# TODO find scripts marked as pre-install
+ #run_preinstall
+
# TODO if this is an upgrade, run pre-upgrade
+ #if [ $upgrade != 'n' ]; then
+ # run_preupgrade
+ #fi
# TODO get total size of install so we can do a progress bar
+ #tsize=totalsize
# add package info to local package db
- # zpm merge -L -f $pkgfile $pkg
+ #zpm merge $pkgfile $pkg
+
# check for conflicts
+
+ conflicts $pkgroot $pkg
+
# mark package in localdb as installing
# zpm setmark installing $pkg
# install all the files for a package
# TODO install directories first in order of path length
- pathlist | xargs zpm ipkgfile -R "$pkgroot" -f $pkgfile -- $pkg
+ echo installing $pkglist
+ filecount=$(pathlist | wc -l)
+ echo $filecount files
+ #die 'aborting for test'
+ #pathlist
+ zpm pkg $pkg status installing
+ pathlist | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $pkg
# TODO find scripts marked as post-install
# TODO if this is an upgrade, run post-upgrade
# mark as ready for install
+ zpm pkg $pkg status installed
#zpm setmark ready $pkg
done