#!perl -w # Copyright (C) all contributors # License: AGPL-3.0+ # # Ensure KQNotify can pick up rename(2) and link(2) operations # used by Maildir writing tools use v5.12; use PublicInbox::TestCommon; use autodie; require_bsd; require_mods('IO::KQueue'); use_ok 'PublicInbox::KQNotify'; my ($tmpdir, $for_destroy) = tmpdir(); mkdir "$tmpdir/new"; my $kqn = PublicInbox::KQNotify->new; my $mask = PublicInbox::KQNotify::MOVED_TO_OR_CREATE(); my $w = $kqn->watch("$tmpdir/new", $mask); open my $fh, '>', "$tmpdir/tst"; close $fh; rename("$tmpdir/tst", "$tmpdir/new/tst"); my $hit = [ map { $_->fullname } $kqn->read ]; is_deeply($hit, ["$tmpdir/new/tst"], 'rename(2) detected (via NOTE_EXTEND)') or diag explain($hit); open $fh, '>', "$tmpdir/tst"; close $fh; link("$tmpdir/tst", "$tmpdir/new/link"); my @read = map { $_->fullname } $kqn->read; $hit = [ grep(m!/link$!, @read) ]; is_deeply($hit, ["$tmpdir/new/link"], 'link(2) detected (via NOTE_WRITE)') or diag explain(\@read); { my $d = "$tmpdir/new/ANOTHER"; mkdir $d; $hit = [ map { $_->fullname } $kqn->read ]; is_xdeeply($hit, [ $d ], 'mkdir detected'); rmdir $d; # TODO: should we always watch for directory removals? } $w->cancel; link("$tmpdir/new/tst", "$tmpdir/new/link2"); $hit = [ map { $_->fullname } $kqn->read ]; is_deeply($hit, [], 'link(2) not detected after cancel'); # rearm: my $GONE = PublicInbox::KQNotify::NOTE_DELETE() | PublicInbox::KQNotify::NOTE_REVOKE() | PublicInbox::KQNotify::NOTE_ATTRIB() | PublicInbox::KQNotify::NOTE_WRITE() | PublicInbox::KQNotify::NOTE_RENAME(); $w = $kqn->watch("$tmpdir/new", $mask|$GONE); my @unlink = sort glob("$tmpdir/new/*"); unlink(@unlink); $hit = [ sort(map { $_->fullname } $kqn->read) ]; is_xdeeply($hit, \@unlink, 'unlinked files match'); # this is unreliable on Dragonfly tmpfs (fixed post-6.4) rmdir "$tmpdir/new"; $hit = [ sort(map { $_->fullname } $kqn->read) ]; is(scalar(@$hit), 1, 'detected self removal') or check_broken_tmpfs; done_testing;