]> pd.if.org Git - zpackage/commitdiff
rewrite zpm-install
authorNathan Wagner <nw@hydaspes.if.org>
Sun, 23 Sep 2018 08:12:39 +0000 (08:12 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Mon, 24 Sep 2018 10:40:18 +0000 (10:40 +0000)
zpm-install [changed mode: 0755->0644]

old mode 100755 (executable)
new mode 100644 (file)
index af14c4d..13a8dcf
 #!/bin/sh
 
-# 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
-# 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
+die() {
+       echo $* 1>&2
+       exit 1
+}
 
-chroot=1
+dryrun=0
+runscripts=1
+runconfigure=1
+localdb=/var/lib/zpm/local.db
 
-while getopts :R:CNXf:d:Dt:T:u:g: opt; do
+# zpm-install [-SCn] [ -d localdb ] [ -f pkgfile ] [ -R installroot ] pkgstr ...
+while getopts :f:d:R:nSC opt; do
        case $opt in
-               R) pkgroot="$OPTARG" ;;
-               C) chroot=0 ;;
                f) pkgfile="$OPTARG" ;;
-               u) user="$OPTARG" ;;
-               g) group="$OPTARG" ;;
-               d) ZPMDB="$OPTARG" ;;
+               d) localdb="$OPTARG" ;;
+               R) rootdir="$OPTARG" ;;
+               S) runscripts=0 ;;
+               C) runconfigure=0 ;;
+               n) dryrun=1
        esac
 done
+shift $(( OPTIND - 1))
 
-shift $((OPTIND - 1))
+pkgid=$1
 
-for cf in /etc/zpmrc ~/.zpmrc ./.zpmrc; do
-       test -r $cf && . $cf
-done
+if [ -z "$pkgid" ]; then
+       die "must specify pkgid"
+fi
 
-: ${ZPMDB:=/var/lib/zpm/db.zpm}
-
-export ZPMDB
-
-die() {
-       printf 'zpm-install:' 1>&2
-       printf ' %s' $* 1>&2
-       printf '\n' 1>&2
-       exit 1
-}
+eval "$(zpm parse -E $pkgid)"
 
 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"
+       pkgfile=$ZPM_PACKAGE_FILE
 fi
 
-set -e
-zpm test -v $pkgfile
+# cases C = create ok, R = full package id, F = specified package file
 
-if [ $# -gt 0 ]; then
-       pkglist="$@"
-else
-       pkglist=$(zpm findpkg $pkgfile)
+# immediate error
+# C-- 100 error, must specify something
+# --- 000 error, must specify something
+if [ -z "$release" ] && [ -z "$pkgfile" ]; then
+       die must specify package file or complete package id
 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"
-)
-
-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...
+# --F 001 error, wouldn't know which pkgid to create, could derive from file?
+# C-F 101 error, since package wouldn't exist in file to find
+if [ -z "$release" ]; then
+       die must specify complete package id
+fi
 
+# set file from pkgid
+# CR- 110 set file from pkgid, create if needed
+# -R- 010 set file from pkgid, create in file, error if no file
+if [ -z "$pkgfile" ]; then
+       pkgfile="$pkgid.zpm"
+fi
 
-# how to do an upgrade?
-# paths to add
-# paths to remove
-# paths to replace
+# will now be one of these
+# CRF 111 create package in file given, create file if needed
+# -RF 011 create package in file, error if file doesn't exist
+if [ ! -f "$pkgfile" ]; then
+       if [ $create -eq 1 ]; then
+               zpm init $pkgfile
+       else
+               die $pkgfile does not exist
+       fi
+fi
 
-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
-}
+set -e
 
-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
-}
+if [ "$idempotent" = 1 ]; then
+       idempotent='or ignore'
+fi
 
-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
-}
+package=$(zpm quote "$name")
+pkgver=$(zpm quote "$version")
+pkgrel=$(zpm quote "$release")
 
-do_upgrade() {
-       newver=$1
-       oldver=$2
-       
-       set -e
-       echo merging $newver
-       zpm merge $pkgfile $newver
-       zpm pkg $newver status installing
+ZPMDB=$localdb
+export ZPMDB
 
-       newct=$(newfiles "$newver" "$oldver" | wc -l)
-       echo newfiles $newct
+# check if we're installing something already
+var=$(zpm list -f $localdb -s installing | wc -l)
+if [ $var -ge 0 ]; then
+       die 'already installing'
+fi
 
-       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 [ -n "$rootdir" ];
+       ZPM_ROOT_DIR="$rootdir"
+       export ZPM_ROOT_DIR
+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
+# TODO mark already installed packages as updating?
+for pkgstr in "$@"; do
+       pkgid=$(zpm findpkg -f $pkgfile $pkgstr)
+       if [ $? -ne 0 ]; then
+               # TODO log
+               die "can't find package $pkgstr in $pkgfile"
        fi
 
-       ct=$(removedfiles $newver $oldver | wc -l)
-       echo removed $ct
-       if [ $ct -gt 0 ]; then
-               removedfiles $newver $oldver | xargs rm
+       curstatus=$(zpm pkg $pkgid status)
+       if [ "$curstatus" = 'installed' ]; then
+               die "$pkgid already installed"
        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
-}
+       eval $(zpm parse -E $pkgid)
 
-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
+       current=$(zpm list -s installed "$package")
+       
+       if [ $runscripts -gt 0 ]; then
+               zpm runscript -f $packagefile -p pre-install $pkgid $current
+               if [ $? -ne 0 ]; then
+                       # TODO log
+                       die "pre-install script for $pkgid failed"
                fi
-       done
+       fi
 
-       {
-       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
+       # only merge if localdb and pkgfile are different
+       if [ "$pkgfile" != "$ZPMDB" ]; then
+               zpm merge -f $pkgfile -s installing $pkgid
+               if [ $? -ne 0 ]; then
+                       # TODO log
+                       die "merging $pkgid failed"
                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 $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
-       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
+       zpm pkgfiles -f $pkgfile $pkgid
+       if [ $runscripts -gt 0 ]; then
+               zpm runscript -f $pkgfile -p post-install $pkgid $current
+       fi
+       # need a way to update multiple statuses all in one
+       # zpm pkgstatus $pkgid installed $pkgid updated
+       zpm pkg $pkgid status installed
+       if [ $runconfigure -gt 0 ]; then
+               zpm runscript -f $pkgfile -p configure $pkgid $current
+       fi
 done
-
-#zpm setmark installed $pkglist