← Back to index

lib/BDD/Behave/Watch/Watcher.rakumod

38 / 41 lines covered (92.7%)

1unit module BDD::Behave::Watch::Watcher;23our class Snapshot {4  has Instant $.mtime is required;5  has Int     $.size  is required;6}78our class Change {9  has IO::Path $.path is required;10  has Str      $.kind is required;11}1213our class Watcher {14  has IO::Path @.paths;15  has Mu       $.match = / [ '.rakumod' | '.raku' | '.rakutest' | '.pm6' ] $ /;16  has %!snapshots;17  has Bool     $!initialized = False;1819  method add-path(IO::Path $path) {20    @!paths.push: $path;21    $!initialized = False;22    self;23  }2425  method scan-files(--> Seq) {26    gather for @!paths -> $root {27      next unless $root.e;28      if $root.f {29        take $root;30      } elsif $root.d {31        self!walk-dir($root);32      }33    }34  }3536  method !walk-dir(IO::Path $dir) {37    for $dir.dir -> $entry {38      next if $entry.basename eq '.precomp' | '.git';39      if $entry.f {40        take $entry if !$.match.defined || $entry.basename ~~ $.match;41      } elsif $entry.d {42        self!walk-dir($entry);43      }44    }45  }4647  method !current-snapshots(--> Hash) {48    my %snap;49    for self.scan-files() -> $file {50      next unless $file.e;51      my $key = $file.absolute;52      %snap{$key} = Snapshot.new(53        :mtime($file.modified),54        :size($file.s),55      );56    }57    %snap;58  }5960  method initialize() {61    %!snapshots  = self!current-snapshots();62    $!initialized = True;63    self;64  }6566  method poll(--> List) {67    self.initialize unless $!initialized;68    my %current = self!current-snapshots();69    my @changes;7071    for %current.kv -> $path, $snap {72      my $prev = %!snapshots{$path};73      if !$prev.defined {74        @changes.push: Change.new(:path($path.IO), :kind('added'));75      } elsif $prev.mtime != $snap.mtime || $prev.size != $snap.size {76        @changes.push: Change.new(:path($path.IO), :kind('modified'));77      }78    }7980    for %!snapshots.keys -> $path {81      next if %current{$path}:exists;82      @changes.push: Change.new(:path($path.IO), :kind('removed'));83    }8485    %!snapshots = %current;86    @changes.List;87  }8889  method tracked-count(--> Int) {90    %!snapshots.elems;91  }92}