findChanges method

Stream<FileChange> findChanges(
  1. FileCollection fileCollection, {
  2. String key = '',
})

Find all changes if a FileCollection has been modified since the last time someone checked with this method.

The key argument is used to consider whether changes have happened since last time the check was made with the exact same key.

Returns an empty Stream if the FileCollection is empty.

Implementation

Stream<FileChange> findChanges(FileCollection fileCollection,
    {String key = ''}) async* {
  logger.finest(
      () => 'Checking if $fileCollection with key="$key" has changed');
  if (fileCollection.isEmpty) return;

  // if the cache is empty, avoid checking anything and report everything as added
  if (await isEmptyDir(_hashesDir)) {
    logger.fine('No hashes in the cache '
        '(${path.join(Directory.current.path, _hashesDir)}), '
        'reporting all as changed');
    yield* _reportAllAdded(fileCollection);
    return;
  }

  Set<String> visitedEntities = {};

  // visit all entities that currently exist
  await for (final entity in fileCollection.resolve()) {
    if (visitedEntities.add(entity.path)) {
      final changes = await entity.use((file) async* {
        final change = await _hasFileChanged(file, key: key);
        if (change != null) yield FileChange(file, change);
      }, (dir, children) async* {
        final dirChange = await _hasDirChanged(dir, children, key: key);
        if (dirChange != null && dirChange.kind == ChangeKind.modified) {
          // file additions/modifications are reported elsehwere,
          // but only here can we find deleted files.
          yield* _deletedFiles(
              dirChange.newContents!, dirChange.oldContents!);
        }
        if (dirChange != null) {
          yield FileChange(dir, dirChange.kind);
        }
      });
      yield* changes;
    }
  }

  // visit entities that do not exist but may have existed before
  for (final file in fileCollection.files.where(visitedEntities.add)) {
    final fileEntity = File(file);
    final change = await _hasFileChanged(fileEntity, key: key);
    if (change != null) {
      yield FileChange(fileEntity, change);
    }
  }
  for (final dir in fileCollection.directories
      .map((e) => e.path)
      .where(visitedEntities.add)) {
    // this dir doesn't exist, otherwise it would've been visited earlier
    final dirEntity = Directory(dir);
    final change = await _hasDirChanged(dirEntity, const [], key: key);
    if (change != null) {
      yield FileChange(dirEntity, change.kind);
    }
  }
}