]> pd.if.org Git - zpackage/blobdiff - zpm-install
get install upgrades working
[zpackage] / zpm-install
index e722bf321f1ea85b4be8b75427c86d47aeaa6449..40e5a4353bcba237d7e805c2dcd95a899b016a2a 100755 (executable)
 #!/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
+# for each path, create leading directories
+# extract to something like /var/tmp/.hash, with low perms
+# only atomic if same filesystem, so use .installid.hash in the
+# install directory
+# set perms and such
+# 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
+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"
+)
+
+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
 
-       if [ ! -z "$prefix" ]; then
-               # trailing slashes on prefix
-               prefix=$(echo "$prefix" | sed -e 's|/*$||')
-               rpath="$prefix/$rpath"
+       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
 
-       if [ -f "$path" ]; then
+       ct=$(removedfiles $newver $oldver | wc -l)
+       echo removed $ct
+       if [ $ct -gt 0 ]; then
+               removedfiles $newver $oldver | xargs rm
+       fi
 
-               hash=$(./zpm-addfile $pkgfile $path)
+       zpm pkg $newver status installed
+       zpm pkg $oldver status upgraded
 
-#if [ -z "$hash" ]; then continue; fi
+       zpm shell $ZPMDB<<-EOS
+       delete from packages
+       where
+       printf('%s-%s-%s', package, version, release) = '$oldver';
+       EOS
+}
 
-# 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
+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 $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