diff options
Diffstat (limited to 'src')
| -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 |
