| ... | @@ -107,6 +107,7 @@ pub fn main() !void { | ... | @@ -107,6 +107,7 @@ pub fn main() !void { |
| 107 | var steps_menu = false; | 107 | var steps_menu = false; |
| 108 | var output_tmp_nonce: ?[16]u8 = null; | 108 | var output_tmp_nonce: ?[16]u8 = null; |
| 109 | var watch = false; | 109 | var watch = false; |
| | 110 | var debounce_interval_ms: u16 = 50; |
| 110 | | 111 | |
| 111 | while (nextArg(args, &arg_idx)) |arg| { | 112 | while (nextArg(args, &arg_idx)) |arg| { |
| 112 | if (mem.startsWith(u8, arg, "-Z")) { | 113 | if (mem.startsWith(u8, arg, "-Z")) { |
| ... | @@ -194,7 +195,15 @@ pub fn main() !void { | ... | @@ -194,7 +195,15 @@ pub fn main() !void { |
| 194 | const next_arg = nextArg(args, &arg_idx) orelse | 195 | const next_arg = nextArg(args, &arg_idx) orelse |
| 195 | fatalWithHint("expected u32 after '{s}'", .{arg}); | 196 | fatalWithHint("expected u32 after '{s}'", .{arg}); |
| 196 | seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| { | 197 | seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| { |
| 197 | fatal("unable to parse seed '{s}' as 32-bit integer: {s}\n", .{ | 198 | fatal("unable to parse seed '{s}' as unsigned 32-bit integer: {s}\n", .{ |
| | 199 | next_arg, @errorName(err), |
| | 200 | }); |
| | 201 | }; |
| | 202 | } else if (mem.eql(u8, arg, "--debounce")) { |
| | 203 | const next_arg = nextArg(args, &arg_idx) orelse |
| | 204 | fatalWithHint("expected u16 after '{s}'", .{arg}); |
| | 205 | debounce_interval_ms = std.fmt.parseUnsigned(u16, next_arg, 0) catch |err| { |
| | 206 | fatal("unable to parse debounce interval '{s}' as unsigned 16-bit integer: {s}\n", .{ |
| 198 | next_arg, @errorName(err), | 207 | next_arg, @errorName(err), |
| 199 | }); | 208 | }); |
| 200 | }; | 209 | }; |
| ... | @@ -473,7 +482,6 @@ pub fn main() !void { | ... | @@ -473,7 +482,6 @@ pub fn main() !void { |
| 473 | // if any more events come in. After the debounce interval has passed, | 482 | // if any more events come in. After the debounce interval has passed, |
| 474 | // trigger a rebuild on all steps with modified inputs, as well as their | 483 | // trigger a rebuild on all steps with modified inputs, as well as their |
| 475 | // recursive dependants. | 484 | // recursive dependants. |
| 476 | const debounce_interval_ms = 50; | | |
| 477 | var poll_fds: [1]std.posix.pollfd = .{ | 485 | var poll_fds: [1]std.posix.pollfd = .{ |
| 478 | .{ | 486 | .{ |
| 479 | .fd = w.fan_fd, | 487 | .fd = w.fan_fd, |
| ... | @@ -515,67 +523,29 @@ fn markDirtySteps(w: *Watch) !bool { | ... | @@ -515,67 +523,29 @@ fn markDirtySteps(w: *Watch) !bool { |
| 515 | error.WouldBlock => return any_dirty, | 523 | error.WouldBlock => return any_dirty, |
| 516 | else => |e| return e, | 524 | else => |e| return e, |
| 517 | }; | 525 | }; |
| 518 | //std.debug.dump_hex(events_buf[0..len]); | | |
| 519 | var meta: [*]align(1) M = @ptrCast(&events_buf); | 526 | var meta: [*]align(1) M = @ptrCast(&events_buf); |
| 520 | while (len >= @sizeOf(M) and meta[0].event_len >= @sizeOf(M) and meta[0].event_len <= len) : ({ | 527 | while (len >= @sizeOf(M) and meta[0].event_len >= @sizeOf(M) and meta[0].event_len <= len) : ({ |
| 521 | len -= meta[0].event_len; | 528 | len -= meta[0].event_len; |
| 522 | meta = @ptrCast(@as([*]u8, @ptrCast(meta)) + meta[0].event_len); | 529 | meta = @ptrCast(@as([*]u8, @ptrCast(meta)) + meta[0].event_len); |
| 523 | }) { | 530 | }) { |
| 524 | assert(meta[0].vers == M.VERSION); | 531 | assert(meta[0].vers == M.VERSION); |
| 525 | std.debug.print("meta = {any}\n", .{meta[0]}); | | |
| 526 | const fid: *align(1) fanotify.event_info_fid = @ptrCast(meta + 1); | 532 | const fid: *align(1) fanotify.event_info_fid = @ptrCast(meta + 1); |
| 527 | switch (fid.hdr.info_type) { | 533 | switch (fid.hdr.info_type) { |
| 528 | .DFID_NAME => { | 534 | .DFID_NAME => { |
| 529 | const file_handle: *align(1) std.os.linux.file_handle = @ptrCast(&fid.handle); | 535 | const file_handle: *align(1) std.os.linux.file_handle = @ptrCast(&fid.handle); |
| 530 | const file_name_z: [*:0]u8 = @ptrCast((&file_handle.f_handle).ptr + file_handle.handle_bytes); | 536 | const file_name_z: [*:0]u8 = @ptrCast((&file_handle.f_handle).ptr + file_handle.handle_bytes); |
| 531 | const file_name = mem.span(file_name_z); | 537 | const file_name = mem.span(file_name_z); |
| 532 | std.debug.print("DFID_NAME file_handle = {any}, found: '{s}'\n", .{ file_handle.*, file_name }); | | |
| 533 | const lfh: Watch.LinuxFileHandle = .{ .handle = file_handle }; | 538 | const lfh: Watch.LinuxFileHandle = .{ .handle = file_handle }; |
| 534 | if (w.handle_table.getPtr(lfh)) |reaction_set| { | 539 | if (w.handle_table.getPtr(lfh)) |reaction_set| { |
| 535 | if (reaction_set.getPtr(file_name)) |step_set| { | 540 | if (reaction_set.getPtr(file_name)) |step_set| { |
| 536 | for (step_set.keys()) |step| { | 541 | for (step_set.keys()) |step| { |
| 537 | std.debug.print("DFID_NAME marking step '{s}' dirty\n", .{step.name}); | | |
| 538 | step.state = .precheck_done; | 542 | step.state = .precheck_done; |
| 539 | any_dirty = true; | 543 | any_dirty = true; |
| 540 | } | 544 | } |
| 541 | } | 545 | } |
| 542 | } else { | | |
| 543 | std.debug.print("DFID_NAME changed file did not match any directories: '{}'\n", .{ | | |
| 544 | std.fmt.fmtSliceHexLower(lfh.slice()), | | |
| 545 | }); | | |
| 546 | } | 546 | } |
| 547 | }, | 547 | }, |
| 548 | //.FID => { | 548 | else => |t| std.log.warn("unexpected fanotify event '{s}'", .{@tagName(t)}), |
| 549 | // const file_handle: *align(1) std.os.linux.file_handle = @ptrCast(&fid.handle); | | |
| 550 | // const lfh: Watch.LinuxFileHandle = .{ .handle = file_handle }; | | |
| 551 | // if (w.handle_table.get(lfh)) |step_set| { | | |
| 552 | // for (step_set.keys()) |step| { | | |
| 553 | // std.debug.print("FID marking step '{s}' dirty\n", .{step.name}); | | |
| 554 | // step.state = .precheck_done; | | |
| 555 | // any_dirty = true; | | |
| 556 | // } | | |
| 557 | // } else { | | |
| 558 | // std.debug.print("FID changed file did not match any steps: '{}'\n", .{ | | |
| 559 | // std.fmt.fmtSliceHexLower(lfh.slice()), | | |
| 560 | // }); | | |
| 561 | // } | | |
| 562 | //}, | | |
| 563 | //.DFID => { | | |
| 564 | // const file_handle: *align(1) std.os.linux.file_handle = @ptrCast(&fid.handle); | | |
| 565 | // const lfh: Watch.LinuxFileHandle = .{ .handle = file_handle }; | | |
| 566 | // if (w.handle_table.get(lfh)) |step_set| { | | |
| 567 | // for (step_set.keys()) |step| { | | |
| 568 | // std.debug.print("DFID marking step '{s}' dirty\n", .{step.name}); | | |
| 569 | // step.state = .precheck_done; | | |
| 570 | // any_dirty = true; | | |
| 571 | // } | | |
| 572 | // } else { | | |
| 573 | // std.debug.print("DFID changed file did not match any steps\n", .{}); | | |
| 574 | // } | | |
| 575 | //}, | | |
| 576 | else => |t| { | | |
| 577 | std.debug.panic("TODO: received event type '{s}'", .{@tagName(t)}); | | |
| 578 | }, | | |
| 579 | } | 549 | } |
| 580 | } | 550 | } |
| 581 | } | 551 | } |
| ... | @@ -1349,6 +1319,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void { | ... | @@ -1349,6 +1319,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void { |
| 1349 | \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss | 1319 | \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss |
| 1350 | \\ --fetch Exit after fetching dependency tree | 1320 | \\ --fetch Exit after fetching dependency tree |
| 1351 | \\ --watch Continuously rebuild when source files are modified | 1321 | \\ --watch Continuously rebuild when source files are modified |
| | 1322 | \\ --debounce <ms> Delay before rebuilding after watched file detection |
| 1352 | \\ | 1323 | \\ |
| 1353 | \\Project-Specific Options: | 1324 | \\Project-Specific Options: |
| 1354 | \\ | 1325 | \\ |