aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorV1K1NGbg <victor@ilchev.com>2024-08-22 17:48:59 -0300
committerHisham Muhammad <hisham@gobolinux.org>2024-10-21 13:30:51 -0300
commit521febd470596142f922ed5f803bac4516ce7dae (patch)
tree0b1358aed123fe34a54c27ebefdb9b5dbde573a1 /src
parent8f656b5a26c6c5352589e8ed294a8c27871b65a7 (diff)
downloadluarocks-521febd470596142f922ed5f803bac4516ce7dae.tar.gz
luarocks-521febd470596142f922ed5f803bac4516ce7dae.tar.bz2
luarocks-521febd470596142f922ed5f803bac4516ce7dae.zip
Teal: convert luarocks.tools.zip
Diffstat (limited to 'src')
-rw-r--r--src/luarocks/tools/zip.tl (renamed from src/luarocks/tools/zip.lua)198
1 files changed, 121 insertions, 77 deletions
diff --git a/src/luarocks/tools/zip.lua b/src/luarocks/tools/zip.tl
index 82d582fa..82a19011 100644
--- a/src/luarocks/tools/zip.lua
+++ b/src/luarocks/tools/zip.tl
@@ -1,27 +1,73 @@
1 1
2--- A Lua implementation of .zip and .gz file compression and decompression, 2--- A Lua implementation of .zip and .gz file compression and decompression,
3-- using only lzlib or lua-lzib. 3-- using only lzlib or lua-lzib.
4local zip = {} 4local record zip
5 record ZipHandle
6 read: function(ZipHandle, ...: number | string): string...
7 seek: function(ZipHandle, ? string, ? integer): integer, string
8 write: function(ZipHandle, ...: string | number): ZipHandle, string
9 close: function(ZipHandle): boolean, string, number
10 end
11
12 record LocalFileHeader
13 last_mod_file_time: integer
14 last_mod_file_date: integer
15 file_name_length: integer
16 extra_field_length: integer
17 file_name: string
18 external_attr: integer
19 crc32: integer
20 compressed_size: integer
21 compression_method: integer
22 uncompressed_size: integer
23 offset: integer
24 version_made_by: integer
25 version_needed: integer
26 bitflag: integer
27 last_mod_luatime: os.DateTable
28 file_comment_length: integer
29 disk_number_start: integer
30 internal_attr: integer
31 extra_field: string
32 file_comment: string
33 end
34
35 record Zip
36 in_open_file: boolean
37 add: function(Zip, string): boolean, string
38 close: function(Zip): boolean
39 close_file_in_zip: function(Zip): boolean
40 open_new_file_in_zip: function(Zip, string): boolean
41 write_file_in_zip: function(Zip, string): boolean
42 local_file_header: LocalFileHeader
43 data: string
44 ZipHandle: ZipHandle
45 files: {LocalFileHeader}
46 end
47end
5 48
6local zlib = require("zlib") 49local zlib = require("zlib")
7local fs = require("luarocks.fs") 50local fs = require("luarocks.fs")
8local fun = require("luarocks.fun") 51local fun = require("luarocks.fun")
9local dir = require("luarocks.dir") 52local dir = require("luarocks.dir")
10 53
11local pack = table.pack or function(...) return { n = select("#", ...), ... } end 54local type Zip = zip.Zip
55local type LocalFileHeader = zip.LocalFileHeader
56local type ZipHandle = zip.ZipHandle
12 57
13local function shr(n, m) 58local function shr(n: integer, m: integer): integer
14 return math.floor(n / 2^m) 59 return math.floor(n / 2^m)
15end 60end
16 61
17local function shl(n, m) 62local function shl(n: integer, m: integer): integer
18 return n * 2^m 63 return (n * 2^m) as integer
19end 64end
20local function lowbits(n, m) 65
21 return n % 2^m 66local function lowbits(n: integer, m: integer): integer
67 return (n % 2^m) as integer
22end 68end
23 69
24local function mode_to_windowbits(mode) 70local function mode_to_windowbits(mode: string): integer
25 if mode == "gzip" then 71 if mode == "gzip" then
26 return 31 72 return 31
27 elseif mode == "zlib" then 73 elseif mode == "zlib" then
@@ -33,47 +79,49 @@ end
33 79
34-- zlib module can be provided by both lzlib and lua-lzib packages. 80-- zlib module can be provided by both lzlib and lua-lzib packages.
35-- Create a compatibility layer. 81-- Create a compatibility layer.
36local zlib_compress, zlib_uncompress, zlib_crc32 82local zlib_compress: function(string, string): string
83local zlib_uncompress: function(string, string): string
84local zlib_crc32: function(string): integer
37if zlib._VERSION:match "^lua%-zlib" then 85if zlib._VERSION:match "^lua%-zlib" then
38 function zlib_compress(data, mode) 86 function zlib_compress(data: string, mode: string): string
39 return (zlib.deflate(6, mode_to_windowbits(mode))(data, "finish")) 87 return (zlib.deflate(6, mode_to_windowbits(mode))(data, "finish"))
40 end 88 end
41 89
42 function zlib_uncompress(data, mode) 90 function zlib_uncompress(data: string, mode: string): string
43 return (zlib.inflate(mode_to_windowbits(mode))(data)) 91 return (zlib.inflate(mode_to_windowbits(mode))(data))
44 end 92 end
45 93
46 function zlib_crc32(data) 94 function zlib_crc32(data: string): integer
47 return zlib.crc32()(data) 95 return zlib.crc32()(data)
48 end 96 end
49elseif zlib._VERSION:match "^lzlib" then 97elseif zlib._VERSION:match "^lzlib" then
50 function zlib_compress(data, mode) 98 function zlib_compress(data: string, mode: string): string
51 return zlib.compress(data, -1, nil, mode_to_windowbits(mode)) 99 return zlib.compress(data, -1, nil, mode_to_windowbits(mode))
52 end 100 end
53 101
54 function zlib_uncompress(data, mode) 102 function zlib_uncompress(data: string, mode: string): string
55 return zlib.decompress(data, mode_to_windowbits(mode)) 103 return zlib.decompress(data, mode_to_windowbits(mode))
56 end 104 end
57 105
58 function zlib_crc32(data) 106 function zlib_crc32(data: string): integer
59 return zlib.crc32(zlib.crc32(), data) 107 return zlib.crc32(zlib.crc32(), data)
60 end 108 end
61else 109else
62 error("unknown zlib library", 0) 110 error("unknown zlib library", 0)
63end 111end
64 112
65local function number_to_lestring(number, nbytes) 113local function number_to_lestring(number: number, nbytes: number): string
66 local out = {} 114 local out = {}
67 for _ = 1, nbytes do 115 for _ = 1, nbytes do
68 local byte = number % 256 116 local byte: integer = number as integer % 256 --! cast I don't like
69 table.insert(out, string.char(byte)) 117 table.insert(out, string.char(byte))
70 number = (number - byte) / 256 118 number = (number - byte) / 256
71 end 119 end
72 return table.concat(out) 120 return table.concat(out)
73end 121end
74 122
75local function lestring_to_number(str) 123local function lestring_to_number(str: string): integer
76 local n = 0 124 local n: number = 0
77 local bytes = { string.byte(str, 1, #str) } 125 local bytes = { string.byte(str, 1, #str) }
78 for b = 1, #str do 126 for b = 1, #str do
79 n = n + shl(bytes[b], (b-1)*8) 127 n = n + shl(bytes[b], (b-1)*8)
@@ -88,14 +136,14 @@ local END_OF_CENTRAL_DIR_SIGNATURE = number_to_lestring(0x06054b50, 4)
88 136
89--- Begin a new file to be stored inside the zipfile. 137--- Begin a new file to be stored inside the zipfile.
90-- @param self handle of the zipfile being written. 138-- @param self handle of the zipfile being written.
91-- @param filename filenome of the file to be added to the zipfile. 139-- @param filename filename of the file to be added to the zipfile.
92-- @return true if succeeded, nil in case of failure. 140-- @return true if succeeded, nil in case of failure.
93local function zipwriter_open_new_file_in_zip(self, filename) 141local function zipwriter_open_new_file_in_zip(self: Zip, filename: string): boolean
94 if self.in_open_file then 142 if self.in_open_file then
95 self:close_file_in_zip() 143 self:close_file_in_zip()
96 return nil 144 return nil
97 end 145 end
98 local lfh = {} 146 local lfh: LocalFileHeader = {}
99 self.local_file_header = lfh 147 self.local_file_header = lfh
100 lfh.last_mod_file_time = 0 -- TODO 148 lfh.last_mod_file_time = 0 -- TODO
101 lfh.last_mod_file_date = 0 -- TODO 149 lfh.last_mod_file_date = 0 -- TODO
@@ -111,7 +159,7 @@ end
111-- @param self handle of the zipfile being written. 159-- @param self handle of the zipfile being written.
112-- @param data string containing full contents of the file. 160-- @param data string containing full contents of the file.
113-- @return true if succeeded, nil in case of failure. 161-- @return true if succeeded, nil in case of failure.
114local function zipwriter_write_file_in_zip(self, data) 162local function zipwriter_write_file_in_zip(self: Zip, data: string): boolean
115 if not self.in_open_file then 163 if not self.in_open_file then
116 return nil 164 return nil
117 end 165 end
@@ -127,8 +175,8 @@ end
127--- Complete the writing of a file stored in the zipfile. 175--- Complete the writing of a file stored in the zipfile.
128-- @param self handle of the zipfile being written. 176-- @param self handle of the zipfile being written.
129-- @return true if succeeded, nil in case of failure. 177-- @return true if succeeded, nil in case of failure.
130local function zipwriter_close_file_in_zip(self) 178local function zipwriter_close_file_in_zip(self: Zip): boolean
131 local zh = self.ziphandle 179 local zh = self.ZipHandle
132 180
133 if not self.in_open_file then 181 if not self.in_open_file then
134 return nil 182 return nil
@@ -167,9 +215,9 @@ end
167 215
168-- @return boolean or (boolean, string): true on success, 216-- @return boolean or (boolean, string): true on success,
169-- false and an error message on failure. 217-- false and an error message on failure.
170local function zipwriter_add(self, file) 218local function zipwriter_add(self: Zip, file: string): boolean, string
171 local fin 219 local fin: FILE
172 local ok, err = self:open_new_file_in_zip(file) 220 local ok, err: boolean, string = self:open_new_file_in_zip(file)
173 if not ok then 221 if not ok then
174 err = "error in opening "..file.." in zipfile" 222 err = "error in opening "..file.." in zipfile"
175 else 223 else
@@ -206,8 +254,8 @@ end
206--- Complete the writing of the zipfile. 254--- Complete the writing of the zipfile.
207-- @param self handle of the zipfile being written. 255-- @param self handle of the zipfile being written.
208-- @return true if succeeded, nil in case of failure. 256-- @return true if succeeded, nil in case of failure.
209local function zipwriter_close(self) 257local function zipwriter_close(self: Zip): boolean
210 local zh = self.ziphandle 258 local zh = self.ZipHandle
211 259
212 local central_directory_offset = zh:seek() 260 local central_directory_offset = zh:seek()
213 261
@@ -252,12 +300,12 @@ end
252--- Return a zip handle open for writing. 300--- Return a zip handle open for writing.
253-- @param name filename of the zipfile to be created. 301-- @param name filename of the zipfile to be created.
254-- @return a zip handle, or nil in case of error. 302-- @return a zip handle, or nil in case of error.
255function zip.new_zipwriter(name) 303function zip.new_zipwriter(name: string): Zip
256 304
257 local zw = {} 305 local zw: Zip = {}
258 306
259 zw.ziphandle = io.open(fs.absolute_name(name), "wb") 307 zw.ZipHandle = io.open(fs.absolute_name(name), "wb") as ZipHandle
260 if not zw.ziphandle then 308 if not zw.ZipHandle then
261 return nil 309 return nil
262 end 310 end
263 zw.files = {} 311 zw.files = {}
@@ -278,18 +326,18 @@ end
278-- additional arguments. 326-- additional arguments.
279-- @return boolean or (boolean, string): true on success, 327-- @return boolean or (boolean, string): true on success,
280-- false and an error message on failure. 328-- false and an error message on failure.
281function zip.zip(zipfile, ...) 329function zip.zip(zipfile: string, ...: string): boolean, string
282 local zw = zip.new_zipwriter(zipfile) 330 local zw = zip.new_zipwriter(zipfile)
283 if not zw then 331 if not zw then
284 return nil, "error opening "..zipfile 332 return nil, "error opening "..zipfile
285 end 333 end
286 334
287 local args = pack(...) 335 local args = table.pack(...)
288 local ok, err 336 local ok, err: boolean, string
289 for i=1, args.n do 337 for i=1, args.n do
290 local file = args[i] 338 local file = args[i]
291 if fs.is_dir(file) then 339 if fs.is_dir(file) then
292 for _, entry in pairs(fs.find(file)) do 340 for _, entry in ipairs(fs.find(file)) do
293 local fullname = dir.path(file, entry) 341 local fullname = dir.path(file, entry)
294 if fs.is_file(fullname) then 342 if fs.is_file(fullname) then
295 ok, err = zw:add(fullname) 343 ok, err = zw:add(fullname)
@@ -307,8 +355,8 @@ function zip.zip(zipfile, ...)
307end 355end
308 356
309 357
310local function ziptime_to_luatime(ztime, zdate) 358local function ziptime_to_luatime(ztime: integer, zdate: integer): os.DateTable
311 local date = { 359 local date: os.DateTable = {
312 year = shr(zdate, 9) + 1980, 360 year = shr(zdate, 9) + 1980,
313 month = shr(lowbits(zdate, 9), 5), 361 month = shr(lowbits(zdate, 9), 5),
314 day = lowbits(zdate, 5), 362 day = lowbits(zdate, 5),
@@ -323,7 +371,7 @@ local function ziptime_to_luatime(ztime, zdate)
323 return date 371 return date
324end 372end
325 373
326local function read_file_in_zip(zh, cdr) 374local function read_file_in_zip(zh: FILE, cdr: LocalFileHeader): string, string
327 local sig = zh:read(4) 375 local sig = zh:read(4)
328 if sig ~= LOCAL_FILE_HEADER_SIGNATURE then 376 if sig ~= LOCAL_FILE_HEADER_SIGNATURE then
329 return nil, "failed reading Local File Header signature" 377 return nil, "failed reading Local File Header signature"
@@ -339,7 +387,7 @@ local function read_file_in_zip(zh, cdr)
339 387
340 local data = zh:read(cdr.compressed_size) 388 local data = zh:read(cdr.compressed_size)
341 389
342 local uncompressed 390 local uncompressed: string
343 if cdr.compression_method == 8 then 391 if cdr.compression_method == 8 then
344 uncompressed = zlib_uncompress(data, "raw") 392 uncompressed = zlib_uncompress(data, "raw")
345 elseif cdr.compression_method == 0 then 393 elseif cdr.compression_method == 0 then
@@ -358,10 +406,10 @@ local function read_file_in_zip(zh, cdr)
358 return uncompressed 406 return uncompressed
359end 407end
360 408
361local function process_end_of_central_dir(zh) 409local function process_end_of_central_dir(zh: ZipHandle): number, integer | string
362 local at, err = zh:seek("end", -22) 410 local at, errend = zh:seek("end", -22)
363 if not at then 411 if not at then
364 return nil, err 412 return nil, errend
365 end 413 end
366 414
367 while true do 415 while true do
@@ -370,7 +418,7 @@ local function process_end_of_central_dir(zh)
370 break 418 break
371 end 419 end
372 at = at - 1 420 at = at - 1
373 local at1, err = zh:seek("set", at) 421 local at1 = zh:seek("set", at)
374 if at1 ~= at then 422 if at1 ~= at then
375 return nil, "Could not find End of Central Directory signature" 423 return nil, "Could not find End of Central Directory signature"
376 end 424 end
@@ -392,9 +440,9 @@ local function process_end_of_central_dir(zh)
392 return central_directory_entries, central_directory_offset 440 return central_directory_entries, central_directory_offset
393end 441end
394 442
395local function process_central_dir(zh, cd_entries) 443local function process_central_dir(zh: ZipHandle, cd_entries: number): {LocalFileHeader}, string
396 444
397 local files = {} 445 local files: {LocalFileHeader} = {}
398 446
399 for i = 1, cd_entries do 447 for i = 1, cd_entries do
400 local sig = zh:read(4) 448 local sig = zh:read(4)
@@ -402,8 +450,8 @@ local function process_central_dir(zh, cd_entries)
402 return nil, "failed reading Central Directory signature" 450 return nil, "failed reading Central Directory signature"
403 end 451 end
404 452
405 local cdr = {} 453 local cdr: LocalFileHeader = {}
406 files[i] = cdr 454 files[i as integer] = cdr
407 455
408 cdr.version_made_by = lestring_to_number(zh:read(2)) 456 cdr.version_made_by = lestring_to_number(zh:read(2))
409 cdr.version_needed = lestring_to_number(zh:read(2)) 457 cdr.version_needed = lestring_to_number(zh:read(2))
@@ -433,50 +481,50 @@ end
433-- @param zipfile string: pathname of .zip archive to be created. 481-- @param zipfile string: pathname of .zip archive to be created.
434-- @return boolean or (boolean, string): true on success, 482-- @return boolean or (boolean, string): true on success,
435-- false and an error message on failure. 483-- false and an error message on failure.
436function zip.unzip(zipfile) 484function zip.unzip(zipfile: string): boolean, string
437 zipfile = fs.absolute_name(zipfile) 485 zipfile = fs.absolute_name(zipfile)
438 local zh, err = io.open(zipfile, "rb") 486 local zh, erropen = io.open(zipfile, "rb")
439 if not zh then 487 if not zh then
440 return nil, err 488 return nil, erropen
441 end 489 end
442 490
443 local cd_entries, cd_offset = process_end_of_central_dir(zh) 491 local cd_entries, cd_offset = process_end_of_central_dir(zh as ZipHandle)
444 if not cd_entries then 492 if cd_offset is string then
445 return nil, cd_offset 493 return nil, cd_offset
446 end 494 end
447 495
448 local ok, err = zh:seek("set", cd_offset) 496 local okseek, errseek = zh:seek("set", cd_offset)
449 if not ok then 497 if not okseek then
450 return nil, err 498 return nil, errseek
451 end 499 end
452 500
453 local files, err = process_central_dir(zh, cd_entries) 501 local files, errproc = process_central_dir(zh as ZipHandle, cd_entries)
454 if not files then 502 if not files then
455 return nil, err 503 return nil, errproc
456 end 504 end
457 505
458 for _, cdr in ipairs(files) do 506 for _, cdr in ipairs(files) do
459 local file = cdr.file_name 507 local file = cdr.file_name
460 if file:sub(#file) == "/" then 508 if file:sub(#file) == "/" then
461 local ok, err = fs.make_dir(dir.path(fs.current_dir(), file)) 509 local okmake, errmake = fs.make_dir(dir.path(fs.current_dir(), file))
462 if not ok then 510 if not okmake then
463 return nil, err 511 return nil, errmake
464 end 512 end
465 else 513 else
466 local base = dir.dir_name(file) 514 local base = dir.dir_name(file)
467 if base ~= "" then 515 if base ~= "" then
468 base = dir.path(fs.current_dir(), base) 516 base = dir.path(fs.current_dir(), base)
469 if not fs.is_dir(base) then 517 if not fs.is_dir(base) then
470 local ok, err = fs.make_dir(base) 518 local okmake, errmake = fs.make_dir(base)
471 if not ok then 519 if not okmake then
472 return nil, err 520 return nil, errmake
473 end 521 end
474 end 522 end
475 end 523 end
476 524
477 local ok, err = zh:seek("set", cdr.offset) 525 local okseek2, errseek2 = zh:seek("set", cdr.offset)
478 if not ok then 526 if not okseek2 then
479 return nil, err 527 return nil, errseek2
480 end 528 end
481 529
482 local contents, err = read_file_in_zip(zh, cdr) 530 local contents, err = read_file_in_zip(zh, cdr)
@@ -484,10 +532,10 @@ function zip.unzip(zipfile)
484 return nil, err 532 return nil, err
485 end 533 end
486 local pathname = dir.path(fs.current_dir(), file) 534 local pathname = dir.path(fs.current_dir(), file)
487 local wf, err = io.open(pathname, "wb") 535 local wf, erropen2 = io.open(pathname, "wb")
488 if not wf then 536 if not wf then
489 zh:close() 537 zh:close()
490 return nil, err 538 return nil, erropen2
491 end 539 end
492 wf:write(contents) 540 wf:write(contents)
493 wf:close() 541 wf:close()
@@ -504,9 +552,7 @@ function zip.unzip(zipfile)
504 return true 552 return true
505end 553end
506 554
507function zip.gzip(input_filename, output_filename) 555function zip.gzip(input_filename: string, output_filename?: string): boolean, string
508 assert(type(input_filename) == "string")
509 assert(output_filename == nil or type(output_filename) == "string")
510 556
511 if not output_filename then 557 if not output_filename then
512 output_filename = input_filename .. ".gz" 558 output_filename = input_filename .. ".gz"
@@ -516,9 +562,7 @@ function zip.gzip(input_filename, output_filename)
516 return fs.filter_file(fn, input_filename, output_filename) 562 return fs.filter_file(fn, input_filename, output_filename)
517end 563end
518 564
519function zip.gunzip(input_filename, output_filename) 565function zip.gunzip(input_filename: string, output_filename?: string): boolean, string
520 assert(type(input_filename) == "string")
521 assert(output_filename == nil or type(output_filename) == "string")
522 566
523 if not output_filename then 567 if not output_filename then
524 output_filename = input_filename:gsub("%.gz$", "") 568 output_filename = input_filename:gsub("%.gz$", "")