scloudFileFinder<T> function

FileFinder<T> scloudFileFinder<T>({
  1. required String fileBaseName,
  2. required List<String> supportedExtensions,
  3. String? startingDirectory(
    1. T arg
    )?,
  4. int searchLevelsDown = 2,
  5. FileContentCondition? fileContentCondition,
})

Returns a FileFinder function that implements the algorithm for finding scloud project files.

If startingDirectory is not provided or it returns null, the current directory is used as starting directory.

If fileContentCondition is provided, it is called with the path of each file found. If it returns false, the file is not considered a match.

The file is searched for in this order:

  1. The starting directory and N levels down.
  2. If there is a pubspec.yaml file in the starting directory, go one level up and search again with depth 1.

If multiple matching files are found then an AmbiguousSearchException is thrown.

If a single matching file is found then its absolute path is returned, otherwise null.

Implementation

FileFinder<T> scloudFileFinder<T>({
  required final String fileBaseName,
  required final List<String> supportedExtensions,
  final String? Function(T arg)? startingDirectory,
  final int searchLevelsDown = 2,
  final FileContentCondition? fileContentCondition,
}) {
  final filenames =
      supportedExtensions.map((final ext) => '$fileBaseName.$ext').toList();

  return (final T arg) {
    // search in current directory and N levels down
    // If several are found, throw StateError
    final startDir = p.absolute(
      p.normalize(
        startingDirectory?.call(arg) ?? Directory.current.path,
      ),
    );
    final foundFile = _findUnambiguousFile(
      startDir,
      filenames,
      subDirLevels: searchLevelsDown,
      fileContentCondition: fileContentCondition,
    );
    if (foundFile != null) {
      return foundFile;
    }

    // if there is a pubspec.yaml file in the current directory,
    // and the current directory is not a root directory,
    // go one level up and search again with depth 1,
    // this covers the case where the current directory is client/ or flutter/
    final pubspecFile = File(p.join(startDir, 'pubspec.yaml'));
    if (pubspecFile.existsSync() && startDir != p.rootPrefix(startDir)) {
      final upDir = Directory(p.normalize(p.join(startDir, '..')));
      final foundFile = _findUnambiguousFile(
        upDir.path,
        filenames,
        subDirLevels: 1,
        fileContentCondition: fileContentCondition,
      );
      if (foundFile != null) {
        return foundFile;
      }
    }

    return null;
  };
}