#!/bin/sh
-package=${1:-$ZPMPACKAGE}
-shift
+# 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}
pkgroot=/
# allocate an install id, perhaps hash package and timestamp
+# installid=$(echo $(date) $pkglist | zpm hash)
+
# extract pre-scripts and run them
# get list of paths to install
# for each path, if directory, create and set mode
# move into place
# after all the files, extract post scripts and run them
+# also need to mark package as installing so if it fails part way
+# through, it can be finished later
+# probably also want an option to "backup" any packages being upgraded
+# so it's trivial to downgrade or to revert if the install fails
+
# option for "multipackage" just to let the system know that's what you meant
# option to take filenames from stdin
# parse package, version, release from file if not given
-while getopts :f:v:r:d:a:u:l:p:b:P: opt; do
+# TODO what's the difference between prefix and pkgroot
+# need an option to not chown the files
+# option to install but not merge/track
+
+# 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
-set -e
+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() {
+ printf 'zpm-install:' 1>&2
+ printf ' %s' $* 1>&2
+ printf '\n' 1>&2
+ exit 1
+}
+
if [ -z "$pkgfile" ]; then
+ # actually, if no pkgfile, get pkgfile from repo
+ # but need to loop over finding package files then
+ # so this program probably needs to be "install from pkgfile"
+ # and a separate one that will loop over a package
+ # spec list and find from repos
+ die "must specify package file"
pkgfile="$package-$pkgver-$pkgrel.zpm"
fi
-appid=$(sqlite3 $pkgfile 'pragma application_id;' | ( echo obase = 16; cat - ) | bc)
-if [ "$appid" != "5A504442" ]; then
- echo $pkgfile does not appear to be a zpm package file
- exit 1
+set -e
+zpm test -v $pkgfile
+
+if [ $# -gt 0 ]; then
+ pkglist="$@"
+else
+ pkglist=$(zpm findpkg $pkgfile)
fi
-# check if package exists
-# run preinstall or preupgrade stage, in chroot
-
-# add package info and mark installing to local package database
-# each path: add to local db, extract, set mode/owner/mtime etc.
-# mark install done in local database
-
-for path in $*; do
- mtime=$(stat -c '%Y' $path)
- uid=$(stat -c '%u' $path)
- gid=$(stat -c '%g' $path)
- username=$(stat -c '%U' $path)
- groupname=$(stat -c '%G' $path)
- mode=$(stat -c '%a' $path)
-
- # strip off leading slashes
- rpath=$(echo "$path" | sed -e 's|^/*||')
- # and a leading ./
- rpath=${rpath#./}
- rpath=$(echo "$rpath" | sed -e 's|^/*||')
-
- if [ -z "$rpath" ] || [ "$rpath" = '.' ]; then
- continue
- fi
+pathlist() {
+ zpm shell $pkgfile<<EOS
+select path from packagefiles
+ where package||'-'||version||'-'||release = '$pkg'
+ ;
+EOS
+}
+
+# find a repo file for a given package
+findrepofor() {
+ false
+}
+
+installpkg() (
+ package="$1"
+)
- if [ ! -z "$prefix" ]; then
- # trailing slashes on prefix
- prefix=$(echo "$prefix" | sed -e 's|/*$||')
- rpath="$prefix/$rpath"
+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() {
+ #zpm merge $pkgfile $newver
+
+ # add...
+ 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 merge $pkgfile $newver
+
+ 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
+
+ echo newfiles
+ newfiles $newver $oldver | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $nver
+
+ echo changed
+ changedfiles $newver $oldver | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $pkg
+
+ echo removed
+ removedfiles $newver $oldver | xargs rm
+
+ 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
+}
+
+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
- if [ -f "$path" ]; then
+ 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
- hash=$(./zpm-addfile $pkgfile $path)
+ zpm merge $pkgfile $pkg
+ # TODO find scripts marked as pre-install
+ #run_preinstall
-#if [ -z "$hash" ]; then continue; fi
+ # TODO if this is an upgrade, run pre-upgrade
+ #if [ $upgrade != 'n' ]; then
+ # run_preupgrade
+ #fi
-# TODO mtime, mode
-sqlite3 $pkgfile <<EOS
-PRAGMA foreign_keys = ON;
-insert or replace into packagefiles (package,version,release,path,mode,mtime,username,groupname,hash)
-values ('$package', '$pkgver', $pkgrel, '$rpath', '$mode',$mtime, '$username','$groupname','$hash')
-;
-EOS
-elif [ -d "$path" ]; then
-sqlite3 $pkgfile <<EOS
-PRAGMA foreign_keys = ON;
-insert or replace into packagefiles (package,version,release,path,mode,mtime,username,groupname)
-values ('$package', '$pkgver', $pkgrel, '$rpath', '$mode',$mtime, '$username','$groupname')
-;
-EOS
-elif [ -l "$path" ]; then
- target=$(readlink $path)
-sqlite3 $pkgfile <<EOS
-PRAGMA foreign_keys = ON;
-insert or replace into packagefiles (package,version,release,path,mode,mtime,username,groupname,target)
-values ('$package', '$pkgver', $pkgrel, '$rpath', '$mode',$mtime, '$username','$groupname','$target')
-;
-EOS
-fi
-#printf "%s %s%s\n" $path $rpath ${target:+" -> $target"}
-printf "%s\n" $path
+ # TODO get total size of install so we can do a progress bar
+ #tsize=totalsize
+
+ # add package info to local package db
+ #zpm merge $pkgfile $pkg
+
+ # check for conflicts
+
+ # 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
+ echo installing $pkglist
+ filecount=$(pathlist | wc -l)
+ echo $filecount files
+ #die 'aborting for test'
+ #pathlist
+ 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 setmark ready $pkg
done
+
+#zpm setmark installed $pkglist