use v6.d.PREVIEW;
class Ultramarine::Model::DirScanner {
has IO $.root is required;
submethod BUILD(IO() :$!root!) {}
class EndOfScan {}
method scan(--> Supply) {
my $ret = Supplier::Preserving.new;
my sub inner-scan(IO() $path) {
my @todo = $path;
while @todo {
my $next = @todo.pop;
$ret.emit($next);
next unless $next ~~ :d & :r & :x;
$next.watch().tap({ inner-scan($^event.path) });
for $next.dir(:CWD($next.CWD)) -> $child {
@todo.push($child);
}
CATCH {
when X::IO::Dir { }
}
}
}
(start {
inner-scan(IO::Path.new('.',:CWD($.root)));
$ret.emit(EndOfScan);
}).then(-> $p { $ret.quit($p.cause) if $p.status ~~ Broken });
CATCH { $ret.quit($_) };
return $ret.Supply;
}
}