]> pd.if.org Git - zpackage/blob - zpm-install
get install upgrades working
[zpackage] / zpm-install
1 #!/bin/sh
2
3 # do one thing and do it well
4 # this program installs packages from a package file
5 # by default, it will install the latest version of each package
6 # found in the file.
7
8 # todo
9
10 # if package specifiers are given as arguments after the package file
11 # it will only install those packages.
12
13 # package specifiers are of the form pkg[-ver[-rel]], i.e the
14 # release can be omitted, and the version-release can be omitted.
15 # examples:
16 # zpm install -f foo-0.1-1.zpm
17 # zpm install -f foo.zpm foo-0.1
18
19 # todo: file tag handling
20
21 # what we need to install a package:
22
23 # recording repo: where we record what we've done
24 # source: where we get the package and files from
25 # install root: really just a prefix, but thought about differently,
26 #    and we might need to do a chroot
27 # package name to install, could be "all" or "all most recent"
28 # but for now, assume only one package in a file?
29
30 # zpm install [options] <package ...>
31
32 pkgver=${ZPMPACKAGEVER:-1.0}
33 pkgrel=${ZPMPACKAGEREL:-1}
34
35 pkgroot=/
36
37 # allocate an install id, perhaps hash package and timestamp
38 # installid=$(echo $(date) $pkglist | zpm hash)
39
40 # extract pre-scripts and run them
41 # get list of paths to install
42 # for each path, if directory, create and set mode
43 # for each path, create leading directories
44 # extract to something like /var/tmp/.hash, with low perms
45 # only atomic if same filesystem, so use .installid.hash in the
46 # install directory
47 # set perms and such
48 # move into place
49 # after all the files, extract post scripts and run them
50
51 # also need to mark package as installing so if it fails part way
52 # through, it can be finished later
53 # probably also want an option to "backup" any packages being upgraded
54 # so it's trivial to downgrade or to revert if the install fails
55
56 # option for "multipackage" just to let the system know that's what you meant
57 # option to take filenames from stdin
58 # parse package, version, release from file if not given
59 # TODO what's the difference between prefix and pkgroot
60 # need an option to not chown the files
61 # option to install but not merge/track
62
63 # options
64 # -R install root, if installing as root, will chroot?
65 # -C no chroot, even if root
66 # -N no pre-scripts
67 # -X no post-scripts
68 # -f source repository file
69 # -d local (recording) repository database
70 # -D don't locally record
71 # -t only files matching tags
72 # -T exclude files matching tags
73
74 chroot=1
75
76 while getopts :R:CNXf:d:Dt:T:u:g: opt; do
77         case $opt in
78                 R) pkgroot="$OPTARG" ;;
79                 C) chroot=0 ;;
80                 f) pkgfile="$OPTARG" ;;
81                 u) user="$OPTARG" ;;
82                 g) group="$OPTARG" ;;
83                 d) ZPMDB="$OPTARG" ;;
84         esac
85 done
86
87 shift $((OPTIND - 1))
88
89 for cf in /etc/zpmrc ~/.zpmrc ./.zpmrc; do
90         test -r $cf && . $cf
91 done
92
93 : ${ZPMDB:=/var/lib/zpm/db.zpm}
94
95 export ZPMDB
96
97 die() {
98         printf 'zpm-install:' 1>&2
99         printf ' %s' $* 1>&2
100         printf '\n' 1>&2
101         exit 1
102 }
103
104 if [ -z "$pkgfile" ]; then
105         # actually, if no pkgfile, get pkgfile from repo
106         # but need to loop over finding package files then
107         # so this program probably needs to be "install from pkgfile"
108         # and a separate one that will loop over a package
109         # spec list and find from repos
110         die "must specify package file" 
111         pkgfile="$package-$pkgver-$pkgrel.zpm"
112 fi
113
114 set -e
115 zpm test -v $pkgfile
116
117 if [ $# -gt 0 ]; then
118         pkglist="$@"
119 else
120         pkglist=$(zpm findpkg $pkgfile)
121 fi
122
123 pathlist() {
124         zpm shell $pkgfile<<EOS
125 select path from packagefiles
126         where package||'-'||version||'-'||release = '$pkg'
127         ;
128 EOS
129 }
130
131 # find a repo file for a given package
132 findrepofor() {
133         false
134 }
135
136 installpkg() (
137         package="$1"
138 )
139
140 pkgname() {
141         # strip off a trailing release
142         nv=$(printf '%s' "$1" | sed -e 's/-[0-9]\+$//')
143         nv=$(printf '%s' "$nv" | sed -e 's/-[0-9][^-]*$//')
144         printf '%s' "$nv"
145 }
146
147 # TODO see if we're already installed
148 # if we are, then bail...
149
150
151 # how to do an upgrade?
152 # paths to add
153 # paths to remove
154 # paths to replace
155
156 newfiles() {
157         nv=$1
158         ov=$2
159 #       printf "zzz checking %s vs %s\n" "$1" "$2"
160 #       printf "zzz checking %s vs %s\n" "$nv" "$ov"
161         zpm shell $ZPMDB<<-EOS
162         select NV.path
163         from packagefiles NV
164         where
165         printf('%s-%s-%s', NV.package, NV.version, NV.release) = '$1'
166         except
167         select OV.path
168         from packagefiles OV
169         where
170         printf('%s-%s-%s', OV.package, OV.version, OV.release) = '$2'
171         ;
172         EOS
173 }
174
175 removedfiles() {
176         zpm shell $ZPMDB<<-EOS
177         select OV.path
178         from packagefiles OV
179         where
180         printf('%s-%s-%s', OV.package, OV.version, OV.release) = '$2'
181         except
182         select NV.path
183         from packagefiles NV
184         where
185         printf('%s-%s-%s', NV.package, NV.version, NV.release) = '$1'
186         ;
187         EOS
188 }
189
190 changedfiles() {
191         # add...
192         zpm shell $ZPMDB<<-EOS
193         select NV.path
194         from packagefiles OV
195         inner join packagefiles NV
196         on OV.path = NV.path
197         where
198         printf('%s-%s-%s', NV.package, NV.version, NV.release) = '$1'
199         and
200         printf('%s-%s-%s', OV.package, OV.version, OV.release) = '$2'
201         and NV.hash != OV.hash
202         ;
203         EOS
204 }
205
206 do_upgrade() {
207         newver=$1
208         oldver=$2
209         
210         set -e
211         echo merging $newver
212         zpm merge $pkgfile $newver
213         zpm pkg $newver status installing
214
215         newct=$(newfiles "$newver" "$oldver" | wc -l)
216         echo newfiles $newct
217
218         if [ $newct -gt 0 ]; then
219         newfiles $newver $oldver
220         { newfiles "$newver" "$oldver"; } | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $nver
221         fi
222
223         ct=$(changedfiles $newver $oldver | wc -l)
224         echo changed $ct
225         if [ $ct -gt 0 ]; then
226                 changedfiles $newver $oldver | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $pkg
227         fi
228
229         ct=$(removedfiles $newver $oldver | wc -l)
230         echo removed $ct
231         if [ $ct -gt 0 ]; then
232                 removedfiles $newver $oldver | xargs rm
233         fi
234
235         zpm pkg $newver status installed
236         zpm pkg $oldver status upgraded
237
238         zpm shell $ZPMDB<<-EOS
239         delete from packages
240         where
241         printf('%s-%s-%s', package, version, release) = '$oldver';
242         EOS
243 }
244
245 for pkg in $pkglist; do
246         pname=$(pkgname $pkg)
247         curver=$(zpm findpkg $ZPMDB $pname)
248         pkg=$(zpm findpkg $pkgfile $pkg)
249         upgrade='n'
250
251         if [ -n "$curver" ]; then
252                 set +e
253                 upgrade=$(zpm vercmp $pkg $curver)
254         fi
255
256         case $upgrade in
257                 0) die 'already installed' $curver;;
258                 1) do_upgrade $pkg $curver ; exit 0 ;;
259                 -1) die 'would be downgrade' $curver '->' $pkg ;;
260                 n) printf 'ok to install %s\n' $pkg ;;
261         esac
262
263         zpm merge $pkgfile $pkg
264         # TODO find scripts marked as pre-install
265         #run_preinstall
266
267         # TODO if this is an upgrade, run pre-upgrade
268         #if [ $upgrade != 'n' ]; then
269         #       run_preupgrade
270         #fi
271
272         # TODO get total size of install so we can do a progress bar
273         #tsize=totalsize
274
275         # add package info to local package db
276         #zpm merge $pkgfile $pkg
277
278         # check for conflicts
279
280         # mark package in localdb as installing
281         # zpm setmark installing $pkg
282         # install all the files for a package
283         # TODO install directories first in order of path length
284         echo installing $pkglist
285         filecount=$(pathlist | wc -l)
286         echo $filecount files
287         #die 'aborting for test'
288         #pathlist
289         pathlist | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $pkg
290
291         # TODO find scripts marked as post-install
292         # TODO if this is an upgrade, run post-upgrade
293
294         # mark as ready for install
295         #zpm setmark ready $pkg
296 done
297
298 #zpm setmark installed $pkglist