aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2019-03-20 12:18:03 -0400
committerHisham Muhammad <hisham@gobolinux.org>2019-04-01 17:32:53 -0400
commit12562d320a83e3f8f60d78a366793d474b522c55 (patch)
treed3700d6c919d1ab2584769754ccce5214b57afd5
parentb46978faaebeb5954d57b13ff786fea789ab775c (diff)
downloadluarocks-12562d320a83e3f8f60d78a366793d474b522c55.tar.gz
luarocks-12562d320a83e3f8f60d78a366793d474b522c55.tar.bz2
luarocks-12562d320a83e3f8f60d78a366793d474b522c55.zip
install, build, make: add --verify and --sign options
The --verify options of build and make check the signature of rockspec and src.rock files; the --sign option is meant to be used alongside --pack-binary-rock.
-rw-r--r--src/luarocks/build.lua5
-rw-r--r--src/luarocks/cmd/build.lua32
-rw-r--r--src/luarocks/cmd/install.lua108
-rw-r--r--src/luarocks/cmd/make.lua18
-rw-r--r--src/luarocks/cmd/pack.lua18
-rw-r--r--src/luarocks/deps.lua23
-rw-r--r--src/luarocks/fetch.lua69
-rw-r--r--src/luarocks/pack.lua25
-rw-r--r--src/luarocks/signing.lua32
-rw-r--r--src/luarocks/util.lua1
10 files changed, 236 insertions, 95 deletions
diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua
index 130ccd3a..14d699e5 100644
--- a/src/luarocks/build.lua
+++ b/src/luarocks/build.lua
@@ -19,6 +19,7 @@ build.opts = util.opts_table("build.opts", {
19 build_only_deps = "boolean", 19 build_only_deps = "boolean",
20 namespace = "string?", 20 namespace = "string?",
21 branch = "boolean", 21 branch = "boolean",
22 verify = "boolean",
22}) 23})
23 24
24do 25do
@@ -104,13 +105,13 @@ local function process_dependencies(rockspec, opts)
104 end 105 end
105 if not opts.build_only_deps then 106 if not opts.build_only_deps then
106 if next(rockspec.build_dependencies) then 107 if next(rockspec.build_dependencies) then
107 local ok, err, errcode = deps.fulfill_dependencies(rockspec, "build_dependencies", opts.deps_mode) 108 local ok, err, errcode = deps.fulfill_dependencies(rockspec, "build_dependencies", opts.deps_mode, opts.verify)
108 if err then 109 if err then
109 return nil, err, errcode 110 return nil, err, errcode
110 end 111 end
111 end 112 end
112 end 113 end
113 local ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode) 114 local ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode, opts.verify)
114 if err then 115 if err then
115 return nil, err, errcode 116 return nil, err, errcode
116 end 117 end
diff --git a/src/luarocks/cmd/build.lua b/src/luarocks/cmd/build.lua
index 29b1bd6e..e6dc8a88 100644
--- a/src/luarocks/cmd/build.lua
+++ b/src/luarocks/cmd/build.lua
@@ -19,7 +19,7 @@ local make = require("luarocks.cmd.make")
19local cmd = require("luarocks.cmd") 19local cmd = require("luarocks.cmd")
20 20
21cmd_build.help_summary = "build/compile a rock." 21cmd_build.help_summary = "build/compile a rock."
22cmd_build.help_arguments = "[--pack-binary-rock] [--keep] {<rockspec>|<rock>|<name> [<version>]}" 22cmd_build.help_arguments = "[<flags...>] {<rockspec>|<rock>|<name> [<version>]}"
23cmd_build.help = [[ 23cmd_build.help = [[
24Build and install a rock, compiling its C parts if any. 24Build and install a rock, compiling its C parts if any.
25Argument may be a rockspec file, a source rock file 25Argument may be a rockspec file, a source rock file
@@ -40,17 +40,22 @@ or the name of a rock to be fetched from a repository.
40 40
41--only-deps Installs only the dependencies of the rock. 41--only-deps Installs only the dependencies of the rock.
42 42
43--verify Verify signature of the rockspec or src.rock being
44 built. If the rockspec or src.rock is being downloaded,
45 LuaRocks will attempt to download the signature as well.
46 Otherwise, the signature file should be already
47 available locally in the same directory.
48 You need the signer’s public key in your local
49 keyring for this option to work properly.
50
51--sign To be used with --pack-binary-rock. Also produce
52 a signature file for the generated .rock file.
53
43]]..util.deps_mode_help() 54]]..util.deps_mode_help()
44 55
45--- Build and install a rock. 56--- Build and install a rock.
46-- @param rock_filename string: local or remote filename of a rock. 57-- @param rock_filename string: local or remote filename of a rock.
47-- @param need_to_fetch boolean: true if sources need to be fetched, 58-- @param opts table: build options
48-- false if the rockspec was obtained from inside a source rock.
49-- @param deps_mode: string: Which trees to check dependencies for:
50-- "one" for the current default tree, "all" for all trees,
51-- "order" for all trees with priority >= the current default, "none" for no trees.
52-- @param build_only_deps boolean: true to build the listed dependencies only.
53-- @param namespace string?: an optional namespace
54-- @return boolean or (nil, string, [string]): True if build was successful, 59-- @return boolean or (nil, string, [string]): True if build was successful,
55-- or false and an error message and an optional error code. 60-- or false and an error message and an optional error code.
56local function build_rock(rock_filename, opts) 61local function build_rock(rock_filename, opts)
@@ -60,7 +65,7 @@ local function build_rock(rock_filename, opts)
60 local ok, err, errcode 65 local ok, err, errcode
61 66
62 local unpack_dir 67 local unpack_dir
63 unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_filename) 68 unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_filename, nil, opts.verify)
64 if not unpack_dir then 69 if not unpack_dir then
65 return nil, err, errcode 70 return nil, err, errcode
66 end 71 end
@@ -100,7 +105,7 @@ local function do_build(ns_name, version, opts)
100 end 105 end
101 106
102 if url:match("%.rockspec$") then 107 if url:match("%.rockspec$") then
103 local rockspec, err, errcode = fetch.load_rockspec(url) 108 local rockspec, err, errcode = fetch.load_rockspec(url, nil, opts.verify)
104 if not rockspec then 109 if not rockspec then
105 return nil, err, errcode 110 return nil, err, errcode
106 end 111 end
@@ -151,10 +156,15 @@ function cmd_build.command(flags, name, version)
151 build_only_deps = not not flags["only-deps"], 156 build_only_deps = not not flags["only-deps"],
152 namespace = flags["namespace"], 157 namespace = flags["namespace"],
153 branch = not not flags["branch"], 158 branch = not not flags["branch"],
159 verify = not not flags["verify"],
154 }) 160 })
155 161
162 if flags["sign"] and not flags["pack-binary-rock"] then
163 return nil, "In the build command, --sign is meant to be used only with --pack-binary-rock"
164 end
165
156 if flags["pack-binary-rock"] then 166 if flags["pack-binary-rock"] then
157 return pack.pack_binary_rock(name, version, function() 167 return pack.pack_binary_rock(name, version, flags["sign"], function()
158 opts.build_only_deps = false 168 opts.build_only_deps = false
159 local status, err, errcode = do_build(name, version, opts) 169 local status, err, errcode = do_build(name, version, opts)
160 if status and flags["no-doc"] then 170 if status and flags["no-doc"] then
diff --git a/src/luarocks/cmd/install.lua b/src/luarocks/cmd/install.lua
index 97c693d9..647dbdfd 100644
--- a/src/luarocks/cmd/install.lua
+++ b/src/luarocks/cmd/install.lua
@@ -14,6 +14,7 @@ local search = require("luarocks.search")
14local queries = require("luarocks.queries") 14local queries = require("luarocks.queries")
15local cfg = require("luarocks.core.cfg") 15local cfg = require("luarocks.core.cfg")
16local cmd = require("luarocks.cmd") 16local cmd = require("luarocks.cmd")
17local dir = require("luarocks.dir")
17 18
18install.help_summary = "Install a rock." 19install.help_summary = "Install a rock."
19 20
@@ -29,22 +30,40 @@ or a filename of a locally available rock.
29 in the configuration file. 30 in the configuration file.
30 31
31--only-deps Installs only the dependencies of the rock. 32--only-deps Installs only the dependencies of the rock.
33
32--no-doc Installs the rock without its documentation. 34--no-doc Installs the rock without its documentation.
35
36--verify Verify signature of the rock being installed.
37 If rock is being downloaded, LuaRocks will attempt
38 to download the signature as well. If the rock is
39 local, the signature file should be in the same
40 directory.
41 You need the signer’s public key in your local
42 keyring for this option to work properly.
43
33]]..util.deps_mode_help() 44]]..util.deps_mode_help()
34 45
46install.opts = util.opts_table("install.opts", {
47 namespace = "string?",
48 keep = "boolean",
49 force = "boolean",
50 force_fast = "boolean",
51 no_doc = "boolean",
52 deps_mode = "string",
53 verify = "boolean",
54})
35 55
36--- Install a binary rock. 56--- Install a binary rock.
37-- @param rock_file string: local or remote filename of a rock. 57-- @param rock_file string: local or remote filename of a rock.
38-- @param deps_mode: string: Which trees to check dependencies for: 58-- @param opts table: installation options
39-- "one" for the current default tree, "all" for all trees,
40-- "order" for all trees with priority >= the current default, "none" for no trees.
41-- @param namespace: string?: an optional namespace.
42-- @return (string, string) or (nil, string, [string]): Name and version of 59-- @return (string, string) or (nil, string, [string]): Name and version of
43-- installed rock if succeeded or nil and an error message followed by an error code. 60-- installed rock if succeeded or nil and an error message followed by an error code.
44function install.install_binary_rock(rock_file, deps_mode, namespace) 61function install.install_binary_rock(rock_file, opts)
45 assert(type(rock_file) == "string") 62 assert(type(rock_file) == "string")
46 assert(type(deps_mode) == "string") 63 assert(opts:type() == "install.opts")
47 assert(type(namespace) == "string" or namespace == nil) 64
65 local namespace = opts.namespace
66 local deps_mode = opts.deps_mode
48 67
49 local name, version, arch = path.parse_name(rock_file) 68 local name, version, arch = path.parse_name(rock_file)
50 if not name then 69 if not name then
@@ -55,23 +74,25 @@ function install.install_binary_rock(rock_file, deps_mode, namespace)
55 return nil, "Incompatible architecture "..arch, "arch" 74 return nil, "Incompatible architecture "..arch, "arch"
56 end 75 end
57 if repos.is_installed(name, version) then 76 if repos.is_installed(name, version) then
58 repos.delete_version(name, version, deps_mode) 77 repos.delete_version(name, version, opts.deps_mode)
59 end 78 end
60 79
80 local install_dir = path.install_dir(name, version)
81
61 local rollback = util.schedule_function(function() 82 local rollback = util.schedule_function(function()
62 fs.delete(path.install_dir(name, version)) 83 fs.delete(install_dir)
63 fs.remove_dir_if_empty(path.versions_dir(name)) 84 fs.remove_dir_if_empty(path.versions_dir(name))
64 end) 85 end)
65 86
66 local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, path.install_dir(name, version)) 87 local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify)
67 if not ok then return nil, err, errcode end 88 if not ok then return nil, err, errcode end
68 89
69 local rockspec, err, errcode = fetch.load_rockspec(path.rockspec_file(name, version)) 90 local rockspec, err = fetch.load_rockspec(path.rockspec_file(name, version))
70 if err then 91 if err then
71 return nil, "Failed loading rockspec for installed package: "..err, errcode 92 return nil, "Failed loading rockspec for installed package: "..err, errcode
72 end 93 end
73 94
74 if deps_mode == "none" then 95 if opts.deps_mode == "none" then
75 util.warning("skipping dependency checks.") 96 util.warning("skipping dependency checks.")
76 else 97 else
77 ok, err, errcode = deps.check_external_deps(rockspec, "install") 98 ok, err, errcode = deps.check_external_deps(rockspec, "install")
@@ -90,7 +111,7 @@ function install.install_binary_rock(rock_file, deps_mode, namespace)
90 end 111 end
91 112
92 if deps_mode ~= "none" then 113 if deps_mode ~= "none" then
93 ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode) 114 ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode, opts.verify)
94 if err then return nil, err, errcode end 115 if err then return nil, err, errcode end
95 end 116 end
96 117
@@ -112,14 +133,13 @@ end
112 133
113--- Installs the dependencies of a binary rock. 134--- Installs the dependencies of a binary rock.
114-- @param rock_file string: local or remote filename of a rock. 135-- @param rock_file string: local or remote filename of a rock.
115-- @param deps_mode: string: Which trees to check dependencies for: 136-- @param opts table: installation options
116-- "one" for the current default tree, "all" for all trees,
117-- "order" for all trees with priority >= the current default, "none" for no trees.
118-- @return (string, string) or (nil, string, [string]): Name and version of 137-- @return (string, string) or (nil, string, [string]): Name and version of
119-- the rock whose dependencies were installed if succeeded or nil and an error message 138-- the rock whose dependencies were installed if succeeded or nil and an error message
120-- followed by an error code. 139-- followed by an error code.
121function install.install_binary_rock_deps(rock_file, deps_mode) 140function install.install_binary_rock_deps(rock_file, opts)
122 assert(type(rock_file) == "string") 141 assert(type(rock_file) == "string")
142 assert(opts:type() == "install.opts")
123 143
124 local name, version, arch = path.parse_name(rock_file) 144 local name, version, arch = path.parse_name(rock_file)
125 if not name then 145 if not name then
@@ -130,15 +150,17 @@ function install.install_binary_rock_deps(rock_file, deps_mode)
130 return nil, "Incompatible architecture "..arch, "arch" 150 return nil, "Incompatible architecture "..arch, "arch"
131 end 151 end
132 152
133 local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, path.install_dir(name, version)) 153 local install_dir = path.install_dir(name, version)
154
155 local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify)
134 if not ok then return nil, err, errcode end 156 if not ok then return nil, err, errcode end
135 157
136 local rockspec, err, errcode = fetch.load_rockspec(path.rockspec_file(name, version)) 158 local rockspec, err = fetch.load_rockspec(path.rockspec_file(name, version))
137 if err then 159 if err then
138 return nil, "Failed loading rockspec for installed package: "..err, errcode 160 return nil, "Failed loading rockspec for installed package: "..err, errcode
139 end 161 end
140 162
141 ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode) 163 ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode, opts.verify)
142 if err then return nil, err, errcode end 164 if err then return nil, err, errcode end
143 165
144 util.printout() 166 util.printout()
@@ -147,27 +169,24 @@ function install.install_binary_rock_deps(rock_file, deps_mode)
147 return name, version 169 return name, version
148end 170end
149 171
150local function install_rock_file_deps(filename, deps_mode) 172local function install_rock_file_deps(filename, opts)
151 local name, version = install.install_binary_rock_deps(filename, deps_mode) 173 assert(opts:type() == "install.opts")
174
175 local name, version = install.install_binary_rock_deps(filename, opts)
152 if not name then return nil, version end 176 if not name then return nil, version end
153 177
154 writer.check_dependencies(nil, deps_mode) 178 writer.check_dependencies(nil, opts.deps_mode)
155 return name, version 179 return name, version
156end 180end
157 181
158local function install_rock_file(filename, namespace, deps_mode, keep, force, force_fast, no_doc) 182local function install_rock_file(filename, opts)
159 assert(type(filename) == "string") 183 assert(type(filename) == "string")
160 assert(type(namespace) == "string" or namespace == nil) 184 assert(opts:type() == "install.opts")
161 assert(type(deps_mode) == "string") 185
162 assert(type(keep) == "boolean" or keep == nil) 186 local name, version = install.install_binary_rock(filename, opts)
163 assert(type(force) == "boolean" or force == nil)
164 assert(type(force_fast) == "boolean" or force_fast == nil)
165 assert(type(no_doc) == "boolean" or no_doc == nil)
166
167 local name, version = install.install_binary_rock(filename, deps_mode, namespace)
168 if not name then return nil, version end 187 if not name then return nil, version end
169 188
170 if no_doc then 189 if opts.no_doc then
171 local install_dir = path.install_dir(name, version) 190 local install_dir = path.install_dir(name, version)
172 for _, f in ipairs(fs.list_dir(install_dir)) do 191 for _, f in ipairs(fs.list_dir(install_dir)) do
173 local doc_dirs = { "doc", "docs" } 192 local doc_dirs = { "doc", "docs" }
@@ -179,12 +198,12 @@ local function install_rock_file(filename, namespace, deps_mode, keep, force, fo
179 end 198 end
180 end 199 end
181 200
182 if (not keep) and not cfg.keep_other_versions then 201 if (not opts.keep) and not cfg.keep_other_versions then
183 local ok, err = remove.remove_other_versions(name, version, force, force_fast) 202 local ok, err = remove.remove_other_versions(name, version, opts.force, opts.force_fast)
184 if not ok then util.printerr(err) end 203 if not ok then util.printerr(err) end
185 end 204 end
186 205
187 writer.check_dependencies(nil, deps_mode) 206 writer.check_dependencies(nil, opts.deps_mode)
188 return name, version 207 return name, version
189end 208end
190 209
@@ -213,10 +232,19 @@ function install.command(flags, name, version)
213 return build.command(flags, name) 232 return build.command(flags, name)
214 elseif name:match("%.rock$") then 233 elseif name:match("%.rock$") then
215 local deps_mode = deps.get_deps_mode(flags) 234 local deps_mode = deps.get_deps_mode(flags)
235 local opts = install.opts({
236 namespace = flags["namespace"],
237 keep = not not flags["keep"],
238 force = not not flags["force"],
239 force_fast = not not flags["force-fast"],
240 no_doc = not not flags["no-doc"],
241 deps_mode = deps_mode,
242 verify = not not flags["verify"],
243 })
216 if flags["only-deps"] then 244 if flags["only-deps"] then
217 return install_rock_file_deps(name, deps_mode) 245 return install_rock_file_deps(name, opts)
218 else 246 else
219 return install_rock_file(name, flags["namespace"], deps_mode, flags["keep"], flags["force"], flags["force-fast"], flags["no-doc"]) 247 return install_rock_file(name, opts)
220 end 248 end
221 else 249 else
222 local url, err = search.find_suitable_rock(queries.new(name:lower(), version)) 250 local url, err = search.find_suitable_rock(queries.new(name:lower(), version))
diff --git a/src/luarocks/cmd/make.lua b/src/luarocks/cmd/make.lua
index 90d4f336..4d813864 100644
--- a/src/luarocks/cmd/make.lua
+++ b/src/luarocks/cmd/make.lua
@@ -48,6 +48,17 @@ only dependencies of the rockspec (see `luarocks help install`).
48 rockspec. Allows to specify a different branch to 48 rockspec. Allows to specify a different branch to
49 fetch. Particularly for "dev" rocks. 49 fetch. Particularly for "dev" rocks.
50 50
51--verify Verify signature of the rockspec or src.rock being
52 built. If the rockspec or src.rock is being downloaded,
53 LuaRocks will attempt to download the signature as well.
54 Otherwise, the signature file should be already
55 available locally in the same directory.
56 You need the signer’s public key in your local
57 keyring for this option to work properly.
58
59--sign To be used with --pack-binary-rock. Also produce
60 a signature file for the generated .rock file.
61
51]] 62]]
52 63
53--- Driver function for "make" command. 64--- Driver function for "make" command.
@@ -82,10 +93,15 @@ function make.command(flags, rockspec_filename)
82 build_only_deps = false, 93 build_only_deps = false,
83 namespace = flags["namespace"], 94 namespace = flags["namespace"],
84 branch = not not flags["branch"], 95 branch = not not flags["branch"],
96 verify = not not flags["verify"],
85 }) 97 })
86 98
99 if flags["sign"] and not flags["pack-binary-rock"] then
100 return nil, "In the make command, --sign is meant to be used only with --pack-binary-rock"
101 end
102
87 if flags["pack-binary-rock"] then 103 if flags["pack-binary-rock"] then
88 return pack.pack_binary_rock(name, rockspec.version, function() 104 return pack.pack_binary_rock(name, rockspec.version, flags["sign"], function()
89 return build.build_rockspec(rockspec, opts) 105 return build.build_rockspec(rockspec, opts)
90 end) 106 end)
91 else 107 else
diff --git a/src/luarocks/cmd/pack.lua b/src/luarocks/cmd/pack.lua
index 02e554d9..7781a3bd 100644
--- a/src/luarocks/cmd/pack.lua
+++ b/src/luarocks/cmd/pack.lua
@@ -40,23 +40,7 @@ function cmd_pack.command(flags, arg, version)
40 local query = queries.new(name, version) 40 local query = queries.new(name, version)
41 file, err = pack.pack_installed_rock(query, flags["tree"]) 41 file, err = pack.pack_installed_rock(query, flags["tree"])
42 end 42 end
43 if err then 43 return pack.report_and_sign_local_file(file, err, flags["sign"])
44 return nil, err
45 else
46 local sigfile
47 if flags["sign"] then
48 sigfile, err = signing.sign_file(file)
49 util.printout()
50 end
51 util.printout("Packed: "..file)
52 if sigfile then
53 util.printout("Sigature stored in: "..sigfile)
54 end
55 if err then
56 return nil, err
57 end
58 return true
59 end
60end 44end
61 45
62return cmd_pack 46return cmd_pack
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua
index d9a88c2b..c2f6ab96 100644
--- a/src/luarocks/deps.lua
+++ b/src/luarocks/deps.lua
@@ -129,12 +129,13 @@ function deps.report_missing_dependencies(name, version, dependencies, deps_mode
129 end 129 end
130end 130end
131 131
132function deps.fulfill_dependency(dep, deps_mode, name, version, rocks_provided) 132function deps.fulfill_dependency(dep, deps_mode, name, version, rocks_provided, verify)
133 assert(dep:type() == "query") 133 assert(dep:type() == "query")
134 assert(type(deps_mode) == "string" or deps_mode == nil) 134 assert(type(deps_mode) == "string" or deps_mode == nil)
135 assert(type(name) == "string" or name == nil) 135 assert(type(name) == "string" or name == nil)
136 assert(type(version) == "string" or version == nil) 136 assert(type(version) == "string" or version == nil)
137 assert(type(rocks_provided) == "table" or rocks_provided == nil) 137 assert(type(rocks_provided) == "table" or rocks_provided == nil)
138 assert(type(verify) == "boolean" or verify == nil)
138 deps_mode = deps_mode or "all" 139 deps_mode = deps_mode or "all"
139 rocks_provided = rocks_provided or {} 140 rocks_provided = rocks_provided or {}
140 141
@@ -169,7 +170,12 @@ function deps.fulfill_dependency(dep, deps_mode, name, version, rocks_provided)
169 return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err 170 return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err
170 end 171 end
171 util.printout("Installing "..url) 172 util.printout("Installing "..url)
172 local ok, install_err, errcode = install.command({deps_mode = deps_mode, namespace = dep.namespace}, url) 173 local install_flags = {
174 deps_mode = deps_mode,
175 namespace = dep.namespace,
176 verify = verify,
177 }
178 local ok, install_err, errcode = install.command(install_flags, url)
173 if not ok then 179 if not ok then
174 return nil, "Failed installing dependency: "..url.." - "..install_err, errcode 180 return nil, "Failed installing dependency: "..url.." - "..install_err, errcode
175 end 181 end
@@ -183,11 +189,18 @@ end
183-- Packages are installed using the LuaRocks "install" command. 189-- Packages are installed using the LuaRocks "install" command.
184-- Aborts the program if a dependency could not be fulfilled. 190-- Aborts the program if a dependency could not be fulfilled.
185-- @param rockspec table: A rockspec in table format. 191-- @param rockspec table: A rockspec in table format.
186-- @param depskey table: Rockspec key to fetch to get dependency table. 192-- @param depskey string: Rockspec key to fetch to get dependency table.
193-- @param deps_mode string
194-- @param verify boolean
187-- @return boolean or (nil, string, [string]): True if no errors occurred, or 195-- @return boolean or (nil, string, [string]): True if no errors occurred, or
188-- nil and an error message if any test failed, followed by an optional 196-- nil and an error message if any test failed, followed by an optional
189-- error code. 197-- error code.
190function deps.fulfill_dependencies(rockspec, depskey, deps_mode) 198function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify)
199 assert(type(rockspec) == "table")
200 assert(type(depskey) == "string")
201 assert(type(deps_mode) == "string")
202 assert(type(verify) == "boolean" or verify == nil)
203
191 if rockspec.supported_platforms and next(rockspec.supported_platforms) then 204 if rockspec.supported_platforms and next(rockspec.supported_platforms) then
192 local supported = false 205 local supported = false
193 for _, plat in pairs(rockspec.supported_platforms) do 206 for _, plat in pairs(rockspec.supported_platforms) do
@@ -214,7 +227,7 @@ function deps.fulfill_dependencies(rockspec, depskey, deps_mode)
214 227
215 util.printout() 228 util.printout()
216 for _, dep in ipairs(rockspec[depskey]) do 229 for _, dep in ipairs(rockspec[depskey]) do
217 local ok, err = deps.fulfill_dependency(dep, deps_mode, rockspec.name, rockspec.version, rockspec.rocks_provided) 230 local ok, err = deps.fulfill_dependency(dep, deps_mode, rockspec.name, rockspec.version, rockspec.rocks_provided, verify)
218 if not ok then 231 if not ok then
219 return nil, err 232 return nil, err
220 end 233 end
diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua
index cd78c327..8fa7d6a6 100644
--- a/src/luarocks/fetch.lua
+++ b/src/luarocks/fetch.lua
@@ -5,6 +5,7 @@ local fetch = {}
5local fs = require("luarocks.fs") 5local fs = require("luarocks.fs")
6local dir = require("luarocks.dir") 6local dir = require("luarocks.dir")
7local rockspecs = require("luarocks.rockspecs") 7local rockspecs = require("luarocks.rockspecs")
8local signing = require("luarocks.signing")
8local persist = require("luarocks.persist") 9local persist = require("luarocks.persist")
9local util = require("luarocks.util") 10local util = require("luarocks.util")
10local cfg = require("luarocks.core.cfg") 11local cfg = require("luarocks.core.cfg")
@@ -120,27 +121,52 @@ function fetch.find_base_dir(file, temp_dir, src_url, src_dir)
120 return inferred_dir, found_dir 121 return inferred_dir, found_dir
121end 122end
122 123
124local function fetch_and_verify_signature_for(url, filename, tmpdir)
125 local sig_url = signing.signature_url(url)
126 local sig_file, err, errcode = fetch.fetch_url_at_temp_dir(sig_url, tmpdir)
127 if not sig_file then
128 return nil, "Could not fetch signature file for verification: " .. err, errcode
129 end
130
131 local ok, err = signing.verify_signature(filename, sig_file)
132 if not ok then
133 return nil, "Failed signature verification: " .. err
134 end
135
136 return fs.absolute_name(sig_file)
137end
138
123--- Obtain a rock and unpack it. 139--- Obtain a rock and unpack it.
124-- If a directory is not given, a temporary directory will be created, 140-- If a directory is not given, a temporary directory will be created,
125-- which will be deleted on program termination. 141-- which will be deleted on program termination.
126-- @param rock_file string: URL or filename of the rock. 142-- @param rock_file string: URL or filename of the rock.
127-- @param dest string or nil: if given, directory will be used as 143-- @param dest string or nil: if given, directory will be used as
128-- a permanent destination. 144-- a permanent destination.
145-- @param verify boolean: if true, download and verify signature for rockspec
129-- @return string or (nil, string, [string]): the directory containing the contents 146-- @return string or (nil, string, [string]): the directory containing the contents
130-- of the unpacked rock. 147-- of the unpacked rock.
131function fetch.fetch_and_unpack_rock(rock_file, dest) 148function fetch.fetch_and_unpack_rock(url, dest, verify)
132 assert(type(rock_file) == "string") 149 assert(type(url) == "string")
133 assert(type(dest) == "string" or not dest) 150 assert(type(dest) == "string" or not dest)
134 151
135 local name = dir.base_name(rock_file):match("(.*)%.[^.]*%.rock") 152 local name = dir.base_name(url):match("(.*)%.[^.]*%.rock")
136 153 local tmpname = "luarocks-rock-" .. name
137 local err, errcode 154
138 rock_file, err, errcode = fetch.fetch_url_at_temp_dir(rock_file,"luarocks-rock-"..name) 155 local rock_file, err, errcode = fetch.fetch_url_at_temp_dir(url, tmpname)
139 if not rock_file then 156 if not rock_file then
140 return nil, "Could not fetch rock file: " .. err, errcode 157 return nil, "Could not fetch rock file: " .. err, errcode
141 end 158 end
142 159
160 local sig_file
161 if verify then
162 sig_file, err = fetch_and_verify_signature_for(url, rock_file, tmpname)
163 if err then
164 return nil, err
165 end
166 end
167
143 rock_file = fs.absolute_name(rock_file) 168 rock_file = fs.absolute_name(rock_file)
169
144 local unpack_dir 170 local unpack_dir
145 if dest then 171 if dest then
146 unpack_dir = dest 172 unpack_dir = dest
@@ -163,6 +189,12 @@ function fetch.fetch_and_unpack_rock(rock_file, dest)
163 if not ok then 189 if not ok then
164 return nil, "Failed unpacking rock file: " .. rock_file .. ": " .. err 190 return nil, "Failed unpacking rock file: " .. rock_file .. ": " .. err
165 end 191 end
192 if sig_file then
193 ok, err = fs.copy(sig_file, ".")
194 if not ok then
195 return nil, "Failed copying signature file"
196 end
197 end
166 fs.pop_dir() 198 fs.pop_dir()
167 return unpack_dir 199 return unpack_dir
168end 200end
@@ -210,35 +242,44 @@ end
210-- @param filename string: Local or remote filename of a rockspec. 242-- @param filename string: Local or remote filename of a rockspec.
211-- @param location string or nil: Where to download. If not given, 243-- @param location string or nil: Where to download. If not given,
212-- a temporary dir is created. 244-- a temporary dir is created.
245-- @param verify boolean: if true, download and verify signature for rockspec
213-- @return table or (nil, string, [string]): A table representing the rockspec 246-- @return table or (nil, string, [string]): A table representing the rockspec
214-- or nil followed by an error message and optional error code. 247-- or nil followed by an error message and optional error code.
215function fetch.load_rockspec(filename, location) 248function fetch.load_rockspec(url, location, verify)
216 assert(type(filename) == "string") 249 assert(type(url) == "string")
217 250
218 local name 251 local name
219 local basename = dir.base_name(filename) 252 local basename = dir.base_name(url)
220 if basename == "rockspec" then 253 if basename == "rockspec" then
221 name = "rockspec" 254 name = "rockspec"
222 else 255 else
223 name = basename:match("(.*)%.rockspec") 256 name = basename:match("(.*)%.rockspec")
224 if not name then 257 if not name then
225 return nil, "Filename '"..filename.."' does not look like a rockspec." 258 return nil, "Filename '"..url.."' does not look like a rockspec."
226 end 259 end
227 end 260 end
228 261
229 local err, errcode 262 local tmpname = "luarocks-rockspec-"..name
263 local filename, err, errcode
230 if location then 264 if location then
231 local ok, err = fs.change_dir(location) 265 local ok, err = fs.change_dir(location)
232 if not ok then return nil, err end 266 if not ok then return nil, err end
233 filename, err = fetch.fetch_url(filename) 267 filename, err = fetch.fetch_url(url)
234 fs.pop_dir() 268 fs.pop_dir()
235 else 269 else
236 filename, err, errcode = fetch.fetch_url_at_temp_dir(filename,"luarocks-rockspec-"..name) 270 filename, err, errcode = fetch.fetch_url_at_temp_dir(url, tmpname)
237 end 271 end
238 if not filename then 272 if not filename then
239 return nil, err, errcode 273 return nil, err, errcode
240 end 274 end
241 275
276 if verify then
277 local _, err = fetch_and_verify_signature_for(url, filename, tmpname)
278 if err then
279 return nil, err
280 end
281 end
282
242 return fetch.load_local_rockspec(filename) 283 return fetch.load_local_rockspec(filename)
243end 284end
244 285
diff --git a/src/luarocks/pack.lua b/src/luarocks/pack.lua
index 3955af3d..336b9167 100644
--- a/src/luarocks/pack.lua
+++ b/src/luarocks/pack.lua
@@ -14,6 +14,7 @@ local util = require("luarocks.util")
14local dir = require("luarocks.dir") 14local dir = require("luarocks.dir")
15local manif = require("luarocks.manif") 15local manif = require("luarocks.manif")
16local search = require("luarocks.search") 16local search = require("luarocks.search")
17local signing = require("luarocks.signing")
17 18
18--- Create a source rock. 19--- Create a source rock.
19-- Packages a rockspec and its required source files in a rock 20-- Packages a rockspec and its required source files in a rock
@@ -125,7 +126,26 @@ function pack.pack_installed_rock(query, tree)
125 return rock_file 126 return rock_file
126end 127end
127 128
128function pack.pack_binary_rock(name, version, cmd) 129function pack.report_and_sign_local_file(file, err, sign)
130 if err then
131 return nil, err
132 end
133 local sigfile
134 if sign then
135 sigfile, err = signing.sign_file(file)
136 util.printout()
137 end
138 util.printout("Packed: "..file)
139 if sigfile then
140 util.printout("Sigature stored in: "..sigfile)
141 end
142 if err then
143 return nil, err
144 end
145 return true
146end
147
148function pack.pack_binary_rock(name, version, sign, cmd)
129 149
130 -- The --pack-binary-rock option for "luarocks build" basically performs 150 -- The --pack-binary-rock option for "luarocks build" basically performs
131 -- "luarocks build" on a temporary tree and then "luarocks pack". The 151 -- "luarocks build" on a temporary tree and then "luarocks pack". The
@@ -150,7 +170,8 @@ function pack.pack_binary_rock(name, version, cmd)
150 rname, rversion = name, version 170 rname, rversion = name, version
151 end 171 end
152 local query = queries.new(rname, rversion) 172 local query = queries.new(rname, rversion)
153 return pack.pack_installed_rock(query, temp_dir) 173 local file, err = pack.pack_installed_rock(query, temp_dir)
174 return pack.report_and_sign_local_file(file, err, sign)
154end 175end
155 176
156return pack 177return pack
diff --git a/src/luarocks/signing.lua b/src/luarocks/signing.lua
index 7503768e..2e61041e 100644
--- a/src/luarocks/signing.lua
+++ b/src/luarocks/signing.lua
@@ -3,13 +3,25 @@ local signing = {}
3local cfg = require("luarocks.core.cfg") 3local cfg = require("luarocks.core.cfg")
4local fs = require("luarocks.fs") 4local fs = require("luarocks.fs")
5 5
6function signing.sign_file(file) 6local function get_gpg()
7 local vars = cfg.variables 7 local vars = cfg.variables
8 local gpg_ok, err = fs.is_tool_available(vars.GPG, "gpg") 8 local gpg = vars.GPG
9 local gpg_ok, err = fs.is_tool_available(gpg, "gpg")
9 if not gpg_ok then 10 if not gpg_ok then
10 return nil, err 11 return nil, err
11 end 12 end
12 local gpg = vars.GPG 13 return gpg
14end
15
16function signing.signature_url(url)
17 return url .. ".asc"
18end
19
20function signing.sign_file(file)
21 local gpg, err = get_gpg()
22 if not gpg then
23 return nil, err
24 end
13 25
14 local sigfile = file .. ".asc" 26 local sigfile = file .. ".asc"
15 if fs.execute(gpg, "--armor", "--output", sigfile, "--detach-sign", file) then 27 if fs.execute(gpg, "--armor", "--output", sigfile, "--detach-sign", file) then
@@ -19,4 +31,18 @@ function signing.sign_file(file)
19 end 31 end
20end 32end
21 33
34function signing.verify_signature(file, sigfile)
35 local gpg, err = get_gpg()
36 if not gpg then
37 return nil, err
38 end
39
40 if fs.execute(gpg, "--verify", sigfile, file) then
41 return true
42 else
43 return nil, "GPG returned a verification error"
44 end
45
46end
47
22return signing 48return signing
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua
index e370e688..2ad59d46 100644
--- a/src/luarocks/util.lua
+++ b/src/luarocks/util.lua
@@ -162,6 +162,7 @@ local supported_flags = {
162 ["tree"] = "<path>", 162 ["tree"] = "<path>",
163 ["user-config"] = true, 163 ["user-config"] = true,
164 ["verbose"] = true, 164 ["verbose"] = true,
165 ["verify"] = true,
165 ["version"] = true, 166 ["version"] = true,
166} 167}
167 168