getDependencyGraph method

Future<Map<String, Set<String>>> getDependencyGraph()

Builds a dependency graph of dependencies and their dependents in this workspace.

Implementation

Future<Map<String, Set<String>>> getDependencyGraph() async {
  final pubExecArgs = utils.pubCommandExecArgs(
    useFlutter: isFlutterWorkspace,
    workspace: this,
  );
  final pubDepsExecArgs = ['--style=list', '--dev'];
  final pubListCommandOutput = await Process.run(
    pubExecArgs.removeAt(0),
    [
      ...pubDepsExecArgs,
      'deps',
      if (isFlutterWorkspace) '--',
      ...pubDepsExecArgs,
    ],
    runInShell: true,
    workingDirectory: melosToolPath,
    stdoutEncoding: utf8,
    stderrEncoding: utf8,
  );

  final pubDepList =
      PubDependencyList.parse(pubListCommandOutput.stdout as String);
  final allEntries = pubDepList.allEntries;
  final allEntriesMap = allEntries.map((entry, map) {
    return MapEntry(entry.name, map);
  });

  void addNestedEntries(Set<String> entriesSet) {
    final countBefore = entriesSet.length;
    final entriesSetClone = Set<String>.from(entriesSet);
    for (final entryName in entriesSetClone) {
      final depsForEntry = allEntriesMap[entryName];
      if (depsForEntry != null && depsForEntry.isNotEmpty) {
        depsForEntry.forEach((dependentName, _) {
          entriesSet.add(dependentName);
        });
      }
    }
    // We check if the set has grown since we may need gather nested entries
    // from newly discovered dependencies.
    if (countBefore != entriesSet.length) {
      addNestedEntries(entriesSet);
    }
  }

  final dependencyGraphFlat = <String, Set<String>>{};

  allEntries.forEach((entry, dependencies) {
    final entriesSet = <String>{};
    if (dependencies.isNotEmpty) {
      dependencies.forEach((dependentName, _) {
        entriesSet.add(dependentName);
      });
    }
    addNestedEntries(entriesSet);
    dependencyGraphFlat[entry.name] = entriesSet;
  });

  return dependencyGraphFlat;
}