|
1 -- |
|
2 -- rpmlua -- OpenPKG RPM Lua Script |
|
3 -- Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/> |
|
4 -- |
|
5 -- This software is property of the OpenPKG GmbH, DE MUC HRB 160208. |
|
6 -- All rights reserved. Licenses which grant limited permission to use, |
|
7 -- copy, modify and distribute this software are available from the |
|
8 -- OpenPKG GmbH. |
|
9 -- |
|
10 -- THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
|
11 -- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
|
12 -- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|
13 -- IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR |
|
14 -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
15 -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
16 -- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
17 -- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
18 -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|
19 -- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
|
20 -- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
21 -- SUCH DAMAGE. |
|
22 -- |
|
23 |
|
24 -- |
|
25 -- The purpose of this Lua script is to extend the default Lua functions |
|
26 -- in the OpenPKG RPM installation for the @l_prefix@ hierarchy. |
|
27 -- |
|
28 |
|
29 -- provide namespace |
|
30 openpkg = {} |
|
31 |
|
32 -- small wrapper around the realpath(3) call provided by RPM |
|
33 function openpkg.realpath(path) |
|
34 if posix.stat(path) ~= nil then |
|
35 -- path exists, so resolve as a whole |
|
36 path = rpm.realpath(path) |
|
37 else |
|
38 -- path not exists, so recursively resolve only prefix |
|
39 local s, _, m = util.rmatch(path, "^(.+?)/([^/]+)/?$") |
|
40 if s ~= nil then |
|
41 local prefix = openpkg.realpath(m[1]) |
|
42 if util.rmatch(prefix, "/$") == nil then |
|
43 prefix = prefix .. "/" |
|
44 end |
|
45 path = prefix .. m[2] |
|
46 end |
|
47 end |
|
48 return path |
|
49 end |
|
50 |
|
51 -- try to reduce real path to symbolic one (if posssible) |
|
52 function openpkg.unrealpath(path, prefix_unreal) |
|
53 local prefix_real = openpkg.realpath(prefix_unreal) |
|
54 if prefix_real ~= prefix_unreal then |
|
55 if string.sub(path, 1, string.len(prefix_real)) == prefix_real then |
|
56 path = prefix_unreal .. string.sub(path, string.len(prefix_real)+1) |
|
57 end |
|
58 end |
|
59 return path |
|
60 end |
|
61 |
|
62 -- canonicalize filesystem path as good as possible |
|
63 function openpkg.canonicalize(path) |
|
64 path = openpkg.unrealpath(path, os.getenv("PWD")) |
|
65 path = openpkg.unrealpath(path, rpm.expand("%{l_prefix}")) |
|
66 return path |
|
67 end |
|
68 |
|
69 -- temporary directory determination |
|
70 function openpkg.tmpdir() |
|
71 local tmpdir = os.getenv("TMPDIR") |
|
72 if tmpdir ~= nil then |
|
73 tmpdir = openpkg.canonicalize(openpkg.realpath(tmpdir)) |
|
74 else |
|
75 tmpdir = "/tmp" |
|
76 end |
|
77 tmpdir = tmpdir .. "/openpkg" |
|
78 return tmpdir |
|
79 end |
|
80 |
|
81 -- layout determination: RPM Lua based implementation |
|
82 function openpkg.layout(args) |
|
83 local dir = "" |
|
84 |
|
85 -- parse arguments |
|
86 local arg = { |
|
87 variable = "", |
|
88 layout = "", |
|
89 macrosfile = "", |
|
90 basedir = "", |
|
91 shared = "no", |
|
92 debug = "no", |
|
93 specdir = "", |
|
94 sourcedir = "", |
|
95 builddir = "", |
|
96 tmppath = "", |
|
97 rpmdir = "", |
|
98 srcrpmdir = "" |
|
99 } |
|
100 local arg_map_fwd = { |
|
101 binrpmdir = "rpmdir", |
|
102 tmpdir = "tmppath" |
|
103 } |
|
104 local arg_map_rev = { |
|
105 rpmdir = "binrpmdir", |
|
106 tmppath = "tmpdir" |
|
107 } |
|
108 if rpm.debug() then |
|
109 arg.debug = "yes" |
|
110 end |
|
111 util.rsubst(args, "(?s)\\s*([a-z_][a-zA-Z0-9_-]*)=(?:\"((?:\\\\.|[^\"])*)\"|(\\S*))", |
|
112 function (key, _, value1, value2) |
|
113 if arg_map_fwd[key] ~= nil then |
|
114 key = arg_map_fwd[key] |
|
115 end |
|
116 if arg[key] == nil then |
|
117 io.stderr:write("rpm: invalid parameter \"" .. key .. "\" on call to \"openpkg.layout()\"\n") |
|
118 else |
|
119 if value1 ~= nil then arg[key] = value1 else arg[key] = value2 end |
|
120 end |
|
121 return false |
|
122 end |
|
123 ) |
|
124 if arg.variable == "" then |
|
125 io.stderr:write("rpm: missing \"variable\" parameter on call to \"openpkg.layout()\"\n") |
|
126 return "" |
|
127 end |
|
128 if arg.layout == "" then |
|
129 io.stderr:write("rpm: missing \"layout\" parameter on call to \"openpkg.layout()\"\n") |
|
130 return "" |
|
131 end |
|
132 if arg.macrosfile == "" and arg.basedir == "" then |
|
133 io.stderr:write("rpm: missing \"macrosfile\" or \"basedir\" parameter on call to \"openpkg.layout()\"\n") |
|
134 return "" |
|
135 end |
|
136 |
|
137 -- determine base directory |
|
138 if arg.basedir == "" then |
|
139 if util.rmatch(arg.macrosfile, "^.*/\.openpkg/rpmmacros$") ~= nil then |
|
140 arg.basedir = openpkg.canonicalize(openpkg.realpath( |
|
141 util.rsubst( |
|
142 openpkg.realpath(arg.macrosfile), |
|
143 "/[^/]+$", "/.." |
|
144 ) |
|
145 )) |
|
146 else |
|
147 arg.basedir = rpm.expand("%{l_prefix}") |
|
148 end |
|
149 end |
|
150 |
|
151 -- temporarily define "__openpkg_basedir" macro |
|
152 rpm.define("__openpkg_basedir " .. arg.basedir) |
|
153 |
|
154 -- temporarily define "__openpkg_shared" macro |
|
155 if arg.shared == "yes" then |
|
156 rpm.define("__openpkg_shared yes") |
|
157 end |
|
158 |
|
159 -- determine layout directory list |
|
160 local list = "" |
|
161 if arg[arg.variable] ~= nil and arg[arg.variable] ~= "" then |
|
162 list = arg[arg.variable] |
|
163 else |
|
164 list = rpm.expand( |
|
165 "%{?__openpkg_layout_" .. arg.layout .. "_" .. arg.variable .. "}" .. |
|
166 "%{!?__openpkg_layout_" .. arg.layout .. "_" .. arg.variable .. ":" .. |
|
167 "%{__openpkg_layout_global_" .. arg.variable .. "}}" |
|
168 ) |
|
169 end |
|
170 |
|
171 -- remove temporarily defined "__openpkg_basedir" macro |
|
172 rpm.undefine("__openpkg_basedir") |
|
173 |
|
174 -- remove temporarily defined "__openpkg_shared" macro |
|
175 if arg.shared == "yes" then |
|
176 rpm.undefine("__openpkg_shared") |
|
177 end |
|
178 |
|
179 -- iterate over all directory specifications |
|
180 local dirs = util.rsplit(list, "(?s)\\s+") |
|
181 local k = table.maxn(dirs) |
|
182 for i, _ in ipairs(dirs) do |
|
183 -- parse specification into path to check and optionally path to make |
|
184 local path_check = dirs[i] |
|
185 local path_append = false |
|
186 local path_make = path_check |
|
187 local s, _, m = util.rmatch(path_check, "^(.+):(\\+?)(.*)$") |
|
188 if s ~= nil then |
|
189 path_check = m[1] |
|
190 path_append = (m[2] == "+") |
|
191 path_make = m[3] |
|
192 end |
|
193 -- check whether path should be taken (last path is always taken) |
|
194 if posix.stat(path_check) ~= nil or i == k then |
|
195 if path_append then |
|
196 -- special case: simply append a suffix |
|
197 dir = path_check .. path_make |
|
198 else |
|
199 -- regular case: use full path to make |
|
200 dir = path_make |
|
201 end |
|
202 break |
|
203 end |
|
204 end |
|
205 if dir ~= "" then |
|
206 -- make sure path really exists and resolve to absolute path |
|
207 if posix.stat(dir) == nil then |
|
208 io.stderr:write("rpm: creating \"" .. arg.variable .. "\" directory \"" .. dir .. "\"\n") |
|
209 if posix.mkdir(dir) ~= 0 then |
|
210 io.stderr:write("rpm: failed to create directory \"" .. dir .. "\"\n") |
|
211 end |
|
212 end |
|
213 dir = openpkg.canonicalize(openpkg.realpath(dir)) |
|
214 end |
|
215 |
|
216 -- debugging |
|
217 if arg.debug == "yes" then |
|
218 local variable = arg.variable |
|
219 if arg_map_rev[variable] ~= nil then |
|
220 variable = arg_map_rev[variable] |
|
221 end |
|
222 io.stderr:write(string.format("rpm: openpkg: layout: [%s] %s = \"%s\"\n", arg.layout, variable, dir)) |
|
223 end |
|
224 |
|
225 -- provide result directory |
|
226 return dir |
|
227 end |
|
228 |