-
Notifications
You must be signed in to change notification settings - Fork 2
/
package_v2.lua
280 lines (230 loc) · 7.65 KB
/
package_v2.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
---
-- Package management module
-- Version 2.0 Package API.
-- Copyright (c) 2017 Blizzard Entertainment
---
local p = premake
local m = p.modules.packagemanager
-- Package API ----------------------------------------------------------------
local packageAPI = {}
function packageAPI:loadvariants(filter)
local result = {}
-- load all variants that match the filter.
for _, variant in pairs(self.variants) do
if variant:matches(filter) then
local r = self:loadvariant(variant)
if r then
table.insert(result, r)
end
end
end
return result
end
function packageAPI:loadvariant(variant)
-- if it's a string, find it.
if type(variant) == "string" then
variant = self.variants[variant:lower()]
end
-- if the variant doesn't exist, or is already loaded, return.
if not variant or variant.loaded then
return variant
end
-- now load it.
verbosef(' LOAD %s/%s', self.name, variant.name)
-- register package as loaded
variant.loaded = true
return variant
end
function packageAPI:generateManifest(tbl, wks)
local vtbl = {}
for _, v in pairs(self.variants) do
v:generateManifest(vtbl, wks)
end
if next(vtbl) == nil then
vtbl = nil
end
tbl[self.name] = {
type = "2.0",
version = self.version,
variants = vtbl
}
end
-- Importing API --------------------------------------------------------------
local function __isPackage(folder)
local filename = path.join(folder, 'premake5-meta.lua')
return os.isfile(filename)
end
local function __getPackageFolder(name, version)
-- test if version is a folder name.
if os.isdir(version) then
if __isPackage(version) then
version = path.getabsolute(version)
verbosef(' LOCAL: %s', version)
return version
end
end
-- test if we have the package locally.
for _, folder in ipairs(p.packagemanager.folders) do
local location = m.createPackageLocation(folder, name, version)
if __isPackage(location) then
location = path.getabsolute(location)
verbosef(' LOCAL: %s', location)
return location
end
end
-- test if we downloaded it already.
local location = m.createPackageLocation(p.packagemanager.getCacheLocation(), name, version)
if __isPackage(location) then
location = path.getabsolute(location)
verbosef(' CACHED: %s', location)
return location
end
-- if we don't want server queries, we stop here.
if _OPTIONS['no-http'] then
return nil
end
-- ask if any of the servers has it? First hit gets it.
local link_url = '/api/v1/link/' .. http.escapeUrlParam(name) .. '/' .. http.escapeUrlParam(version)
local info = http.getJson(p.packagemanager.servers, link_url)
if info ~= nil and info.url ~= nil then
if type(info.state) == "string" and info.state:lower() ~= 'active' then
p.warn('"%s/%s" is marked "%s", consider upgrading to a known good version.', name, version, info.state)
end
if info.version then
version = info.version
location = m.createPackageLocation(p.packagemanager.getCacheLocation(), name, version)
if __isPackage(location) then
verbosef(' CACHED: %s', location)
return location
end
end
-- create destination folder.
os.mkdir(location)
-- download to packagecache/name-version.zip.
local destination = m.createPackageLocation(p.packagemanager.getCacheLocation(), name .. '-' .. version .. '.zip')
print(' DOWNLOAD: ' .. info.url)
local result_str, response_code = http.download(info.url, destination,
{
headers = http.getHttpHeader(),
progress = iif(_OPTIONS.verbose, http.reportProgress, nil)
})
if result_str ~= "OK" then
p.error('Download of %s failed (%d)\n%s', info.url, response_code, result_str)
end
-- Unzip it
verbosef(' UNZIP : %s', destination)
zip.extract(destination, location)
os.remove(destination)
return location
end
return nil
end
local function __createFilter(meta)
return m.validateFilter({
system = meta.system,
host = meta.host,
architecture = meta.architecture,
toolset = meta.toolset,
action = meta.action,
configurations = meta.configurations,
tags = meta.tags
})
end
local function __createVariant(pkg, name, meta, dir)
if meta == nil then
error("Metadata entry for '" .. name .."' does not exist.")
end
m.checkType("includedirs", meta.includedirs, "table")
m.checkType("links", meta.links, "table")
m.checkType("libdirs", meta.libdirs, "table")
m.checkType("defines", meta.defines, "table")
m.checkType("dependson", meta.dependson, "table")
m.checkType("bindirs", meta.bindirs, "table")
m.checkType("includedependencies", meta.includedependencies, "table")
m.checkType("linkdependencies", meta.linkdependencies, "table")
m.checkType("usedependencies", meta.usedependencies, "table")
m.checkType("premake", meta.premake, "string")
m.checkType("tests", meta.tests, "string")
m.checkType("options", meta.options, "table")
local variant = m.createVariant(name)
variant.filter = __createFilter(meta)
variant.includes = meta.includedirs
variant.links = meta.links
variant.libdirs = meta.libdirs
variant.defines = meta.defines
variant.bindirs = meta.bindirs
variant.dependson = meta.dependson
variant.includedependencies = table.join(meta.usedependencies or {}, meta.includedependencies)
variant.linkdependencies = table.join(meta.usedependencies or {}, meta.linkdependencies)
variant.location = dir
variant.script = meta.premake
variant.testscript = meta.tests
variant.package = pkg
variant.loaded = false
-- deal with package options.
if name == 'noarch' then
pkg.options = meta.options
elseif meta.options ~= nil then
error("Cannot specify package options in variants.")
end
-- if links wasn't set, then enumerate the libdirs if set
if meta.links == nil and meta.libdirs ~= nil then
variant.links = variant.links or {}
for _, libdir in ipairs(meta.libdirs) do
libdir = path.join(dir, libdir)
table.insertflat(variant.links, _get_lib_files(libdir, variant.filter.system))
end
end
-- setup the initializer.
if meta.premake ~= nil then
variant.initializer = function()
dofile(meta.premake)
end
end
return variant
end
return function (name, version)
local dir = __getPackageFolder(name, version)
if not dir then
return nil
end
-- make dir absolute.
dir = path.getabsolute(dir)
-- load the meta data file.
local env = {}
local filename = path.join(dir, 'premake5-meta.lua');
if not os.isfile(filename) then
error('Package in folder "' .. dir .. '" does not have a premake5-meta.lua script.')
end
local untrusted_function, message = loadfile(filename, 't', env)
if not untrusted_function then
error(message)
end
-- now execute it, so we can get the data.
local result, meta = pcall(untrusted_function)
if not result then
error(meta)
end
-- create package from metadata.
local pkg = m.createPackageBase(name, version)
pkg.variants['noarch'] = __createVariant(pkg, 'noarch', meta, dir)
if meta.variants ~= nil then
for _, v in ipairs(meta.variants) do
if variant == "noarch" then
p.error("'noarch' variant is reserved for the top-level meta-data.")
end
pkg.variants[v] = __createVariant(pkg, v, meta[v], dir)
end
end
-- return package with PackageV2 metadata attachment.
return setmetatable(pkg, {
__metatable = false,
__index = packageAPI,
__newindex = function(tbl, key, value)
error("Attempt to modify readonly table.")
end,
__tostring = function()
return "Package V2"
end,
})
end