Install a moduli(5) manual page.
[dragonfly.git] / contrib / bsdinstaller-1.1.6 / src / backend / lua / lib / package.lua
1 -- lib/package.lua
2 -- $Id: package.lua,v 1.13 2005/04/04 18:59:20 cpressey Exp $
3 -- Installer package functions written in Lua.
4
5 -- BEGIN lib/package.lua --
6
7 local POSIX = require("posix")
8 local FileName = require("filename")
9 local App = require("app")
10
11 require "cmdchain"
12
13 --[[---------]]--
14 --[[ Package ]]--
15 --[[---------]]--
16
17 -- This 'class' currently only contains static global methods
18 -- for dealing with packages.  There is no 'package object.'
19
20 Package = {}
21
22 --
23 -- Determine whether a package is installed on a HDD.
24 --
25 Package.exists = function(base, pkg_name)
26         return FileName.is_dir(
27             App.expand("${root}${base}var/db/pkg/${pkg_name}", {
28                 base = base,
29                 pkg_name = pkg_name
30             })
31         )
32 end
33
34 Package.list_all = function(base)
35         local i, filename, list
36         local dir = POSIX.dir(
37             App.expand("${root}${base}var/db/pkg", {
38                 base = base
39             })
40         )
41
42         list = {}
43         for i, filename in ipairs(dir) do
44                 if filename ~= "." and filename ~= ".." then
45                         table.insert(list, filename)
46                 end
47         end
48
49         return list
50 end
51
52 --
53 -- Methods which construct command-chains.
54 --
55
56 --
57 -- Delete all packages from a given base.
58 --
59 Package.cmds_clean = function(base, cmds)
60         cmds:add({
61             cmdline = "${root}${CHROOT} ${root}${base} /${PKG_DELETE} '*'",
62             replacements = { base = base }
63         })
64 end
65
66 --
67 -- Create commands to copy a package from the installation media onto
68 -- the target system.
69 --
70 -- This function returns the number of packages that will be copied
71 -- by the commands it has created, or nil if an error occurs.
72 --
73 Package.cmds_copy = function(base, cmds, pkg_name, pkg_seen, pkg_done)
74         local pty, rpkg_name, line, pkg_suffix
75         local depcount = 0
76         pkg_seen = pkg_seen or {}
77         pkg_done = pkg_done or {}
78
79         --
80         -- Get all the packages that this package depends on, and
81         -- recursively copy them first, if they're not already there,
82         -- and if we've not already seen them.
83         --
84         -- It woulld be nice if we could send this command through a command
85         -- chain  so that we could get an accurate idea of what is being
86         -- run and so that it will be logged.  But unfortunately that's
87         -- not feasible, since this function is building another command
88         -- chain for later use.  So we use a pty.
89         --
90         pty = Pty.open(App.expand("${root}${PKG_INFO} -r ") .. pkg_name)
91         if not pty then
92                 return nil
93         end
94
95         line = pty:readline()
96         while line do
97                 --
98                 -- Only look at lines that begin with 'Dependency:'.
99                 --
100                 local found, len, rpkg_name =
101                     string.find(line, "^Dependency:%s*([^%s]+)")
102                 if found and not Package.exists(base, rpkg_name) then
103                         local subcount = Package.cmds_copy(
104                             base, cmds, rpkg_name, pkg_seen, pkg_done
105                         )
106                         if subcount == nil then
107                                 pty:close()
108                                 return nil
109                         end
110                         depcount = depcount + subcount
111                 end
112                 line = pty:readline()
113         end
114         pty:close()
115
116         pkg_suffix = "tgz"
117         if App.os.name == "FreeBSD" then
118                 pkg_suffix = "tbz"
119         end
120
121         if not Package.exists(base, pkg_name) and not pkg_seen[pkg_name] then
122                 pkg_seen[pkg_name] = true
123                 depcount = depcount + 1
124                 cmds:set_replacements{
125                     base       = base,
126                     pkg_name   = pkg_name,
127                     pkg_suffix = pkg_suffix
128                 }
129                 cmds:add(
130                     "${root}${PKG_CREATE} -b ${pkg_name} ${root}${base}tmp/${pkg_name}.${pkg_suffix}",
131                     {
132                         cmdline = "${root}${CHROOT} ${root}${base} " ..
133                                   "/${PKG_ADD} /tmp/${pkg_name}.${pkg_suffix}",
134                         tag = pkg_name,
135                         on_executed = function(cmd, result, output)
136                             if result == 0 then
137                                     pkg_done[cmd.tag] = true
138                             end
139                         end
140                     },
141                     "${root}${RM} ${root}${base}tmp/${pkg_name}.${pkg_suffix}"
142                 )
143         end
144
145         return depcount
146 end
147
148 --
149 -- Remove a package from a target system.
150 --
151 -- This function returns the number of packages that will be removed
152 -- by the commands it has created, or nil if an error occurs.
153 --
154 Package.cmds_remove = function(base, cmds, pkg_name, pkg_seen, pkg_done)
155         local pty, line
156         local command, rpkg_name
157         local depcount = 0
158         local seen_required_by = false
159         pkg_seen = pkg_seen or {}
160         pkg_done = pkg_done or {}
161
162         --
163         -- Get all the packages that this package depends on, and
164         -- recursively delete them.
165         --
166         pty = Pty.open(App.expand(
167             "${root}${CHROOT} ${root}${base} /${PKG_INFO} -R ${pkg_name}", {
168                 base = base,
169                 pkg_name = pkg_name
170             }
171         ))
172         if not pty then
173                 return nil
174         end
175
176         line = pty:readline()
177         while line do
178                 --
179                 -- Only look at lines that follow the "Required by:" line.
180                 --
181                 if seen_required_by then
182                         found, len, rpkg_name =
183                             string.find(line, "^%s*([^%s]+)")
184                         if found and Package.exists(base, rpkg_name) then
185                                 local subcount = Package.cmds_remove(
186                                     base, cmds, rpkg_name, pkg_seen, pkg_done
187                                 )
188                                 if subcount == nil then
189                                         pty:close()
190                                         return nil
191                                 end
192                                 depcount = depcount + subcount
193                         end
194                 else
195                         if string.find(line, "^Required by:") then
196                                 seen_required_by = true
197                         end
198                 end
199                 line = pty:readline()
200         end
201         pty:close()
202
203         if Package.exists(base, pkg_name) and not pkg_seen[pkg_name] then
204                 pkg_seen[pkg_name] = true
205                 depcount = depcount + 1
206                 cmds:add({
207                     cmdline = "${root}${CHROOT} ${root}${base} /${PKG_DELETE} ${pkg_name}",
208                     replacements = {
209                         base = base,
210                         pkg_name = pkg_name
211                     },
212                     tag = pkg_name,
213                     on_executed = function(cmd, result, output)
214                         if result == 0 then
215                                 pkg_done[cmd.tag] = true
216                         end
217                     end
218                 })
219         end
220         
221         return depcount
222 end
223
224 -- END of lib/package.lua --