]> pd.if.org Git - zpackage/blob - zpm-install
zpm-install work on upgrades
[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         #zpm merge $pkgfile $newver
158
159         # add...
160         zpm shell $ZPMDB<<-EOS
161         select NV.path
162         from packagefiles NV
163         where
164         printf('%s-%s-%s', NV.package, NV.version, NV.release) = '$1'
165         except
166         select OV.path
167         from packagefiles OV
168         where
169         printf('%s-%s-%s', OV.package, OV.version, OV.release) = '$2'
170         ;
171         EOS
172 }
173
174 removedfiles() {
175         #zpm merge $pkgfile $newver
176
177         zpm shell $ZPMDB<<-EOS
178         select OV.path
179         from packagefiles OV
180         where
181         printf('%s-%s-%s', OV.package, OV.version, OV.release) = '$2'
182         except
183         select NV.path
184         from packagefiles NV
185         where
186         printf('%s-%s-%s', NV.package, NV.version, NV.release) = '$1'
187         ;
188         EOS
189 }
190
191 changedfiles() {
192         # add...
193         zpm shell $ZPMDB<<-EOS
194         select NV.path
195         from packagefiles OV
196         inner join packagefiles NV
197         on OV.path = NV.path
198         where
199         printf('%s-%s-%s', NV.package, NV.version, NV.release) = '$1'
200         and
201         printf('%s-%s-%s', OV.package, OV.version, OV.release) = '$2'
202         and NV.hash != OV.hash
203         ;
204         EOS
205 }
206
207 do_upgrade() {
208         newver=$1
209         oldver=$2
210         
211         set -e
212         echo merging $newver
213         zpm merge $pkgfile $newver
214
215         echo newfiles
216         newfiles $newver $oldver | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $nver
217
218         echo changed
219         changedfiles $newver $oldver | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $pkg
220
221         echo removed
222         removedfiles $newver $oldver | xargs rm
223
224         zpm pkg $newver status installed
225         zpm pkg $oldver status upgraded
226
227         zpm shell $ZPMDB<<-EOS
228         delete from packages
229         where
230         printf('%s-%s-%s', package, version, release) = '$oldver';
231         EOS
232 }
233
234 for pkg in $pkglist; do
235         pname=$(pkgname $pkg)
236         curver=$(zpm findpkg $ZPMDB $pname)
237         pkg=$(zpm findpkg $pkgfile $pkg)
238         upgrade='n'
239
240         if [ -n "$curver" ]; then
241                 set +e
242                 upgrade=$(zpm vercmp $pkg $curver)
243         fi
244
245         case $upgrade in
246                 0) die 'already installed' $curver;;
247                 1) do_upgrade $pkg $curver ; exit 0 ;;
248                 -1) die 'would be downgrade' $curver '->' $pkg ;;
249                 n) printf 'ok to install %s\n' $pkg ;;
250         esac
251
252         zpm merge $pkgfile $pkg
253         # TODO find scripts marked as pre-install
254         #run_preinstall
255
256         # TODO if this is an upgrade, run pre-upgrade
257         #if [ $upgrade != 'n' ]; then
258         #       run_preupgrade
259         #fi
260
261         # TODO get total size of install so we can do a progress bar
262         #tsize=totalsize
263
264         # add package info to local package db
265         #zpm merge $pkgfile $pkg
266
267         # check for conflicts
268
269         # mark package in localdb as installing
270         # zpm setmark installing $pkg
271         # install all the files for a package
272         # TODO install directories first in order of path length
273         echo installing $pkglist
274         filecount=$(pathlist | wc -l)
275         echo $filecount files
276         #die 'aborting for test'
277         #pathlist
278         pathlist | xargs zpm ipkgfile ${user+-u $user} ${group+-g $group} -R "$pkgroot" -f $pkgfile -- $pkg
279
280         # TODO find scripts marked as post-install
281         # TODO if this is an upgrade, run post-upgrade
282
283         # mark as ready for install
284         #zpm setmark ready $pkg
285 done
286
287 #zpm setmark installed $pkglist