diff options
-rw-r--r-- | src/luarocks/cfg.lua | 4 | ||||
-rw-r--r-- | src/luarocks/deps.lua | 15 | ||||
-rw-r--r-- | src/luarocks/fetch.lua | 4 | ||||
-rw-r--r-- | src/luarocks/fs/lua.lua | 83 | ||||
-rw-r--r-- | src/luarocks/manif.lua | 4 | ||||
-rw-r--r-- | src/luarocks/manif_core.lua | 4 | ||||
-rw-r--r-- | src/luarocks/persist.lua | 10 | ||||
-rw-r--r-- | src/luarocks/tools/zip.lua | 187 | ||||
-rw-r--r-- | src/luarocks/util.lua | 16 |
9 files changed, 168 insertions, 159 deletions
diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua index d1735ff0..4bb376a4 100644 --- a/src/luarocks/cfg.lua +++ b/src/luarocks/cfg.lua | |||
@@ -243,12 +243,12 @@ if detected.unix then | |||
243 | defaults.variables.LIBFLAG = "-shared" | 243 | defaults.variables.LIBFLAG = "-shared" |
244 | defaults.external_deps_patterns = { | 244 | defaults.external_deps_patterns = { |
245 | bin = { "?" }, | 245 | bin = { "?" }, |
246 | lib = { "lib?.a", "lib?.so" }, | 246 | lib = { "lib?.a", "lib?.so", "lib?.so.*" }, |
247 | include = { "?.h" } | 247 | include = { "?.h" } |
248 | } | 248 | } |
249 | defaults.runtime_external_deps_patterns = { | 249 | defaults.runtime_external_deps_patterns = { |
250 | bin = { "?" }, | 250 | bin = { "?" }, |
251 | lib = { "lib?.so" }, | 251 | lib = { "lib?.so", "lib?.so.*" }, |
252 | include = { "?.h" } | 252 | include = { "?.h" } |
253 | } | 253 | } |
254 | defaults.local_cache = home.."/.cache/luarocks" | 254 | defaults.local_cache = home.."/.cache/luarocks" |
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua index b10594a3..4f16c2a6 100644 --- a/src/luarocks/deps.lua +++ b/src/luarocks/deps.lua | |||
@@ -543,9 +543,18 @@ function check_external_deps(rockspec, mode) | |||
543 | if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then | 543 | if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then |
544 | f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension) | 544 | f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension) |
545 | end | 545 | end |
546 | local testfile = dir.path(dirdata.dir, f) | 546 | if f:match("%*") then |
547 | if fs.exists(testfile) then | 547 | local replaced = f:gsub("%.", "%%."):gsub("%*", ".*") |
548 | found = true | 548 | for _, entry in ipairs(fs.list_dir(dirdata.dir)) do |
549 | if entry:match(replaced) then | ||
550 | found = true | ||
551 | break | ||
552 | end | ||
553 | end | ||
554 | else | ||
555 | found = fs.exists(dir.path(dirdata.dir, f)) | ||
556 | end | ||
557 | if found then | ||
549 | break | 558 | break |
550 | else | 559 | else |
551 | if failed_file then | 560 | if failed_file then |
diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua index 25add66a..ff77882e 100644 --- a/src/luarocks/fetch.lua +++ b/src/luarocks/fetch.lua | |||
@@ -30,9 +30,9 @@ function fetch_url(url, filename) | |||
30 | if protocol == "file" then | 30 | if protocol == "file" then |
31 | return fs.absolute_name(pathname) | 31 | return fs.absolute_name(pathname) |
32 | elseif protocol == "http" or protocol == "ftp" or protocol == "https" then | 32 | elseif protocol == "http" or protocol == "ftp" or protocol == "https" then |
33 | local ok = fs.download(url, filename) | 33 | local ok, err = fs.download(url, filename) |
34 | if not ok then | 34 | if not ok then |
35 | return nil, "Failed downloading "..url, "network" | 35 | return nil, "Failed downloading "..url.." - "..err, "network" |
36 | end | 36 | end |
37 | return dir.path(fs.current_dir(), filename or dir.base_name(url)) | 37 | return dir.path(fs.current_dir(), filename or dir.base_name(url)) |
38 | else | 38 | else |
diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua index a9fca7b4..e055f67e 100644 --- a/src/luarocks/fs/lua.lua +++ b/src/luarocks/fs/lua.lua | |||
@@ -478,50 +478,27 @@ end | |||
478 | if socket_ok then | 478 | if socket_ok then |
479 | 479 | ||
480 | local ltn12 = require("ltn12") | 480 | local ltn12 = require("ltn12") |
481 | 481 | local luasec_ok, https = pcall(require, "ssl.https") | |
482 | --- Download a remote file. | 482 | |
483 | -- @param url string: URL to be fetched. | 483 | local function http_request(url, http) |
484 | -- @param filename string or nil: this function attempts to detect the | 484 | local proxy = cfg.proxy |
485 | -- resulting local filename of the remote file as the basename of the URL; | 485 | local url_arg, proxy_result |
486 | -- if that is not correct (due to a redirection, for example), the local | 486 | if proxy then |
487 | -- filename can be given explicitly as this second argument. | 487 | proxy_result = {} |
488 | -- @return boolean: true on success, false on failure. | 488 | url_arg = { url = url, proxy = proxy, sink = ltn12.sink.table(proxy_result) } |
489 | function download(url, filename) | 489 | else |
490 | assert(type(url) == "string") | 490 | url_arg = url |
491 | assert(type(filename) == "string" or not filename) | ||
492 | |||
493 | filename = dir.path(fs.current_dir(), filename or dir.base_name(url)) | ||
494 | |||
495 | local content, err | ||
496 | if util.starts_with(url, "http:") then | ||
497 | local proxy = cfg.proxy | ||
498 | local url_arg, proxy_result | ||
499 | if proxy then | ||
500 | proxy_result = {} | ||
501 | url_arg = { url = url, proxy = proxy, sink = ltn12.sink.table(proxy_result) } | ||
502 | else | ||
503 | url_arg = url | ||
504 | end | ||
505 | local res, status, headers, line = http.request(url_arg) | ||
506 | if not res then | ||
507 | err = status | ||
508 | elseif status ~= 200 then | ||
509 | err = line | ||
510 | else | ||
511 | if proxy_result then res = table.concat(proxy_result) end | ||
512 | content = res | ||
513 | end | ||
514 | elseif util.starts_with(url, "ftp:") then | ||
515 | content, err = ftp.get(url) | ||
516 | end | 491 | end |
517 | if not content then | 492 | local res, status, headers, line = http.request(url_arg) |
518 | return false, "Failed downloading: " .. err | 493 | if not res then |
494 | err = status | ||
495 | elseif status ~= 200 then | ||
496 | err = line | ||
497 | else | ||
498 | if proxy_result then res = table.concat(proxy_result) end | ||
499 | content = res | ||
519 | end | 500 | end |
520 | local file = io.open(filename, "wb") | 501 | return content, err |
521 | if not file then return false end | ||
522 | file:write(content) | ||
523 | file:close() | ||
524 | return true | ||
525 | end | 502 | end |
526 | 503 | ||
527 | --- Download a remote file. | 504 | --- Download a remote file. |
@@ -536,22 +513,23 @@ function download(url, filename) | |||
536 | assert(type(filename) == "string" or not filename) | 513 | assert(type(filename) == "string" or not filename) |
537 | 514 | ||
538 | filename = dir.path(fs.current_dir(), filename or dir.base_name(url)) | 515 | filename = dir.path(fs.current_dir(), filename or dir.base_name(url)) |
539 | 516 | ||
540 | local content, err | 517 | local content, err |
541 | if util.starts_with(url, "http:") then | 518 | if util.starts_with(url, "http:") then |
542 | local res, status, headers, line = http.request(url) | 519 | content, err = http_request(url, http) |
543 | if not res then | ||
544 | err = status | ||
545 | elseif status ~= 200 then | ||
546 | err = line | ||
547 | else | ||
548 | content = res | ||
549 | end | ||
550 | elseif util.starts_with(url, "ftp:") then | 520 | elseif util.starts_with(url, "ftp:") then |
551 | content, err = ftp.get(url) | 521 | content, err = ftp.get(url) |
522 | elseif util.starts_with(url, "https:") then | ||
523 | if luasec_ok then | ||
524 | content, err = http_request(url, https) | ||
525 | else | ||
526 | err = "Unsupported protocol - install luasec to get HTTPS support." | ||
527 | end | ||
528 | else | ||
529 | err = "Unsupported protocol" | ||
552 | end | 530 | end |
553 | if not content then | 531 | if not content then |
554 | return false, "Failed downloading: " .. err | 532 | return false, err |
555 | end | 533 | end |
556 | local file = io.open(filename, "wb") | 534 | local file = io.open(filename, "wb") |
557 | if not file then return false end | 535 | if not file then return false end |
@@ -560,7 +538,6 @@ function download(url, filename) | |||
560 | return true | 538 | return true |
561 | end | 539 | end |
562 | 540 | ||
563 | |||
564 | end | 541 | end |
565 | --------------------------------------------------------------------- | 542 | --------------------------------------------------------------------- |
566 | -- MD5 functions | 543 | -- MD5 functions |
diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua index c677a22c..a7211d70 100644 --- a/src/luarocks/manif.lua +++ b/src/luarocks/manif.lua | |||
@@ -304,9 +304,9 @@ local function find_providers(file, root) | |||
304 | assert(type(file) == "string") | 304 | assert(type(file) == "string") |
305 | root = root or cfg.root_dir | 305 | root = root or cfg.root_dir |
306 | 306 | ||
307 | local manifest = manif_core.load_local_manifest(path.rocks_dir(root)) | 307 | local manifest, err = manif_core.load_local_manifest(path.rocks_dir(root)) |
308 | if not manifest then | 308 | if not manifest then |
309 | return nil, "manifest file is missing. Corrupted local rocks tree?" | 309 | return nil, err .. " -- corrupted local rocks tree?" |
310 | end | 310 | end |
311 | local deploy_bin = path.deploy_bin_dir(root) | 311 | local deploy_bin = path.deploy_bin_dir(root) |
312 | local deploy_lua = path.deploy_lua_dir(root) | 312 | local deploy_lua = path.deploy_lua_dir(root) |
diff --git a/src/luarocks/manif_core.lua b/src/luarocks/manif_core.lua index d1eb4ebb..2e1a9518 100644 --- a/src/luarocks/manif_core.lua +++ b/src/luarocks/manif_core.lua | |||
@@ -16,9 +16,9 @@ manifest_cache = {} | |||
16 | -- @param file string: The local filename of the manifest file. | 16 | -- @param file string: The local filename of the manifest file. |
17 | -- @param repo_url string: The repository identifier. | 17 | -- @param repo_url string: The repository identifier. |
18 | function manifest_loader(file, repo_url, quick) | 18 | function manifest_loader(file, repo_url, quick) |
19 | local manifest = persist.load_into_table(file) | 19 | local manifest, err = persist.load_into_table(file) |
20 | if not manifest then | 20 | if not manifest then |
21 | return nil, "Failed loading manifest for "..repo_url | 21 | return nil, "Failed loading manifest for "..repo_url..": "..err |
22 | end | 22 | end |
23 | if not quick then | 23 | if not quick then |
24 | local ok, err = type_check.type_check_manifest(manifest) | 24 | local ok, err = type_check.type_check_manifest(manifest) |
diff --git a/src/luarocks/persist.lua b/src/luarocks/persist.lua index d74a805e..c809b51c 100644 --- a/src/luarocks/persist.lua +++ b/src/luarocks/persist.lua | |||
@@ -28,10 +28,6 @@ function load_into_table(filename, tbl) | |||
28 | return result | 28 | return result |
29 | end | 29 | end |
30 | 30 | ||
31 | local function string_sort(a,b) | ||
32 | return tostring(a) < tostring(b) | ||
33 | end | ||
34 | |||
35 | --- Write a table as Lua code representing a table to disk | 31 | --- Write a table as Lua code representing a table to disk |
36 | -- (that is, in curly brackets notation). | 32 | -- (that is, in curly brackets notation). |
37 | -- This function handles only numbers, strings and tables | 33 | -- This function handles only numbers, strings and tables |
@@ -43,7 +39,7 @@ local function write_table(out, tbl, level) | |||
43 | local sep = "\n" | 39 | local sep = "\n" |
44 | local indent = true | 40 | local indent = true |
45 | local i = 1 | 41 | local i = 1 |
46 | for k, v in util.sortedpairs(tbl, string_sort) do | 42 | for k, v in util.sortedpairs(tbl) do |
47 | out:write(sep) | 43 | out:write(sep) |
48 | if indent then | 44 | if indent then |
49 | for n = 1,level do out:write(" ") end | 45 | for n = 1,level do out:write(" ") end |
@@ -52,7 +48,7 @@ local function write_table(out, tbl, level) | |||
52 | indent = true | 48 | indent = true |
53 | if type(k) == "number" then | 49 | if type(k) == "number" then |
54 | if k ~= i then | 50 | if k ~= i then |
55 | out:write(tostring(k).."=") | 51 | out:write('['..tostring(k).."]=") |
56 | else | 52 | else |
57 | i = i + 1 | 53 | i = i + 1 |
58 | end | 54 | end |
@@ -95,7 +91,7 @@ function save_from_table(filename, tbl) | |||
95 | if not out then | 91 | if not out then |
96 | return nil, "Cannot create file at "..filename | 92 | return nil, "Cannot create file at "..filename |
97 | end | 93 | end |
98 | for k, v in util.sortedpairs(tbl, string_sort) do | 94 | for k, v in util.sortedpairs(tbl) do |
99 | out:write(k.." = ") | 95 | out:write(k.." = ") |
100 | write_table(out, v, 1) | 96 | write_table(out, v, 1) |
101 | out:write("\n") | 97 | out:write("\n") |
diff --git a/src/luarocks/tools/zip.lua b/src/luarocks/tools/zip.lua index 18ad967e..caeb4ac9 100644 --- a/src/luarocks/tools/zip.lua +++ b/src/luarocks/tools/zip.lua | |||
@@ -1,7 +1,11 @@ | |||
1 | 1 | ||
2 | module("luarocks.tools.zip", package.seeall) | 2 | module("luarocks.tools.zip", package.seeall) |
3 | 3 | ||
4 | local zlib = require "zlib" | 4 | local zlib = require("zlib") |
5 | local fs = require("luarocks.fs") | ||
6 | local dir = require("luarocks.dir") | ||
7 | |||
8 | local size_buf = 65535 | ||
5 | 9 | ||
6 | local function number_to_bytestring(number, nbytes) | 10 | local function number_to_bytestring(number, nbytes) |
7 | local out = {} | 11 | local out = {} |
@@ -13,34 +17,17 @@ local function number_to_bytestring(number, nbytes) | |||
13 | return table.concat(out) | 17 | return table.concat(out) |
14 | end | 18 | end |
15 | 19 | ||
16 | --- Return a zip handle open for writing. | ||
17 | -- @param name filename of the zipfile to be created. | ||
18 | -- @return a zip handle, or nil in case of error. | ||
19 | function write_open(name) | ||
20 | |||
21 | local zf = {} | ||
22 | |||
23 | zf.ziphandle = io.open(name, "w") | ||
24 | if not zf.ziphandle then | ||
25 | return nil | ||
26 | end | ||
27 | zf.files = {} | ||
28 | zf.in_open_file = false | ||
29 | |||
30 | return zf | ||
31 | end | ||
32 | |||
33 | --- Begin a new file to be stored inside the zipfile. | 20 | --- Begin a new file to be stored inside the zipfile. |
34 | -- @param zf handle of the zipfile being written. | 21 | -- @param self handle of the zipfile being written. |
35 | -- @param filename filenome of the file to be added to the zipfile. | 22 | -- @param filename filenome of the file to be added to the zipfile. |
36 | -- @return true if succeeded, nil in case of failure. | 23 | -- @return true if succeeded, nil in case of failure. |
37 | function write_open_new_file_in_zip(zf, filename) | 24 | local function zipwriter_open_new_file_in_zip(self, filename) |
38 | if zf.in_open_file then | 25 | if self.in_open_file then |
39 | close_file_in_zip(zf) | 26 | self:close_file_in_zip() |
40 | return nil | 27 | return nil |
41 | end | 28 | end |
42 | local lfh = {} | 29 | local lfh = {} |
43 | zf.local_file_header = lfh | 30 | self.local_file_header = lfh |
44 | lfh.last_mod_file_time = 0 -- TODO | 31 | lfh.last_mod_file_time = 0 -- TODO |
45 | lfh.last_mod_file_date = 0 -- TODO | 32 | lfh.last_mod_file_date = 0 -- TODO |
46 | lfh.crc32 = 0 -- initial value | 33 | lfh.crc32 = 0 -- initial value |
@@ -49,40 +36,41 @@ function write_open_new_file_in_zip(zf, filename) | |||
49 | lfh.file_name_length = #filename | 36 | lfh.file_name_length = #filename |
50 | lfh.extra_field_length = 0 | 37 | lfh.extra_field_length = 0 |
51 | lfh.file_name = filename:gsub("\\", "/") | 38 | lfh.file_name = filename:gsub("\\", "/") |
52 | zf.in_open_file = true | 39 | lfh.external_attr = 0 -- TODO properly store permissions |
53 | zf.data = {} | 40 | self.in_open_file = true |
41 | self.data = {} | ||
54 | return true | 42 | return true |
55 | end | 43 | end |
56 | 44 | ||
57 | --- Write data to the file currently being stored in the zipfile. | 45 | --- Write data to the file currently being stored in the zipfile. |
58 | -- @param zf handle of the zipfile being written. | 46 | -- @param self handle of the zipfile being written. |
59 | -- @param buf string containing data to be written. | 47 | -- @param buf string containing data to be written. |
60 | -- @return true if succeeded, nil in case of failure. | 48 | -- @return true if succeeded, nil in case of failure. |
61 | function write_in_file_in_zip(zf, buf) | 49 | local function zipwriter_write_file_in_zip(self, buf) |
62 | if not zf.in_open_file then | 50 | if not self.in_open_file then |
63 | return nil | 51 | return nil |
64 | end | 52 | end |
65 | local lfh = zf.local_file_header | 53 | local lfh = self.local_file_header |
66 | local cbuf = zlib.compress(buf):sub(3, -5) | 54 | local cbuf = zlib.compress(buf):sub(3, -5) |
67 | lfh.crc32 = zlib.crc32(lfh.crc32, buf) | 55 | lfh.crc32 = zlib.crc32(lfh.crc32, buf) |
68 | lfh.compressed_size = lfh.compressed_size + #cbuf | 56 | lfh.compressed_size = lfh.compressed_size + #cbuf |
69 | lfh.uncompressed_size = lfh.uncompressed_size + #buf | 57 | lfh.uncompressed_size = lfh.uncompressed_size + #buf |
70 | table.insert(zf.data, cbuf) | 58 | table.insert(self.data, cbuf) |
71 | return true | 59 | return true |
72 | end | 60 | end |
73 | 61 | ||
74 | --- Complete the writing of a file stored in the zipfile. | 62 | --- Complete the writing of a file stored in the zipfile. |
75 | -- @param zf handle of the zipfile being written. | 63 | -- @param self handle of the zipfile being written. |
76 | -- @return true if succeeded, nil in case of failure. | 64 | -- @return true if succeeded, nil in case of failure. |
77 | function write_close_file_in_zip(zf) | 65 | local function zipwriter_close_file_in_zip(self) |
78 | local zh = zf.ziphandle | 66 | local zh = self.ziphandle |
79 | 67 | ||
80 | if not zf.in_open_file then | 68 | if not self.in_open_file then |
81 | return nil | 69 | return nil |
82 | end | 70 | end |
83 | 71 | ||
84 | -- Local file header | 72 | -- Local file header |
85 | local lfh = zf.local_file_header | 73 | local lfh = self.local_file_header |
86 | lfh.offset = zh:seek() | 74 | lfh.offset = zh:seek() |
87 | zh:write(number_to_bytestring(0x04034b50, 4)) -- signature | 75 | zh:write(number_to_bytestring(0x04034b50, 4)) -- signature |
88 | zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0 | 76 | zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0 |
@@ -98,7 +86,7 @@ function write_close_file_in_zip(zf) | |||
98 | zh:write(lfh.file_name) | 86 | zh:write(lfh.file_name) |
99 | 87 | ||
100 | -- File data | 88 | -- File data |
101 | for _, cbuf in ipairs(zf.data) do | 89 | for _, cbuf in ipairs(self.data) do |
102 | zh:write(cbuf) | 90 | zh:write(cbuf) |
103 | end | 91 | end |
104 | 92 | ||
@@ -107,23 +95,59 @@ function write_close_file_in_zip(zf) | |||
107 | zh:write(number_to_bytestring(lfh.compressed_size, 4)) | 95 | zh:write(number_to_bytestring(lfh.compressed_size, 4)) |
108 | zh:write(number_to_bytestring(lfh.uncompressed_size, 4)) | 96 | zh:write(number_to_bytestring(lfh.uncompressed_size, 4)) |
109 | 97 | ||
110 | table.insert(zf.files, lfh) | 98 | table.insert(self.files, lfh) |
111 | zf.in_open_file = false | 99 | self.in_open_file = false |
112 | 100 | ||
113 | return true | 101 | return true |
114 | end | 102 | end |
115 | 103 | ||
104 | -- @return boolean or (boolean, string): true on success, | ||
105 | -- false and an error message on failure. | ||
106 | local function zipwriter_add(self, file) | ||
107 | local fin | ||
108 | local ok, err = self:open_new_file_in_zip(file) | ||
109 | if not ok then | ||
110 | err = "error in opening "..file.." in zipfile" | ||
111 | else | ||
112 | fin = io.open(file, "rb") | ||
113 | if not fin then | ||
114 | ok = false | ||
115 | err = "error opening "..file.." for reading" | ||
116 | end | ||
117 | end | ||
118 | while ok do | ||
119 | local buf = fin:read(size_buf) | ||
120 | if not buf then | ||
121 | break | ||
122 | end | ||
123 | ok = self:write_file_in_zip(buf) | ||
124 | if not ok then | ||
125 | err = "error in writing "..file.." in the zipfile" | ||
126 | end | ||
127 | end | ||
128 | if fin then | ||
129 | fin:close() | ||
130 | end | ||
131 | if ok then | ||
132 | ok = self:close_file_in_zip() | ||
133 | if not ok then | ||
134 | err = "error in writing "..file.." in the zipfile" | ||
135 | end | ||
136 | end | ||
137 | return ok == true, err | ||
138 | end | ||
139 | |||
116 | --- Complete the writing of the zipfile. | 140 | --- Complete the writing of the zipfile. |
117 | -- @param zf handle of the zipfile being written. | 141 | -- @param self handle of the zipfile being written. |
118 | -- @return true if succeeded, nil in case of failure. | 142 | -- @return true if succeeded, nil in case of failure. |
119 | function write_close(zf) | 143 | local function zipwriter_close(self) |
120 | local zh = zf.ziphandle | 144 | local zh = self.ziphandle |
121 | 145 | ||
122 | local central_directory_offset = zh:seek() | 146 | local central_directory_offset = zh:seek() |
123 | 147 | ||
124 | local size_of_central_directory = 0 | 148 | local size_of_central_directory = 0 |
125 | -- Central directory structure | 149 | -- Central directory structure |
126 | for _, lfh in ipairs(zf.files) do | 150 | for _, lfh in ipairs(self.files) do |
127 | zh:write(number_to_bytestring(0x02014b50, 4)) -- signature | 151 | zh:write(number_to_bytestring(0x02014b50, 4)) -- signature |
128 | zh:write(number_to_bytestring(3, 2)) -- version made by: UNIX | 152 | zh:write(number_to_bytestring(3, 2)) -- version made by: UNIX |
129 | zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0 | 153 | zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0 |
@@ -139,7 +163,7 @@ function write_close(zf) | |||
139 | zh:write(number_to_bytestring(0, 2)) -- file comment length | 163 | zh:write(number_to_bytestring(0, 2)) -- file comment length |
140 | zh:write(number_to_bytestring(0, 2)) -- disk number start | 164 | zh:write(number_to_bytestring(0, 2)) -- disk number start |
141 | zh:write(number_to_bytestring(0, 2)) -- internal file attributes | 165 | zh:write(number_to_bytestring(0, 2)) -- internal file attributes |
142 | zh:write(number_to_bytestring(0, 4)) -- external file attributes | 166 | zh:write(number_to_bytestring(lfh.external_attr, 4)) -- external file attributes |
143 | zh:write(number_to_bytestring(lfh.offset, 4)) -- relative offset of local header | 167 | zh:write(number_to_bytestring(lfh.offset, 4)) -- relative offset of local header |
144 | zh:write(lfh.file_name) | 168 | zh:write(lfh.file_name) |
145 | size_of_central_directory = size_of_central_directory + 46 + lfh.file_name_length | 169 | size_of_central_directory = size_of_central_directory + 46 + lfh.file_name_length |
@@ -149,8 +173,8 @@ function write_close(zf) | |||
149 | zh:write(number_to_bytestring(0x06054b50, 4)) -- signature | 173 | zh:write(number_to_bytestring(0x06054b50, 4)) -- signature |
150 | zh:write(number_to_bytestring(0, 2)) -- number of this disk | 174 | zh:write(number_to_bytestring(0, 2)) -- number of this disk |
151 | zh:write(number_to_bytestring(0, 2)) -- number of disk with start of central directory | 175 | zh:write(number_to_bytestring(0, 2)) -- number of disk with start of central directory |
152 | zh:write(number_to_bytestring(#zf.files, 2)) -- total number of entries in the central dir on this disk | 176 | zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir on this disk |
153 | zh:write(number_to_bytestring(#zf.files, 2)) -- total number of entries in the central dir | 177 | zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir |
154 | zh:write(number_to_bytestring(size_of_central_directory, 4)) | 178 | zh:write(number_to_bytestring(size_of_central_directory, 4)) |
155 | zh:write(number_to_bytestring(central_directory_offset, 4)) | 179 | zh:write(number_to_bytestring(central_directory_offset, 4)) |
156 | zh:write(number_to_bytestring(0, 2)) -- zip file comment length | 180 | zh:write(number_to_bytestring(0, 2)) -- zip file comment length |
@@ -159,40 +183,27 @@ function write_close(zf) | |||
159 | return true | 183 | return true |
160 | end | 184 | end |
161 | 185 | ||
162 | -- @return boolean or (boolean, string): true on success, | 186 | --- Return a zip handle open for writing. |
163 | -- false and an error message on failure. | 187 | -- @param name filename of the zipfile to be created. |
164 | local function add_to_zip(zf, file) | 188 | -- @return a zip handle, or nil in case of error. |
165 | local fin | 189 | function new_zipwriter(name) |
166 | local ok, err = write_open_new_file_in_zip(zf, file) | 190 | |
167 | if not ok then | 191 | local zw = {} |
168 | err = "error in opening "..file.." in zipfile" | 192 | |
169 | else | 193 | zw.ziphandle = io.open(name, "w") |
170 | fin = io.open(file, "rb") | 194 | if not zw.ziphandle then |
171 | if not fin then | 195 | return nil |
172 | ok = false | ||
173 | err = "error opening "..file.." for reading" | ||
174 | end | ||
175 | end | ||
176 | while ok do | ||
177 | local buf = fin:read(size_buf) | ||
178 | if not buf then | ||
179 | break | ||
180 | end | ||
181 | ok = write_in_file_in_zip(zf, buf) | ||
182 | if not ok then | ||
183 | err = "error in writing "..file.." in the zipfile" | ||
184 | end | ||
185 | end | ||
186 | if fin then | ||
187 | fin:close() | ||
188 | end | ||
189 | if ok then | ||
190 | ok = write_close_file_in_zip(zf) | ||
191 | if not ok then | ||
192 | err = "error in writing "..file.." in the zipfile" | ||
193 | end | ||
194 | end | 196 | end |
195 | return ok == true, err | 197 | zw.files = {} |
198 | zw.in_open_file = false | ||
199 | |||
200 | zw.add = zipwriter_add | ||
201 | zw.close = zipwriter_close | ||
202 | zw.open_new_file_in_zip = zipwriter_open_new_file_in_zip | ||
203 | zw.write_file_in_zip = zipwriter_write_file_in_zip | ||
204 | zw.close_file_in_zip = zipwriter_close_file_in_zip | ||
205 | |||
206 | return zw | ||
196 | end | 207 | end |
197 | 208 | ||
198 | --- Compress files in a .zip archive. | 209 | --- Compress files in a .zip archive. |
@@ -202,29 +213,31 @@ end | |||
202 | -- @return boolean or (boolean, string): true on success, | 213 | -- @return boolean or (boolean, string): true on success, |
203 | -- false and an error message on failure. | 214 | -- false and an error message on failure. |
204 | function zip(zipfile, ...) | 215 | function zip(zipfile, ...) |
205 | local zf = write_open(filename) | 216 | local zw = new_zipwriter(zipfile) |
206 | if not zf then | 217 | if not zw then |
207 | return nil, "error opening "..filename | 218 | return nil, "error opening "..zipfile |
208 | end | 219 | end |
209 | 220 | ||
210 | local ok, err | 221 | local ok, err |
211 | for _, file in pairs({...}) do | 222 | for _, file in pairs({...}) do |
212 | if fs.is_dir(file) then | 223 | if fs.is_dir(file) then |
213 | for _, file in pairs(fs.find(file)) do | 224 | for _, entry in pairs(fs.find(file)) do |
214 | if fs.is_file(file) then | 225 | local fullname = dir.path(file, entry) |
215 | ok, err = add_to_zip(file) | 226 | if fs.is_file(fullname) then |
227 | ok, err = zw:add(fullname) | ||
216 | if not ok then break end | 228 | if not ok then break end |
217 | end | 229 | end |
218 | end | 230 | end |
219 | else | 231 | else |
220 | ok, err = add_to_zip(file) | 232 | ok, err = zw:add(file) |
221 | if not ok then break end | 233 | if not ok then break end |
222 | end | 234 | end |
223 | end | 235 | end |
224 | 236 | ||
225 | local ok = write_close(zf) | 237 | local ok = zw:close() |
226 | if not ok then | 238 | if not ok then |
227 | return false, "error closing "..filename | 239 | return false, "error closing "..zipfile |
228 | end | 240 | end |
229 | return ok, err | 241 | return ok, err |
230 | end | 242 | end |
243 | |||
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua index 10fc1e36..e0c01421 100644 --- a/src/luarocks/util.lua +++ b/src/luarocks/util.lua | |||
@@ -216,6 +216,20 @@ function keys(tbl) | |||
216 | return ks | 216 | return ks |
217 | end | 217 | end |
218 | 218 | ||
219 | local function default_sort(a, b) | ||
220 | local ta = type(a) | ||
221 | local tb = type(b) | ||
222 | if ta == "number" and tb == "number" then | ||
223 | return a < b | ||
224 | elseif ta == "number" then | ||
225 | return true | ||
226 | elseif tb == "number" then | ||
227 | return false | ||
228 | else | ||
229 | return tostring(a) < tostring(b) | ||
230 | end | ||
231 | end | ||
232 | |||
219 | -- The iterator function used internally by util.sortedpairs. | 233 | -- The iterator function used internally by util.sortedpairs. |
220 | -- @param tbl table: The table to be iterated. | 234 | -- @param tbl table: The table to be iterated. |
221 | -- @param sort_function function or nil: An optional comparison function | 235 | -- @param sort_function function or nil: An optional comparison function |
@@ -223,7 +237,7 @@ end | |||
223 | -- @see sortedpairs | 237 | -- @see sortedpairs |
224 | local function sortedpairs_iterator(tbl, sort_function) | 238 | local function sortedpairs_iterator(tbl, sort_function) |
225 | local ks = keys(tbl) | 239 | local ks = keys(tbl) |
226 | table.sort(ks, sort_function) | 240 | table.sort(ks, sort_function or default_sort) |
227 | for _, k in ipairs(ks) do | 241 | for _, k in ipairs(ks) do |
228 | coroutine.yield(k, tbl[k]) | 242 | coroutine.yield(k, tbl[k]) |
229 | end | 243 | end |