diff options
-rw-r--r-- | src/luarocks/deps.lua | 14 | ||||
-rw-r--r-- | src/luarocks/new_version.lua | 84 | ||||
-rw-r--r-- | src/luarocks/tools/zip.lua | 56 | ||||
-rw-r--r-- | src/luarocks/upload/api.lua | 21 | ||||
-rwxr-xr-x | test/testing.sh | 1 |
5 files changed, 114 insertions, 62 deletions
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua index eb01075c..acc571f8 100644 --- a/src/luarocks/deps.lua +++ b/src/luarocks/deps.lua | |||
@@ -247,12 +247,16 @@ end | |||
247 | function deps.show_dep(dep, internal) | 247 | function deps.show_dep(dep, internal) |
248 | assert(type(dep) == "table") | 248 | assert(type(dep) == "table") |
249 | assert(type(internal) == "boolean" or not internal) | 249 | assert(type(internal) == "boolean" or not internal) |
250 | 250 | ||
251 | local pretty = {} | 251 | if #dep.constraints > 0 then |
252 | for _, c in ipairs(dep.constraints) do | 252 | local pretty = {} |
253 | table.insert(pretty, c.op .. " " .. deps.show_version(c.version, internal)) | 253 | for _, c in ipairs(dep.constraints) do |
254 | table.insert(pretty, c.op .. " " .. deps.show_version(c.version, internal)) | ||
255 | end | ||
256 | return dep.name.." "..table.concat(pretty, ", ") | ||
257 | else | ||
258 | return dep.name | ||
254 | end | 259 | end |
255 | return dep.name.." "..table.concat(pretty, ", ") | ||
256 | end | 260 | end |
257 | 261 | ||
258 | --- A more lenient check for equivalence between versions. | 262 | --- A more lenient check for equivalence between versions. |
diff --git a/src/luarocks/new_version.lua b/src/luarocks/new_version.lua index 9ef0cfbb..6969d4b2 100644 --- a/src/luarocks/new_version.lua +++ b/src/luarocks/new_version.lua | |||
@@ -1,9 +1,7 @@ | |||
1 | 1 | ||
2 | --- Module implementing the LuaRocks "new_version" command. | 2 | --- Module implementing the LuaRocks "new_version" command. |
3 | -- Utility function that writes a new rockspec, updating data from a previous one. | 3 | -- Utility function that writes a new rockspec, updating data from a previous one. |
4 | --module("luarocks.new_version", package.seeall) | ||
5 | local new_version = {} | 4 | local new_version = {} |
6 | package.loaded["luarocks.new_version"] = new_version | ||
7 | 5 | ||
8 | local util = require("luarocks.util") | 6 | local util = require("luarocks.util") |
9 | local download = require("luarocks.download") | 7 | local download = require("luarocks.download") |
@@ -13,7 +11,7 @@ local fs = require("luarocks.fs") | |||
13 | local type_check = require("luarocks.type_check") | 11 | local type_check = require("luarocks.type_check") |
14 | 12 | ||
15 | new_version.help_summary = "Auto-write a rockspec for a new version of a rock." | 13 | new_version.help_summary = "Auto-write a rockspec for a new version of a rock." |
16 | new_version.help_arguments = "{<package>|<rockspec>} [<new_version>] [<new_url>]" | 14 | new_version.help_arguments = "[--tag=<tag>] {<package>|<rockspec>} [<new_version>] [<new_url>]" |
17 | new_version.help = [[ | 15 | new_version.help = [[ |
18 | This is a utility function that writes a new rockspec, updating data | 16 | This is a utility function that writes a new rockspec, updating data |
19 | from a previous one. | 17 | from a previous one. |
@@ -21,8 +19,10 @@ from a previous one. | |||
21 | If a package name is given, it downloads the latest rockspec from the | 19 | If a package name is given, it downloads the latest rockspec from the |
22 | default server. If a rockspec is given, it uses it instead. | 20 | default server. If a rockspec is given, it uses it instead. |
23 | 21 | ||
24 | If the version number is not given, it only increments the revision | 22 | If the version number is not given and tag is passed using --tag, |
25 | number of the given (or downloaded) rockspec. | 23 | it is used as the version, with 'v' removed from beginning. |
24 | Otherwise, it only increments the revision number of the given | ||
25 | (or downloaded) rockspec. | ||
26 | 26 | ||
27 | If a URL is given, it replaces the one from the old rockspec with the | 27 | If a URL is given, it replaces the one from the old rockspec with the |
28 | given URL. If a URL is not given and a new version is given, it tries | 28 | given URL. If a URL is not given and a new version is given, it tries |
@@ -30,6 +30,9 @@ to guess the new URL by replacing occurrences of the version number | |||
30 | in the URL or tag. It also tries to download the new URL to determine | 30 | in the URL or tag. It also tries to download the new URL to determine |
31 | the new MD5 checksum. | 31 | the new MD5 checksum. |
32 | 32 | ||
33 | If a tag is given, it replaces the one from the old rockspec. If there is | ||
34 | an old tag but no new one passed, it is guessed in the same way URL is. | ||
35 | |||
33 | WARNING: it writes the new rockspec to the current directory, | 36 | WARNING: it writes the new rockspec to the current directory, |
34 | overwriting the file if it already exists. | 37 | overwriting the file if it already exists. |
35 | ]] | 38 | ]] |
@@ -48,58 +51,73 @@ local function try_replace(tbl, field, old, new) | |||
48 | return false | 51 | return false |
49 | end | 52 | end |
50 | 53 | ||
51 | local function check_url_and_update_md5(out_rs, out_name) | 54 | -- Try to download source file using URL from a rockspec. |
52 | local old_md5 = out_rs.source.md5 | 55 | -- If it specified MD5, update it. |
53 | out_rs.source.md5 = nil | 56 | -- @return (true, false) if MD5 was not specified or it stayed same, |
54 | local file, temp_dir = fetch.fetch_url_at_temp_dir(out_rs.source.url, "luarocks-new-version-"..out_name) | 57 | -- (true, true) if MD5 changed, (nil, string) on error. |
58 | local function check_url_and_update_md5(out_rs) | ||
59 | local file, temp_dir = fetch.fetch_url_at_temp_dir(out_rs.source.url, "luarocks-new-version-"..out_rs.package) | ||
55 | if not file then | 60 | if not file then |
56 | util.printerr("Warning: invalid URL - "..temp_dir) | 61 | util.printerr("Warning: invalid URL - "..temp_dir) |
57 | return true | 62 | return true, false |
58 | end | 63 | end |
59 | util.printout("File successfully downloaded. Updating MD5 checksum...") | 64 | |
60 | out_rs.source.md5 = fs.get_md5(file) | ||
61 | local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, out_rs.source.url, out_rs.source.dir) | 65 | local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, out_rs.source.url, out_rs.source.dir) |
62 | if not inferred_dir then | 66 | if not inferred_dir then |
63 | return nil, found_dir | 67 | return nil, found_dir |
64 | end | 68 | end |
69 | |||
65 | if found_dir and found_dir ~= inferred_dir then | 70 | if found_dir and found_dir ~= inferred_dir then |
66 | out_rs.source.dir = found_dir | 71 | out_rs.source.dir = found_dir |
67 | end | 72 | end |
68 | return out_rs.source.md5 ~= old_md5 | 73 | |
74 | if file then | ||
75 | if out_rs.source.md5 then | ||
76 | util.printout("File successfully downloaded. Updating MD5 checksum...") | ||
77 | local new_md5, err = fs.get_md5(file) | ||
78 | if not new_md5 then | ||
79 | return nil, err | ||
80 | end | ||
81 | local old_md5 = out_rs.source.md5 | ||
82 | out_rs.source.md5 = new_md5 | ||
83 | return true, new_md5 ~= old_md5 | ||
84 | else | ||
85 | util.printout("File successfully downloaded.") | ||
86 | return true, false | ||
87 | end | ||
88 | end | ||
69 | end | 89 | end |
70 | 90 | ||
71 | local function update_source_section(out_rs, out_name, url, old_ver, new_ver) | 91 | local function update_source_section(out_rs, url, tag, old_ver, new_ver) |
92 | if tag then | ||
93 | out_rs.source.tag = tag | ||
94 | end | ||
72 | if url then | 95 | if url then |
73 | out_rs.source.url = url | 96 | out_rs.source.url = url |
74 | check_url_and_update_md5(out_rs, out_name) | 97 | return check_url_and_update_md5(out_rs) |
75 | return true | ||
76 | end | 98 | end |
77 | if new_ver == old_ver then | 99 | if new_ver == old_ver then |
78 | return true | 100 | return true |
79 | end | 101 | end |
80 | if not out_rs.source then | ||
81 | return nil, "'source' table is missing. Invalid rockspec?" | ||
82 | end | ||
83 | if out_rs.source.dir then | 102 | if out_rs.source.dir then |
84 | try_replace(out_rs.source, "dir", old_ver, new_ver) | 103 | try_replace(out_rs.source, "dir", old_ver, new_ver) |
85 | end | 104 | end |
86 | if out_rs.source.file then | 105 | if out_rs.source.file then |
87 | try_replace(out_rs.source, "file", old_ver, new_ver) | 106 | try_replace(out_rs.source, "file", old_ver, new_ver) |
88 | end | 107 | end |
89 | local ok = try_replace(out_rs.source, "url", old_ver, new_ver) | 108 | if try_replace(out_rs.source, "url", old_ver, new_ver) then |
90 | if ok then | 109 | return check_url_and_update_md5(out_rs) |
91 | check_url_and_update_md5(out_rs, out_name) | 110 | end |
111 | if tag or try_replace(out_rs.source, "tag", old_ver, new_ver) then | ||
92 | return true | 112 | return true |
93 | end | 113 | end |
94 | ok = try_replace(out_rs.source, "tag", old_ver, new_ver) | 114 | -- Couldn't replace anything significant, use the old URL. |
115 | local ok, md5_changed = check_url_and_update_md5(out_rs) | ||
95 | if not ok then | 116 | if not ok then |
96 | ok = check_url_and_update_md5(out_rs, out_name) | 117 | return nil, md5_changed |
97 | if ok then | ||
98 | util.printerr("Warning: URL is the same, but MD5 has changed. Old rockspec is broken.") | ||
99 | end | ||
100 | end | 118 | end |
101 | if not ok then | 119 | if md5_changed then |
102 | return nil, "Failed to determine the location of the new version." | 120 | util.printerr("Warning: URL is the same, but MD5 has changed. Old rockspec is broken.") |
103 | end | 121 | end |
104 | return true | 122 | return true |
105 | end | 123 | end |
@@ -107,7 +125,7 @@ end | |||
107 | function new_version.run(...) | 125 | function new_version.run(...) |
108 | local flags, input, version, url = util.parse_flags(...) | 126 | local flags, input, version, url = util.parse_flags(...) |
109 | if not input then | 127 | if not input then |
110 | return nil, "Missing arguments: expected program or rockspec. "..util.see_help("new_version") | 128 | return nil, "Missing argument: expected package or rockspec. "..util.see_help("new_version") |
111 | end | 129 | end |
112 | assert(type(input) == "string") | 130 | assert(type(input) == "string") |
113 | 131 | ||
@@ -127,6 +145,10 @@ function new_version.run(...) | |||
127 | 145 | ||
128 | local old_ver, old_rev = valid_rs.version:match("(.*)%-(%d+)$") | 146 | local old_ver, old_rev = valid_rs.version:match("(.*)%-(%d+)$") |
129 | local new_ver, new_rev | 147 | local new_ver, new_rev |
148 | |||
149 | if flags.tag and not version then | ||
150 | version = flags.tag:gsub("^v", "") | ||
151 | end | ||
130 | 152 | ||
131 | if version then | 153 | if version then |
132 | new_ver, new_rev = version:match("(.*)%-(%d+)$") | 154 | new_ver, new_rev = version:match("(.*)%-(%d+)$") |
@@ -145,7 +167,7 @@ function new_version.run(...) | |||
145 | local out_name = out_rs.package:lower() | 167 | local out_name = out_rs.package:lower() |
146 | out_rs.version = new_rockver.."-"..new_rev | 168 | out_rs.version = new_rockver.."-"..new_rev |
147 | 169 | ||
148 | local ok, err = update_source_section(out_rs, out_name, url, old_ver, new_ver) | 170 | local ok, err = update_source_section(out_rs, url, flags.tag, old_ver, new_ver) |
149 | if not ok then return nil, err end | 171 | if not ok then return nil, err end |
150 | 172 | ||
151 | if out_rs.build and out_rs.build.type == "module" then | 173 | if out_rs.build and out_rs.build.type == "module" then |
diff --git a/src/luarocks/tools/zip.lua b/src/luarocks/tools/zip.lua index 101cae82..e6d9e36a 100644 --- a/src/luarocks/tools/zip.lua +++ b/src/luarocks/tools/zip.lua | |||
@@ -1,13 +1,35 @@ | |||
1 | 1 | ||
2 | --- A Lua implementation of .zip file archiving (used for creating .rock files), | 2 | --- A Lua implementation of .zip file archiving (used for creating .rock files), |
3 | -- using only lzlib. | 3 | -- using only lzlib or lua-lzib. |
4 | --module("luarocks.tools.zip", package.seeall) | ||
5 | local zip = {} | 4 | local zip = {} |
6 | 5 | ||
7 | local zlib = require("zlib") | 6 | local zlib = require("zlib") |
8 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
9 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
10 | 9 | ||
10 | -- zlib module can be provided by both lzlib and lua-lzib packages. | ||
11 | -- Create a compatibility layer. | ||
12 | local zlib_compress, zlib_crc32 | ||
13 | if zlib._VERSION:match "^lua%-zlib" then | ||
14 | function zlib_compress(data) | ||
15 | return (zlib.deflate()(data, "finish")) | ||
16 | end | ||
17 | |||
18 | function zlib_crc32(data) | ||
19 | return zlib.crc32()(data) | ||
20 | end | ||
21 | elseif zlib._VERSION:match "^lzlib" then | ||
22 | function zlib_compress(data) | ||
23 | return zlib.compress(data) | ||
24 | end | ||
25 | |||
26 | function zlib_crc32(data) | ||
27 | return zlib.crc32(zlib.crc32(), data) | ||
28 | end | ||
29 | else | ||
30 | error("unknown zlib library", 0) | ||
31 | end | ||
32 | |||
11 | local function number_to_bytestring(number, nbytes) | 33 | local function number_to_bytestring(number, nbytes) |
12 | local out = {} | 34 | local out = {} |
13 | for _ = 1, nbytes do | 35 | for _ = 1, nbytes do |
@@ -31,32 +53,28 @@ local function zipwriter_open_new_file_in_zip(self, filename) | |||
31 | self.local_file_header = lfh | 53 | self.local_file_header = lfh |
32 | lfh.last_mod_file_time = 0 -- TODO | 54 | lfh.last_mod_file_time = 0 -- TODO |
33 | lfh.last_mod_file_date = 0 -- TODO | 55 | lfh.last_mod_file_date = 0 -- TODO |
34 | lfh.crc32 = 0 -- initial value | ||
35 | lfh.compressed_size = 0 -- unknown yet | ||
36 | lfh.uncompressed_size = 0 -- unknown yet | ||
37 | lfh.file_name_length = #filename | 56 | lfh.file_name_length = #filename |
38 | lfh.extra_field_length = 0 | 57 | lfh.extra_field_length = 0 |
39 | lfh.file_name = filename:gsub("\\", "/") | 58 | lfh.file_name = filename:gsub("\\", "/") |
40 | lfh.external_attr = 0 -- TODO properly store permissions | 59 | lfh.external_attr = 0 -- TODO properly store permissions |
41 | self.in_open_file = true | 60 | self.in_open_file = true |
42 | self.data = {} | ||
43 | return true | 61 | return true |
44 | end | 62 | end |
45 | 63 | ||
46 | --- Write data to the file currently being stored in the zipfile. | 64 | --- Write data to the file currently being stored in the zipfile. |
47 | -- @param self handle of the zipfile being written. | 65 | -- @param self handle of the zipfile being written. |
48 | -- @param buf string containing data to be written. | 66 | -- @param data string containing full contents of the file. |
49 | -- @return true if succeeded, nil in case of failure. | 67 | -- @return true if succeeded, nil in case of failure. |
50 | local function zipwriter_write_file_in_zip(self, buf) | 68 | local function zipwriter_write_file_in_zip(self, data) |
51 | if not self.in_open_file then | 69 | if not self.in_open_file then |
52 | return nil | 70 | return nil |
53 | end | 71 | end |
54 | local lfh = self.local_file_header | 72 | local lfh = self.local_file_header |
55 | local cbuf = zlib.compress(buf):sub(3, -5) | 73 | local compressed = zlib_compress(data):sub(3, -5) |
56 | lfh.crc32 = zlib.crc32(lfh.crc32, buf) | 74 | lfh.crc32 = zlib_crc32(data) |
57 | lfh.compressed_size = lfh.compressed_size + #cbuf | 75 | lfh.compressed_size = #compressed |
58 | lfh.uncompressed_size = lfh.uncompressed_size + #buf | 76 | lfh.uncompressed_size = #data |
59 | table.insert(self.data, cbuf) | 77 | self.data = compressed |
60 | return true | 78 | return true |
61 | end | 79 | end |
62 | 80 | ||
@@ -86,10 +104,8 @@ local function zipwriter_close_file_in_zip(self) | |||
86 | zh:write(number_to_bytestring(lfh.extra_field_length, 2)) | 104 | zh:write(number_to_bytestring(lfh.extra_field_length, 2)) |
87 | zh:write(lfh.file_name) | 105 | zh:write(lfh.file_name) |
88 | 106 | ||
89 | -- File data | 107 | -- File data |
90 | for _, cbuf in ipairs(self.data) do | 108 | zh:write(self.data) |
91 | zh:write(cbuf) | ||
92 | end | ||
93 | 109 | ||
94 | -- Data descriptor | 110 | -- Data descriptor |
95 | zh:write(number_to_bytestring(lfh.crc32, 4)) | 111 | zh:write(number_to_bytestring(lfh.crc32, 4)) |
@@ -117,12 +133,12 @@ local function zipwriter_add(self, file) | |||
117 | end | 133 | end |
118 | end | 134 | end |
119 | if ok then | 135 | if ok then |
120 | local buf = fin:read("*a") | 136 | local data = fin:read("*a") |
121 | if not buf then | 137 | if not data then |
122 | err = "error reading "..file | 138 | err = "error reading "..file |
123 | ok = false | 139 | ok = false |
124 | else | 140 | else |
125 | ok = self:write_file_in_zip(buf) | 141 | ok = self:write_file_in_zip(data) |
126 | if not ok then | 142 | if not ok then |
127 | err = "error in writing "..file.." in the zipfile" | 143 | err = "error in writing "..file.." in the zipfile" |
128 | end | 144 | end |
diff --git a/src/luarocks/upload/api.lua b/src/luarocks/upload/api.lua index 2cf462fb..6df24569 100644 --- a/src/luarocks/upload/api.lua +++ b/src/luarocks/upload/api.lua | |||
@@ -106,13 +106,22 @@ end | |||
106 | 106 | ||
107 | -- An ode to the multitude of JSON libraries out there... | 107 | -- An ode to the multitude of JSON libraries out there... |
108 | local function require_json() | 108 | local function require_json() |
109 | for _, lib in ipairs({ "cjson", "dkjson", "json" }) do | 109 | local list = { "cjson", "dkjson", "json" } |
110 | for _, lib in ipairs(list) do | ||
110 | local json_ok, json = pcall(require, lib) | 111 | local json_ok, json = pcall(require, lib) |
111 | if json_ok then | 112 | if json_ok then |
112 | return json_ok, json | 113 | return json_ok, json |
113 | end | 114 | end |
114 | end | 115 | end |
115 | return nil | 116 | local errmsg = "Failed loading " |
117 | for i, name in ipairs(list) do | ||
118 | if i == #list then | ||
119 | errmsg = errmsg .."and '"..name.."'. Use 'luarocks search <partial-name>' to search for a library and 'luarocks install <name>' to install one." | ||
120 | else | ||
121 | errmsg = errmsg .."'"..name.."', " | ||
122 | end | ||
123 | end | ||
124 | return nil, errmsg | ||
116 | end | 125 | end |
117 | 126 | ||
118 | local function redact_api_url(url) | 127 | local function redact_api_url(url) |
@@ -126,12 +135,12 @@ if not ltn12_ok then -- If not using LuaSocket and/or LuaSec... | |||
126 | function Api:request(url, params, post_params) | 135 | function Api:request(url, params, post_params) |
127 | local vars = cfg.variables | 136 | local vars = cfg.variables |
128 | local json_ok, json = require_json() | 137 | local json_ok, json = require_json() |
129 | if not json_ok then return nil, "A JSON library is required for this command." end | 138 | if not json_ok then return nil, "A JSON library is required for this command. "..json end |
130 | 139 | ||
131 | if cfg.downloader == "wget" then | 140 | if cfg.downloader == "wget" then |
132 | local curl_ok = fs.execute_quiet(vars.CURL, "--version") | 141 | local curl_ok, err = fs.is_tool_available(vars.CURL, "curl") |
133 | if not curl_ok then | 142 | if not curl_ok then |
134 | return nil, "Missing network helper program 'curl'.\nMake sure 'curl' is installed and available from your path." | 143 | return nil, err |
135 | end | 144 | end |
136 | end | 145 | end |
137 | 146 | ||
@@ -192,7 +201,7 @@ local warned_luasec = false | |||
192 | 201 | ||
193 | function Api:request(url, params, post_params) | 202 | function Api:request(url, params, post_params) |
194 | local json_ok, json = require_json() | 203 | local json_ok, json = require_json() |
195 | if not json_ok then return nil, "A JSON library is required for this command." end | 204 | if not json_ok then return nil, "A JSON library is required for this command. "..json end |
196 | local server = tostring(self.config.server) | 205 | local server = tostring(self.config.server) |
197 | local http_ok, http | 206 | local http_ok, http |
198 | local via = "luasocket" | 207 | local via = "luasocket" |
diff --git a/test/testing.sh b/test/testing.sh index 44e78205..74b39b8f 100755 --- a/test/testing.sh +++ b/test/testing.sh | |||
@@ -427,6 +427,7 @@ fail_make_which_rockspec() { rm -rf ./luasocket-${verrev_luasocket} && $luarocks | |||
427 | 427 | ||
428 | test_new_version() { $luarocks download --rockspec luacov ${version_luacov} && $luarocks new_version ./luacov-${version_luacov}-1.rockspec 0.2 && rm ./luacov-0.*; } | 428 | test_new_version() { $luarocks download --rockspec luacov ${version_luacov} && $luarocks new_version ./luacov-${version_luacov}-1.rockspec 0.2 && rm ./luacov-0.*; } |
429 | test_new_version_url() { $luarocks download --rockspec abelhas 1.0 && $luarocks new_version ./abelhas-1.0-1.rockspec 1.1 https://github.com/downloads/ittner/abelhas/abelhas-1.1.tar.gz && rm ./abelhas-*; } | 429 | test_new_version_url() { $luarocks download --rockspec abelhas 1.0 && $luarocks new_version ./abelhas-1.0-1.rockspec 1.1 https://github.com/downloads/ittner/abelhas/abelhas-1.1.tar.gz && rm ./abelhas-*; } |
430 | test_new_version_tag() { $luarocks download --rockspec luacov ${version_luacov} && $luarocks new_version ./luacov-${version_luacov}-1.rockspec --tag v0.3 && rm ./luacov-0.3-1.rockspec; } | ||
430 | 431 | ||
431 | test_pack() { $luarocks list && $luarocks pack luacov && rm ./luacov-*.rock; } | 432 | test_pack() { $luarocks list && $luarocks pack luacov && rm ./luacov-*.rock; } |
432 | test_pack_src() { $luarocks install $luasec && $luarocks download --rockspec luasocket && $luarocks pack ./luasocket-${verrev_luasocket}.rockspec && rm ./luasocket-${version_luasocket}-*.rock; } | 433 | test_pack_src() { $luarocks install $luasec && $luarocks download --rockspec luasocket && $luarocks pack ./luasocket-${verrev_luasocket}.rockspec && rm ./luasocket-${version_luasocket}-*.rock; } |