diff options
author | V1K1NGbg <victor@ilchev.com> | 2024-08-03 14:49:25 +0300 |
---|---|---|
committer | V1K1NGbg <victor@ilchev.com> | 2024-08-05 20:51:31 +0300 |
commit | a22cc0d426e52254cca0ed623f1514b8391b48b3 (patch) | |
tree | 59c2894fe90b6f645c918d305693176e7c6288ee | |
parent | 3c2ab76e26c3cd4c863b7902cfd3f4424784d6b6 (diff) | |
download | luarocks-a22cc0d426e52254cca0ed623f1514b8391b48b3.tar.gz luarocks-a22cc0d426e52254cca0ed623f1514b8391b48b3.tar.bz2 luarocks-a22cc0d426e52254cca0ed623f1514b8391b48b3.zip |
patch 2
-rw-r--r-- | src/luarocks/fs.d.tl | 2 | ||||
-rw-r--r-- | src/luarocks/fun.tl | 2 | ||||
-rw-r--r-- | src/luarocks/tools/patch.tl | 148 |
3 files changed, 79 insertions, 73 deletions
diff --git a/src/luarocks/fs.d.tl b/src/luarocks/fs.d.tl index 17cf0517..a2218cd6 100644 --- a/src/luarocks/fs.d.tl +++ b/src/luarocks/fs.d.tl | |||
@@ -27,6 +27,8 @@ local record fs | |||
27 | Q: function(string): string | 27 | Q: function(string): string |
28 | download: function(string, string): boolean, string | 28 | download: function(string, string): boolean, string |
29 | set_permissions: function(string, string, string) | 29 | set_permissions: function(string, string, string) |
30 | -- patch | ||
31 | absolute_name: function(string, ?string): string | ||
30 | end | 32 | end |
31 | 33 | ||
32 | return fs | 34 | return fs |
diff --git a/src/luarocks/fun.tl b/src/luarocks/fun.tl index 16873dc2..e2d43d5d 100644 --- a/src/luarocks/fun.tl +++ b/src/luarocks/fun.tl | |||
@@ -16,7 +16,7 @@ function fun.concat<K>(xs: {K}, ys: {K}): {K} | |||
16 | return rs | 16 | return rs |
17 | end | 17 | end |
18 | 18 | ||
19 | function fun.contains<K>(xs: {K}, v: K): boolean --? same logic as above fine? | 19 | function fun.contains<K>(xs: {K}, v: any): boolean --? same logic as above fine? |
20 | for _, x in ipairs(xs) do | 20 | for _, x in ipairs(xs) do |
21 | if v == x then | 21 | if v == x then |
22 | return true | 22 | return true |
diff --git a/src/luarocks/tools/patch.tl b/src/luarocks/tools/patch.tl index 05b447da..bd6c3d63 100644 --- a/src/luarocks/tools/patch.tl +++ b/src/luarocks/tools/patch.tl | |||
@@ -14,7 +14,7 @@ local record patch | |||
14 | crlf: number | 14 | crlf: number |
15 | cr: number | 15 | cr: number |
16 | end | 16 | end |
17 | record Hunks | 17 | record Hunk |
18 | startsrc: number | 18 | startsrc: number |
19 | linessrc: number | 19 | linessrc: number |
20 | starttgt: number | 20 | starttgt: number |
@@ -22,24 +22,27 @@ local record patch | |||
22 | invalid: boolean | 22 | invalid: boolean |
23 | text: {string} | 23 | text: {string} |
24 | end | 24 | end |
25 | record Files | ||
26 | source: {string | number} --! | ||
27 | target: {string | number} | ||
28 | epoch: {boolean} | ||
29 | hunks: {{Hunk}} | ||
30 | fileends: {Lineends} | ||
31 | hunkends: {Lineends} | ||
32 | end | ||
25 | end | 33 | end |
26 | 34 | ||
27 | local fs = require("luarocks.fs") | 35 | local fs = require("luarocks.fs") |
28 | local fun = require("luarocks.fun") | 36 | local fun = require("luarocks.fun") |
29 | 37 | ||
30 | local type Lineends = patch.Lineends | 38 | local type Lineends = patch.Lineends |
31 | local type Hunks = patch.Hunks | 39 | local type Hunk = patch.Hunk |
32 | 40 | local type Files = patch.Files | |
33 | -- local io = io | ||
34 | -- local os = os | ||
35 | -- local string = string | ||
36 | -- local table = table | ||
37 | -- local format = string.format | ||
38 | 41 | ||
39 | -- logging | 42 | -- logging |
40 | local debugmode = false | 43 | local debugmode = false |
41 | local function debug(_) end --! | 44 | local function debug(_: string) end --! |
42 | local function info(_) end | 45 | local function info(_: string) end |
43 | local function warning(s: string) io.stderr:write(s .. '\n') end | 46 | local function warning(s: string) io.stderr:write(s .. '\n') end |
44 | 47 | ||
45 | -- Returns boolean whether string s2 starts with string s. | 48 | -- Returns boolean whether string s2 starts with string s. |
@@ -148,7 +151,7 @@ local function match_epoch(str: string): string | |||
148 | return str:match("[^0-9]1969[^0-9]") or str:match("[^0-9]1970[^0-9]") | 151 | return str:match("[^0-9]1969[^0-9]") or str:match("[^0-9]1970[^0-9]") |
149 | end | 152 | end |
150 | 153 | ||
151 | function patch.read_patch(filename: string, data: string) | 154 | function patch.read_patch(filename: string, data: string): Files, boolean |
152 | -- define possible file regions that will direct the parser flow | 155 | -- define possible file regions that will direct the parser flow |
153 | local state = 'header' | 156 | local state = 'header' |
154 | -- 'header' - comments before the patch body | 157 | -- 'header' - comments before the patch body |
@@ -159,17 +162,17 @@ function patch.read_patch(filename: string, data: string) | |||
159 | 162 | ||
160 | local all_ok = true | 163 | local all_ok = true |
161 | local lineends: Lineends = {lf=0, crlf=0, cr=0} | 164 | local lineends: Lineends = {lf=0, crlf=0, cr=0} |
162 | local files = {source={}, target={}, epoch={}, hunks: {{Hunks}}={}, fileends={}, hunkends: {Lineends}={}} | 165 | local files: Files = {source={}, target={}, epoch={}, hunks: {{Hunk}}={}, fileends={}, hunkends: {Lineends}={}} |
163 | local nextfileno = 0 | 166 | local nextfileno = 0 |
164 | local nexthunkno = 0 --: even if index starts with 0 user messages | 167 | local nexthunkno = 0 --: even if index starts with 0 user messages |
165 | -- number hunks from 1 | 168 | -- number hunks from 1 |
166 | 169 | ||
167 | -- hunkinfo holds parsed values, hunkactual - calculated | 170 | -- hunkinfo holds parsed values, hunkactual - calculated |
168 | local hunkinfo: Hunks = { | 171 | local hunkinfo: Hunk = { |
169 | startsrc=nil, linessrc=nil, starttgt=nil, linestgt=nil, | 172 | startsrc=nil, linessrc=nil, starttgt=nil, linestgt=nil, |
170 | invalid=false, text={} | 173 | invalid=false, text={} |
171 | } | 174 | } |
172 | local hunkactual: Hunks = {linessrc=nil, linestgt=nil} | 175 | local hunkactual: Hunk = {linessrc=nil, linestgt=nil} |
173 | 176 | ||
174 | info(string.format("reading patch %s", filename)) --! | 177 | info(string.format("reading patch %s", filename)) --! |
175 | 178 | ||
@@ -224,7 +227,7 @@ function patch.read_patch(filename: string, data: string) | |||
224 | warning(string.format("invalid hunk no.%d at %d for target file %s", | 227 | warning(string.format("invalid hunk no.%d at %d for target file %s", |
225 | nexthunkno, lineno, files.target[nextfileno])) | 228 | nexthunkno, lineno, files.target[nextfileno])) |
226 | -- add hunk status node | 229 | -- add hunk status node |
227 | table.insert(files.hunks[nextfileno], table_copy(hunkinfo)) --! cast | 230 | table.insert(files.hunks[nextfileno], table_copy(hunkinfo as {any: any}) as Hunk) |
228 | files.hunks[nextfileno][nexthunkno].invalid = true | 231 | files.hunks[nextfileno][nexthunkno].invalid = true |
229 | all_ok = false | 232 | all_ok = false |
230 | state = 'hunkskip' | 233 | state = 'hunkskip' |
@@ -237,13 +240,13 @@ function patch.read_patch(filename: string, data: string) | |||
237 | warning(string.format("extra hunk no.%d lines at %d for target %s", | 240 | warning(string.format("extra hunk no.%d lines at %d for target %s", |
238 | nexthunkno, lineno, files.target[nextfileno])) | 241 | nexthunkno, lineno, files.target[nextfileno])) |
239 | -- add hunk status node | 242 | -- add hunk status node |
240 | table.insert(files.hunks[nextfileno], table_copy(hunkinfo)) | 243 | table.insert(files.hunks[nextfileno], table_copy(hunkinfo as {any: any}) as Hunk) |
241 | files.hunks[nextfileno][nexthunkno].invalid = true | 244 | files.hunks[nextfileno][nexthunkno].invalid = true |
242 | state = 'hunkskip' | 245 | state = 'hunkskip' |
243 | elseif hunkinfo.linessrc == hunkactual.linessrc and | 246 | elseif hunkinfo.linessrc == hunkactual.linessrc and |
244 | hunkinfo.linestgt == hunkactual.linestgt | 247 | hunkinfo.linestgt == hunkactual.linestgt |
245 | then | 248 | then |
246 | table.insert(files.hunks[nextfileno], table_copy(hunkinfo)) | 249 | table.insert(files.hunks[nextfileno], table_copy(hunkinfo as {any: any}) as Hunk) |
247 | state = 'hunkskip' | 250 | state = 'hunkskip' |
248 | 251 | ||
249 | -- detect mixed window/unix line ends | 252 | -- detect mixed window/unix line ends |
@@ -264,18 +267,18 @@ function patch.read_patch(filename: string, data: string) | |||
264 | elseif startswith(line, "--- ") then | 267 | elseif startswith(line, "--- ") then |
265 | state = 'filenames' | 268 | state = 'filenames' |
266 | if debugmode and #files.source > 0 then | 269 | if debugmode and #files.source > 0 then |
267 | debug(format("- %2d hunks for %s", #files.hunks[nextfileno], | 270 | debug(string.format("- %2d hunks for %s", #files.hunks[nextfileno], |
268 | files.source[nextfileno])) | 271 | files.source[nextfileno])) |
269 | end | 272 | end |
270 | end | 273 | end |
271 | -- state is 'hunkskip', 'hunkhead', or 'filenames' | 274 | -- state is 'hunkskip', 'hunkhead', or 'filenames' |
272 | end | 275 | end |
273 | local advance | 276 | local advance: boolean |
274 | if state == 'filenames' then | 277 | if state == 'filenames' then |
275 | if startswith(line, "--- ") then | 278 | if startswith(line, "--- ") then |
276 | if fun.contains(files.source, nextfileno) then | 279 | if fun.contains(files.source, nextfileno) then |
277 | all_ok = false | 280 | all_ok = false |
278 | warning(format("skipping invalid patch for %s", | 281 | warning(string.format("skipping invalid patch for %s", |
279 | files.source[nextfileno+1])) | 282 | files.source[nextfileno+1])) |
280 | table.remove(files.source, nextfileno+1) | 283 | table.remove(files.source, nextfileno+1) |
281 | -- double source filename line is encountered | 284 | -- double source filename line is encountered |
@@ -287,7 +290,7 @@ function patch.read_patch(filename: string, data: string) | |||
287 | local match, rest = line:match("^%-%-%- ([^ \t\r\n]+)(.*)") | 290 | local match, rest = line:match("^%-%-%- ([^ \t\r\n]+)(.*)") |
288 | if not match then | 291 | if not match then |
289 | all_ok = false | 292 | all_ok = false |
290 | warning(format("skipping invalid filename at line %d", lineno+1)) | 293 | warning(string.format("skipping invalid filename at line %d", lineno+1)) |
291 | state = 'header' | 294 | state = 'header' |
292 | else | 295 | else |
293 | if match_epoch(rest) then | 296 | if match_epoch(rest) then |
@@ -298,7 +301,7 @@ function patch.read_patch(filename: string, data: string) | |||
298 | elseif not startswith(line, "+++ ") then | 301 | elseif not startswith(line, "+++ ") then |
299 | if fun.contains(files.source, nextfileno) then | 302 | if fun.contains(files.source, nextfileno) then |
300 | all_ok = false | 303 | all_ok = false |
301 | warning(format("skipping invalid patch with no target for %s", | 304 | warning(string.format("skipping invalid patch with no target for %s", |
302 | files.source[nextfileno+1])) | 305 | files.source[nextfileno+1])) |
303 | table.remove(files.source, nextfileno+1) | 306 | table.remove(files.source, nextfileno+1) |
304 | else | 307 | else |
@@ -309,7 +312,7 @@ function patch.read_patch(filename: string, data: string) | |||
309 | else | 312 | else |
310 | if fun.contains(files.target, nextfileno) then | 313 | if fun.contains(files.target, nextfileno) then |
311 | all_ok = false | 314 | all_ok = false |
312 | warning(format("skipping invalid patch - double target at line %d", | 315 | warning(string.format("skipping invalid patch - double target at line %d", |
313 | lineno+1)) | 316 | lineno+1)) |
314 | table.remove(files.source, nextfileno+1) | 317 | table.remove(files.source, nextfileno+1) |
315 | table.remove(files.target, nextfileno+1) | 318 | table.remove(files.target, nextfileno+1) |
@@ -325,7 +328,7 @@ function patch.read_patch(filename: string, data: string) | |||
325 | local match, rest = line:match(re_filename) | 328 | local match, rest = line:match(re_filename) |
326 | if not match then | 329 | if not match then |
327 | all_ok = false | 330 | all_ok = false |
328 | warning(format( | 331 | warning(string.format( |
329 | "skipping invalid patch - no target filename at line %d", | 332 | "skipping invalid patch - no target filename at line %d", |
330 | lineno+1)) | 333 | lineno+1)) |
331 | state = 'header' | 334 | state = 'header' |
@@ -337,8 +340,8 @@ function patch.read_patch(filename: string, data: string) | |||
337 | end | 340 | end |
338 | nexthunkno = 0 | 341 | nexthunkno = 0 |
339 | table.insert(files.hunks, {}) | 342 | table.insert(files.hunks, {}) |
340 | table.insert(files.hunkends, table_copy(lineends)) | 343 | table.insert(files.hunkends, table_copy(lineends as {any: any}) as Lineends) |
341 | table.insert(files.fileends, table_copy(lineends)) | 344 | table.insert(files.fileends, table_copy(lineends as {any: any}) as Lineends) |
342 | state = 'hunkhead' | 345 | state = 'hunkhead' |
343 | advance = true | 346 | advance = true |
344 | end | 347 | end |
@@ -349,17 +352,17 @@ function patch.read_patch(filename: string, data: string) | |||
349 | if not advance and state == 'hunkhead' then | 352 | if not advance and state == 'hunkhead' then |
350 | local m1, m2, m3, m4 = match_linerange(line) | 353 | local m1, m2, m3, m4 = match_linerange(line) |
351 | if not m1 then | 354 | if not m1 then |
352 | if not fun.contains(files.hunks, nextfileno-1) then | 355 | if not fun.contains(files.hunks, nextfileno-1) then --! |
353 | all_ok = false | 356 | all_ok = false |
354 | warning(format("skipping invalid patch with no hunks for file %s", | 357 | warning(string.format("skipping invalid patch with no hunks for file %s", |
355 | files.target[nextfileno])) | 358 | files.target[nextfileno])) |
356 | end | 359 | end |
357 | state = 'header' | 360 | state = 'header' |
358 | else | 361 | else |
359 | hunkinfo.startsrc = tonumber(m1) | 362 | hunkinfo.startsrc = tonumber(m1) |
360 | hunkinfo.linessrc = tonumber(m2 or 1) | 363 | hunkinfo.linessrc = tonumber(tonumber(m2) or 1) --! |
361 | hunkinfo.starttgt = tonumber(m3) | 364 | hunkinfo.starttgt = tonumber(m3) |
362 | hunkinfo.linestgt = tonumber(m4 or 1) | 365 | hunkinfo.linestgt = tonumber(tonumber(m4) or 1) |
363 | hunkinfo.invalid = false | 366 | hunkinfo.invalid = false |
364 | hunkinfo.text = {} | 367 | hunkinfo.text = {} |
365 | 368 | ||
@@ -373,24 +376,24 @@ function patch.read_patch(filename: string, data: string) | |||
373 | end | 376 | end |
374 | end | 377 | end |
375 | if state ~= 'hunkskip' then | 378 | if state ~= 'hunkskip' then |
376 | warning(format("patch file incomplete - %s", filename)) | 379 | warning(string.format("patch file incomplete - %s", filename)) |
377 | all_ok = false | 380 | all_ok = false |
378 | -- os.exit(?) | 381 | -- os.exit(?) |
379 | else | 382 | else |
380 | -- duplicated message when an eof is reached | 383 | -- duplicated message when an eof is reached |
381 | if debugmode and #files.source > 0 then | 384 | if debugmode and #files.source > 0 then |
382 | debug(format("- %2d hunks for %s", #files.hunks[nextfileno], | 385 | debug(string.format("- %2d hunks for %s", #files.hunks[nextfileno], |
383 | files.source[nextfileno])) | 386 | files.source[nextfileno])) |
384 | end | 387 | end |
385 | end | 388 | end |
386 | 389 | ||
387 | local sum = 0; for _,hset in ipairs(files.hunks) do sum = sum + #hset end | 390 | local sum = 0; for _,hset in ipairs(files.hunks) do sum = sum + #hset end |
388 | info(format("total files: %d total hunks: %d", #files.source, sum)) | 391 | info(string.format("total files: %d total hunks: %d", #files.source, sum)) |
389 | fp:close() | 392 | fp:close() |
390 | return files, all_ok | 393 | return files, all_ok |
391 | end | 394 | end |
392 | 395 | ||
393 | local function find_hunk(file, h, hno) | 396 | local function find_hunk(file: {string}, h: Hunk, hno: number): boolean |
394 | for fuzz=0,2 do | 397 | for fuzz=0,2 do |
395 | local lineno = h.startsrc | 398 | local lineno = h.startsrc |
396 | for i=0,#file do | 399 | for i=0,#file do |
@@ -400,7 +403,7 @@ local function find_hunk(file, h, hno) | |||
400 | if l > fuzz then | 403 | if l > fuzz then |
401 | -- todo: \ No newline at the end of file | 404 | -- todo: \ No newline at the end of file |
402 | if startswith(hline, " ") or startswith(hline, "-") then | 405 | if startswith(hline, " ") or startswith(hline, "-") then |
403 | local line = file[lineno] | 406 | local line = file[lineno as integer] --! cast |
404 | lineno = lineno + 1 | 407 | lineno = lineno + 1 |
405 | if not line or #line == 0 then | 408 | if not line or #line == 0 then |
406 | found = false | 409 | found = false |
@@ -416,7 +419,7 @@ local function find_hunk(file, h, hno) | |||
416 | if found then | 419 | if found then |
417 | local offset = location - h.startsrc - fuzz | 420 | local offset = location - h.startsrc - fuzz |
418 | if offset ~= 0 then | 421 | if offset ~= 0 then |
419 | warning(format("Hunk %d found at offset %d%s...", hno, offset, fuzz == 0 and "" or format(" (fuzz %d)", fuzz))) | 422 | warning(string.format("Hunk %d found at offset %d%s...", hno, offset, fuzz == 0 and "" or string.format(" (fuzz %d)", fuzz))) |
420 | end | 423 | end |
421 | h.startsrc = location | 424 | h.startsrc = location |
422 | h.starttgt = h.starttgt + offset | 425 | h.starttgt = h.starttgt + offset |
@@ -432,8 +435,8 @@ local function find_hunk(file, h, hno) | |||
432 | return false | 435 | return false |
433 | end | 436 | end |
434 | 437 | ||
435 | local function load_file(filename) | 438 | local function load_file(filename: string): {string} |
436 | local fp = assert(io.open(filename)) | 439 | local fp = assert(io.open(filename) as (FILE, string)) --! cast |
437 | local file = {} | 440 | local file = {} |
438 | local readline = file_lines(fp) | 441 | local readline = file_lines(fp) |
439 | while true do | 442 | while true do |
@@ -445,15 +448,15 @@ local function load_file(filename) | |||
445 | return file | 448 | return file |
446 | end | 449 | end |
447 | 450 | ||
448 | local function find_hunks(file, hunks) | 451 | local function find_hunks(file: {string}, hunks: {Hunk}) |
449 | for hno, h in ipairs(hunks) do | 452 | for hno, h in ipairs(hunks) do |
450 | find_hunk(file, h, hno) | 453 | find_hunk(file, h, hno) |
451 | end | 454 | end |
452 | end | 455 | end |
453 | 456 | ||
454 | local function check_patched(file, hunks) | 457 | local function check_patched(file: {string}, hunks: {Hunk}): boolean |
455 | local lineno = 1 | 458 | local lineno: integer = 1 |
456 | local ok, err = pcall(function() | 459 | local ok, err: boolean, string = pcall(function() |
457 | if #file == 0 then | 460 | if #file == 0 then |
458 | error('nomatch', 0) | 461 | error('nomatch', 0) |
459 | end | 462 | end |
@@ -462,7 +465,7 @@ local function check_patched(file, hunks) | |||
462 | if #file < h.starttgt then | 465 | if #file < h.starttgt then |
463 | error('nomatch', 0) | 466 | error('nomatch', 0) |
464 | end | 467 | end |
465 | lineno = h.starttgt | 468 | lineno = h.starttgt as integer --! cast |
466 | for _, hline in ipairs(h.text) do | 469 | for _, hline in ipairs(h.text) do |
467 | -- todo: \ No newline at the end of file | 470 | -- todo: \ No newline at the end of file |
468 | if not startswith(hline, "-") and not startswith(hline, "\\") then | 471 | if not startswith(hline, "-") and not startswith(hline, "\\") then |
@@ -472,7 +475,7 @@ local function check_patched(file, hunks) | |||
472 | error('nomatch', 0) | 475 | error('nomatch', 0) |
473 | end | 476 | end |
474 | if endlstrip(line) ~= endlstrip(hline:sub(2)) then | 477 | if endlstrip(line) ~= endlstrip(hline:sub(2)) then |
475 | warning(format("file is not patched - failed hunk: %d", hno)) | 478 | warning(string.format("file is not patched - failed hunk: %d", hno)) |
476 | error('nomatch', 0) | 479 | error('nomatch', 0) |
477 | end | 480 | end |
478 | end | 481 | end |
@@ -483,9 +486,9 @@ local function check_patched(file, hunks) | |||
483 | return err ~= 'nomatch' | 486 | return err ~= 'nomatch' |
484 | end | 487 | end |
485 | 488 | ||
486 | local function patch_hunks(srcname, tgtname, hunks) | 489 | local function patch_hunks(srcname: string, tgtname: string, hunks: {Hunk}): boolean |
487 | local src = assert(io.open(srcname, "rb")) | 490 | local src = assert(io.open(srcname, "rb") as (FILE, string)) --! cast |
488 | local tgt = assert(io.open(tgtname, "wb")) | 491 | local tgt = assert(io.open(tgtname, "wb") as (FILE, string)) --! cast |
489 | 492 | ||
490 | local src_readline = file_lines(src) | 493 | local src_readline = file_lines(src) |
491 | 494 | ||
@@ -498,7 +501,7 @@ local function patch_hunks(srcname, tgtname, hunks) | |||
498 | local srclineno = 1 | 501 | local srclineno = 1 |
499 | local lineends = {['\n']=0, ['\r\n']=0, ['\r']=0} | 502 | local lineends = {['\n']=0, ['\r\n']=0, ['\r']=0} |
500 | for hno, h in ipairs(hunks) do | 503 | for hno, h in ipairs(hunks) do |
501 | debug(format("processing hunk %d for file %s", hno, tgtname)) | 504 | debug(string.format("processing hunk %d for file %s", hno, tgtname)) |
502 | -- skip to line just before hunk starts | 505 | -- skip to line just before hunk starts |
503 | while srclineno < h.startsrc do | 506 | while srclineno < h.startsrc do |
504 | local line = src_readline() | 507 | local line = src_readline() |
@@ -527,10 +530,10 @@ local function patch_hunks(srcname, tgtname, hunks) | |||
527 | local line2write = hline:sub(2) | 530 | local line2write = hline:sub(2) |
528 | -- detect if line ends are consistent in source file | 531 | -- detect if line ends are consistent in source file |
529 | local sum = 0 | 532 | local sum = 0 |
530 | for _,v in pairs(lineends) do if v > 0 then sum=sum+1 end end | 533 | for _,v in pairs(lineends as {string:any}) do if v as integer > 0 then sum=sum+1 end end --! unchecked |
531 | if sum == 1 then | 534 | if sum == 1 then |
532 | local newline | 535 | local newline: string |
533 | for k,v in pairs(lineends) do if v ~= 0 then newline = k end end | 536 | for k,v in pairs(lineends as {string:any}) do if v ~= 0 then newline = k end end |
534 | tgt:write(endlstrip(line2write) .. newline) | 537 | tgt:write(endlstrip(line2write) .. newline) |
535 | else -- newlines are mixed or unknown | 538 | else -- newlines are mixed or unknown |
536 | tgt:write(line2write) | 539 | tgt:write(line2write) |
@@ -546,7 +549,7 @@ local function patch_hunks(srcname, tgtname, hunks) | |||
546 | return true | 549 | return true |
547 | end | 550 | end |
548 | 551 | ||
549 | local function strip_dirs(filename, strip) | 552 | local function strip_dirs(filename: string, strip: integer): string |
550 | if strip == nil then return filename end | 553 | if strip == nil then return filename end |
551 | for _=1,strip do | 554 | for _=1,strip do |
552 | filename=filename:gsub("^[^/]*/", "") | 555 | filename=filename:gsub("^[^/]*/", "") |
@@ -554,7 +557,7 @@ local function strip_dirs(filename, strip) | |||
554 | return filename | 557 | return filename |
555 | end | 558 | end |
556 | 559 | ||
557 | local function write_new_file(filename, hunk) | 560 | local function write_new_file(filename: string, hunk: Hunk): boolean, string |
558 | local fh = io.open(filename, "wb") | 561 | local fh = io.open(filename, "wb") |
559 | if not fh then return false end | 562 | if not fh then return false end |
560 | for _, hline in ipairs(hunk.text) do | 563 | for _, hline in ipairs(hunk.text) do |
@@ -568,12 +571,12 @@ local function write_new_file(filename, hunk) | |||
568 | return true | 571 | return true |
569 | end | 572 | end |
570 | 573 | ||
571 | local function patch_file(source, target, epoch, hunks, strip, create_delete) | 574 | local function patch_file(source: string, target: string, epoch: boolean, hunks: {Hunk}, strip: integer, create_delete: boolean): boolean, string |
572 | local create_file = false | 575 | local create_file = false |
573 | if create_delete then | 576 | if create_delete then |
574 | local is_src_epoch = epoch and #hunks == 1 and hunks[1].startsrc == 0 and hunks[1].linessrc == 0 | 577 | local is_src_epoch = epoch and #hunks == 1 and hunks[1].startsrc == 0 and hunks[1].linessrc == 0 |
575 | if is_src_epoch or source == "/dev/null" then | 578 | if is_src_epoch or source == "/dev/null" then |
576 | info(format("will create %s", target)) | 579 | info(string.format("will create %s", target)) |
577 | create_file = true | 580 | create_file = true |
578 | end | 581 | end |
579 | end | 582 | end |
@@ -586,13 +589,14 @@ local function patch_file(source, target, epoch, hunks, strip, create_delete) | |||
586 | f2patch = strip_dirs(target, strip) | 589 | f2patch = strip_dirs(target, strip) |
587 | f2patch = fs.absolute_name(f2patch) | 590 | f2patch = fs.absolute_name(f2patch) |
588 | if not exists(f2patch) then --FIX:if f2patch nil | 591 | if not exists(f2patch) then --FIX:if f2patch nil |
589 | warning(format("source/target file does not exist\n--- %s\n+++ %s", | 592 | warning(string.format("source/target file does not exist\n--- %s\n+++ %s", |
590 | source, f2patch)) | 593 | source, f2patch)) |
591 | return false | 594 | return false |
592 | end | 595 | end |
593 | end | 596 | end |
594 | if not isfile(f2patch) then | 597 | -- if not isfile(f2patch) then --! |
595 | warning(format("not a file - %s", f2patch)) | 598 | if not isfile() then --! |
599 | warning(string.format("not a file - %s", f2patch)) | ||
596 | return false | 600 | return false |
597 | end | 601 | end |
598 | 602 | ||
@@ -605,7 +609,7 @@ local function patch_file(source, target, epoch, hunks, strip, create_delete) | |||
605 | local hunkfind = {} | 609 | local hunkfind = {} |
606 | local validhunks = 0 | 610 | local validhunks = 0 |
607 | local canpatch = false | 611 | local canpatch = false |
608 | local hunklineno | 612 | local hunklineno: integer |
609 | if not file then | 613 | if not file then |
610 | return nil, "failed reading file " .. source | 614 | return nil, "failed reading file " .. source |
611 | end | 615 | end |
@@ -616,14 +620,14 @@ local function patch_file(source, target, epoch, hunks, strip, create_delete) | |||
616 | if not ok then | 620 | if not ok then |
617 | return false | 621 | return false |
618 | end | 622 | end |
619 | info(format("successfully removed %s", source)) | 623 | info(string.format("successfully removed %s", source)) |
620 | return true | 624 | return true |
621 | end | 625 | end |
622 | end | 626 | end |
623 | 627 | ||
624 | find_hunks(file, hunks) | 628 | find_hunks(file, hunks) |
625 | 629 | ||
626 | local function process_line(line, lineno) | 630 | local function process_line(line: string, lineno: number): boolean |
627 | if not hunk or lineno < hunk.startsrc then | 631 | if not hunk or lineno < hunk.startsrc then |
628 | return false | 632 | return false |
629 | end | 633 | end |
@@ -643,7 +647,7 @@ local function patch_file(source, target, epoch, hunks, strip, create_delete) | |||
643 | if endlstrip(line) == hunkfind[hunklineno] then | 647 | if endlstrip(line) == hunkfind[hunklineno] then |
644 | hunklineno = hunklineno + 1 | 648 | hunklineno = hunklineno + 1 |
645 | else | 649 | else |
646 | debug(format("hunk no.%d doesn't match source file %s", | 650 | debug(string.format("hunk no.%d doesn't match source file %s", |
647 | hunkno, source)) | 651 | hunkno, source)) |
648 | -- file may be already patched, but check other hunks anyway | 652 | -- file may be already patched, but check other hunks anyway |
649 | hunkno = hunkno + 1 | 653 | hunkno = hunkno + 1 |
@@ -657,7 +661,7 @@ local function patch_file(source, target, epoch, hunks, strip, create_delete) | |||
657 | end | 661 | end |
658 | -- check if processed line is the last line | 662 | -- check if processed line is the last line |
659 | if lineno == hunk.startsrc + #hunkfind - 1 then | 663 | if lineno == hunk.startsrc + #hunkfind - 1 then |
660 | debug(format("file %s hunk no.%d -- is ready to be patched", | 664 | debug(string.format("file %s hunk no.%d -- is ready to be patched", |
661 | source, hunkno)) | 665 | source, hunkno)) |
662 | hunkno = hunkno + 1 | 666 | hunkno = hunkno + 1 |
663 | validhunks = validhunks + 1 | 667 | validhunks = validhunks + 1 |
@@ -683,16 +687,16 @@ local function patch_file(source, target, epoch, hunks, strip, create_delete) | |||
683 | end | 687 | end |
684 | if not done then | 688 | if not done then |
685 | if hunkno <= #hunks and not create_file then | 689 | if hunkno <= #hunks and not create_file then |
686 | warning(format("premature end of source file %s at hunk %d", | 690 | warning(string.format("premature end of source file %s at hunk %d", |
687 | source, hunkno)) | 691 | source, hunkno)) |
688 | return false | 692 | return false |
689 | end | 693 | end |
690 | end | 694 | end |
691 | if validhunks < #hunks then | 695 | if validhunks < #hunks then |
692 | if check_patched(file, hunks) then | 696 | if check_patched(file, hunks) then |
693 | warning(format("already patched %s", source)) | 697 | warning(string.format("already patched %s", source)) |
694 | elseif not create_file then | 698 | elseif not create_file then |
695 | warning(format("source file is different - %s", source)) | 699 | warning(string.format("source file is different - %s", source)) |
696 | return false | 700 | return false |
697 | end | 701 | end |
698 | end | 702 | end |
@@ -701,30 +705,30 @@ local function patch_file(source, target, epoch, hunks, strip, create_delete) | |||
701 | end | 705 | end |
702 | local backupname = source .. ".orig" | 706 | local backupname = source .. ".orig" |
703 | if exists(backupname) then | 707 | if exists(backupname) then |
704 | warning(format("can't backup original file to %s - aborting", | 708 | warning(string.format("can't backup original file to %s - aborting", |
705 | backupname)) | 709 | backupname)) |
706 | return false | 710 | return false |
707 | end | 711 | end |
708 | local ok = os.rename(source, backupname) | 712 | local ok = os.rename(source, backupname) |
709 | if not ok then | 713 | if not ok then |
710 | warning(format("failed backing up %s when patching", source)) | 714 | warning(string.format("failed backing up %s when patching", source)) |
711 | return false | 715 | return false |
712 | end | 716 | end |
713 | patch_hunks(backupname, source, hunks) | 717 | patch_hunks(backupname, source, hunks) |
714 | info(format("successfully patched %s", source)) | 718 | info(string.format("successfully patched %s", source)) |
715 | os.remove(backupname) | 719 | os.remove(backupname) |
716 | return true | 720 | return true |
717 | end | 721 | end |
718 | 722 | ||
719 | function patch.apply_patch(the_patch, strip, create_delete) | 723 | function patch.apply_patch(the_patch: Files, strip: integer, create_delete: boolean): boolean |
720 | local all_ok = true | 724 | local all_ok = true |
721 | local total = #the_patch.source | 725 | local total = #the_patch.source |
722 | for fileno, source in ipairs(the_patch.source) do | 726 | for fileno, source in ipairs(the_patch.source) do |
723 | local target = the_patch.target[fileno] | 727 | local target = the_patch.target[fileno] |
724 | local hunks = the_patch.hunks[fileno] | 728 | local hunks = the_patch.hunks[fileno] |
725 | local epoch = the_patch.epoch[fileno] | 729 | local epoch = the_patch.epoch[fileno] |
726 | info(format("processing %d/%d:\t %s", fileno, total, source)) | 730 | info(string.format("processing %d/%d:\t %s", fileno, total, source)) |
727 | local ok = patch_file(source, target, epoch, hunks, strip, create_delete) | 731 | local ok = patch_file(tostring(source), tostring(target), epoch, hunks, strip, create_delete) |
728 | all_ok = all_ok and ok | 732 | all_ok = all_ok and ok |
729 | end | 733 | end |
730 | -- todo: check for premature eof | 734 | -- todo: check for premature eof |