recursivePubPath function

Future<List<String>> recursivePubPath(
  1. List<String> dirs, {
  2. List<String>? dependencies,
  3. bool? readConfig,
  4. FilterDartProjectOptions? filterDartProjectOptions,
})

if forceRecursive is true, we folder going deeper even if the current path is a dart project

if ignoreSdkConstraints is true, it lists the project even if not compatible.

if dependencies is specified, it will only list the project that contains such dependency, use either dependency like path, or 'direct:path', 'dev:path' or 'override:path'.

Hidden folders, build, deploy, node_modules and the test folder of a project are not scanned.

Returns the list of valid pub folder, including me

Implementation

Future<List<String>> recursivePubPath(
  List<String> dirs, {
  List<String>? dependencies,
  bool? readConfig,
  FilterDartProjectOptions? filterDartProjectOptions,
}) async {
  var pubDirs = await filterPubPath(
    dirs,
    dependencies: dependencies,
    readConfig: readConfig,
    filterDartProjectOptions: filterDartProjectOptions,
  );

  Future<List<String>> getSubDirs(String dir) async {
    if (!_isToBeIgnored(basename(dir))) {
      // devPrint('testing: $dir');
      final sub = <String>[];
      final futures = <Future>[];
      final isPubProject = isPubPackageRootSync(dir);
      await Directory(dir).list().listen((FileSystemEntity fse) {
        var subDir = fse.path;
        // Make sure it is not added even if it is a package root
        if (_isToBeIgnored(basename(subDir))) {
          return;
        }
        // Don't look for projects in the test folder of a project
        if (isPubProject && _isPubProjectTopDirToBeIgnored(subDir)) {
          return;
        }
        if (FileSystemEntity.isDirectorySync(subDir)) {
          // Also handle the case where the directory linked is a dart project
          futures.add(() async {
            // follow links
            var dir = subDir;

            var isLink = FileSystemEntity.isLinkSync(dir);
            if (isLink) {
              dir = _linkTargetSync(dir);
            }
            var subPubDirs = await filterPubPath(
              [dir],
              dependencies: dependencies,
              readConfig: readConfig,
              filterDartProjectOptions: filterDartProjectOptions,
            );
            sub.addAll(subPubDirs);
            sub.addAll(await getSubDirs(dir));
          }());
        }
      }).asFuture<void>();
      await Future.wait(futures);
      return sub;
    }
    return <String>[];
  }

  for (final dir in dirs) {
    if (FileSystemEntity.isDirectorySync(dir)) {
      pubDirs.addAll(await getSubDirs(dir));
    } else {
      throw ArgumentError('$dir not a directory');
    }
  }

  return removeDuplicates(pubDirs)..sort();
}