aboutsummaryrefslogtreecommitdiff
path: root/src/luarocks/pack.tl
diff options
context:
space:
mode:
Diffstat (limited to 'src/luarocks/pack.tl')
-rw-r--r--src/luarocks/pack.tl188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/luarocks/pack.tl b/src/luarocks/pack.tl
new file mode 100644
index 00000000..8bb284f7
--- /dev/null
+++ b/src/luarocks/pack.tl
@@ -0,0 +1,188 @@
1
2-- Create rock files, packing sources or binaries.
3local record pack
4end
5
6local queries = require("luarocks.queries")
7local path = require("luarocks.path")
8local repos = require("luarocks.repos")
9local fetch = require("luarocks.fetch")
10local fs = require("luarocks.fs")
11local cfg = require("luarocks.core.cfg")
12local util = require("luarocks.util")
13local dir = require("luarocks.dir")
14local manif = require("luarocks.manif")
15local search = require("luarocks.search")
16local signing = require("luarocks.signing")
17
18local type Tree = require("luarocks.core.types.tree").Tree
19
20local type Query = require("luarocks.core.types.query").Query
21
22local type Entry = require("luarocks.core.types.rockmanifest").RockManifest.Entry
23
24--- Create a source rock.
25-- Packages a rockspec and its required source files in a rock
26-- file with the .src.rock extension, which can later be built and
27-- installed with the "build" command.
28-- @param rockspec_file string: An URL or pathname for a rockspec file.
29-- @return string or (nil, string): The filename of the resulting
30-- .src.rock file; or nil and an error message.
31function pack.pack_source_rock(rockspec_file: string): string, string
32
33 local rockspec, errload = fetch.load_rockspec(rockspec_file)
34 if errload then
35 return nil, "Error loading rockspec: "..errload
36 end
37 rockspec_file = rockspec.local_abs_filename
38
39 local name_version = rockspec.name .. "-" .. rockspec.version
40 local rock_file = fs.absolute_name(name_version .. ".src.rock")
41
42 local temp_dir, err = fs.make_temp_dir("pack-"..name_version)
43 if not temp_dir then
44 return nil, "Failed creating temporary directory: "..err
45 end
46 util.schedule_function(fs.delete, temp_dir)
47
48 local source_file, source_dir = fetch.fetch_sources(rockspec, true, temp_dir)
49 if not source_file then
50 return nil, source_dir
51 end
52 local ok, errchange = fs.change_dir(source_dir)
53 if not ok then return nil, errchange end
54
55 fs.delete(rock_file)
56 fs.copy(rockspec_file, source_dir, "read")
57 ok, err = fs.zip(rock_file, dir.base_name(rockspec_file), dir.base_name(source_file))
58 if not ok then
59 return nil, "Failed packing "..rock_file.." - "..err
60 end
61 fs.pop_dir()
62
63 return rock_file
64end
65
66local function copy_back_files(name: string, version: string, file_tree: {string: any}, deploy_dir: string, pack_dir: string, perms?: string): boolean, string
67 local ok, err = fs.make_dir(pack_dir)
68 if not ok then return nil, err end
69 for file, sub in pairs(file_tree) do
70 local source = dir.path(deploy_dir, file)
71 local target = dir.path(pack_dir, file)
72 if sub is {string: any} then
73 ok, err = copy_back_files(name, version, sub, source, target)
74 if not ok then return nil, err end
75 else
76 local versioned = path.versioned_name(source, deploy_dir, name, version)
77 if fs.exists(versioned) then
78 fs.copy(versioned, target, perms)
79 else
80 fs.copy(source, target, perms)
81 end
82 end
83 end
84 return true
85end
86
87-- @param name string: Name of package to pack.
88-- @param version string or nil: A version number may also be passed.
89-- @param tree string or nil: An optional tree to pick the package from.
90-- @return string or (nil, string): The filename of the resulting
91-- .src.rock file; or nil and an error message.
92function pack.pack_installed_rock(query: Query, tree: string | Tree): string, string
93
94 local name, version, repo, repo_url = search.pick_installed_rock(query, tree)
95 if not name then
96 return nil, version
97 end
98
99 local root = path.root_from_rocks_dir(repo_url)
100 local prefix = path.install_dir(name, version, root)
101 if not fs.exists(prefix) then
102 return nil, "'"..name.." "..version.."' does not seem to be an installed rock."
103 end
104
105 local rock_manifest, err = manif.load_rock_manifest(name, version, root)
106 if not rock_manifest then return nil, err end
107
108 local name_version = name .. "-" .. version
109 local rock_file = fs.absolute_name(name_version .. "."..cfg.arch..".rock")
110
111 local temp_dir = fs.make_temp_dir("pack")
112 fs.copy_contents(prefix, temp_dir)
113
114 local is_binary = false
115 if rock_manifest.lib then
116 local ok, err = copy_back_files(name, version, (rock_manifest.lib as {string: Entry}), path.deploy_lib_dir(repo), dir.path(temp_dir, "lib"), "exec")
117 if not ok then return nil, "Failed copying back files: " .. err end
118 is_binary = true
119 end
120 if rock_manifest.lua then
121 local ok, err = copy_back_files(name, version, (rock_manifest.lua as {string: Entry}), path.deploy_lua_dir(repo), dir.path(temp_dir, "lua"), "read")
122 if not ok then return nil, "Failed copying back files: " .. err end
123 end
124
125 local ok, err = fs.change_dir(temp_dir)
126 if not ok then return nil, err end
127 if not is_binary and not repos.has_binaries(name, version) then
128 rock_file = rock_file:gsub("%."..cfg.arch:gsub("%-","%%-").."%.", ".all.")
129 end
130 fs.delete(rock_file)
131 ok, err = fs.zip(rock_file, table.unpack(fs.list_dir()))
132 if not ok then
133 return nil, "Failed packing " .. rock_file .. " - " .. err
134 end
135 fs.pop_dir()
136 fs.delete(temp_dir)
137 return rock_file
138end
139
140function pack.report_and_sign_local_file(file: string, err: string, sign: boolean): boolean, string
141 if err then
142 return nil, err
143 end
144 local sigfile: string
145 if sign then
146 sigfile, err = signing.sign_file(file)
147 util.printout()
148 end
149 util.printout("Packed: "..file)
150 if sigfile then
151 util.printout("Signature stored in: "..sigfile)
152 end
153 if err then
154 return nil, err
155 end
156 return true
157end
158
159function pack.pack_binary_rock(name: string, namespace: string, version: string, sign: boolean, cmd: function(): (string, string)): boolean, string
160
161 -- The --pack-binary-rock option for "luarocks build" basically performs
162 -- "luarocks build" on a temporary tree and then "luarocks pack". The
163 -- alternative would require refactoring parts of luarocks.build and
164 -- luarocks.pack, which would save a few file operations: the idea would be
165 -- to shave off the final deploy steps from the build phase and the initial
166 -- collect steps from the pack phase.
167
168 local temp_dir, err = fs.make_temp_dir("luarocks-build-pack-"..dir.base_name(name))
169 if not temp_dir then
170 return nil, "Failed creating temporary directory: "..err
171 end
172 util.schedule_function(fs.delete, temp_dir)
173
174 path.use_tree(temp_dir)
175 local ok, err = cmd()
176 if not ok then
177 return nil, err
178 end
179 local rname, rversion = path.parse_name(name)
180 if not rname then
181 rname, rversion = name, version
182 end
183 local query = queries.new(rname, namespace, rversion)
184 local file, err = pack.pack_installed_rock(query, temp_dir)
185 return pack.report_and_sign_local_file(file, err, sign)
186end
187
188return pack