resolveConfig function

ConfigResult resolveConfig({
  1. required String packageName,
  2. required String packageRoot,
  3. required String? packageConfig,
  4. required PubspecReader readPubspec,
  5. required void log(
    1. String message
    ),
  6. void addDependency(
    1. Uri uri
    ) = _ignoreDependency,
})

Implementation

ConfigResult resolveConfig({
  required String packageName,
  required String packageRoot,
  required String? packageConfig,
  required PubspecReader readPubspec,
  required void Function(String message) log,
  void Function(Uri uri) addDependency = _ignoreDependency,
}) {
  final normalizedPackageRoot = p.normalize(packageRoot);
  var workspaceRootDetected = false;
  if (packageConfig != null) {
    // packageConfig is a file:/// URI pointing to .dart_tool/package_config.json
    final packageConfigUri = Uri.parse(packageConfig);
    final packageConfigPath = p.normalize(File.fromUri(packageConfigUri).path);
    final configRoot = p.dirname(p.dirname(packageConfigPath));
    final rootPubspec = File(p.join(configRoot, 'pubspec.yaml'));
    addDependency(packageConfigUri);
    final rootPubspecData = rootPubspec.existsSync()
        ? _readTrackedPubspec(rootPubspec, readPubspec, addDependency)
        : null;
    workspaceRootDetected = rootPubspecData?.isWorkspace ?? false;
    final packageGraph = _readPackageGraph(
      packageConfigUri.resolve('package_graph.json'),
      log,
      addDependency,
    );

    // 1. Prefer configuration from the package-config/workspace root.
    if (rootPubspecData?.config != null) {
      log('Using configuration from ${rootPubspec.path}');
      return ConfigResult(
        rootPubspecData!.config,
        configRoot,
        source: 'legacy ffmpeg_kit_extended_config',
      );
    }

    // 2. If the root has no configuration, inspect package roots contained
    // in it. Only a workspace root depending on this package may supply the
    // configuration.
    final candidates = <_ConfigCandidate>[];
    for (final package in _readPackageEntries(packageConfigUri, log)) {
      if (package.name == packageName ||
          p.equals(package.root, normalizedPackageRoot)) {
        continue;
      }
      if (!_isWithin(configRoot, package.root)) continue;

      final packagePubspec = File(p.join(package.root, 'pubspec.yaml'));
      if (!packagePubspec.existsSync()) continue;
      final pubspec = _readTrackedPubspec(
        packagePubspec,
        readPubspec,
        addDependency,
      );
      if (pubspec?.config != null) {
        candidates.add(
          _ConfigCandidate(
            packageName: package.name,
            pubspec: packagePubspec,
            config: pubspec!.config,
          ),
        );
      }
    }

    final dependentRootNames = packageGraph?.dependentRootNames(packageName);
    final dependentCandidates = packageGraph == null
        ? candidates
        : candidates
              .where(
                (candidate) =>
                    dependentRootNames!.contains(candidate.packageName),
              )
              .toList();

    if (workspaceRootDetected &&
        dependentRootNames != null &&
        dependentRootNames.length > 1 &&
        dependentCandidates.isNotEmpty) {
      final paths = dependentCandidates
          .map(
            (candidate) =>
                '${candidate.packageName}: ${candidate.pubspec.path}',
          )
          .join('; ');
      final message =
          'Ambiguous FFmpegKit configuration: multiple workspace roots depend '
          'on $packageName, so the hook cannot identify which '
          'package-specific configuration applies. Place a shared '
          'configuration in ${rootPubspec.path} or configure only one '
          'workspace root (${dependentRootNames.join(', ')}): $paths';
      log('Error: $message');
      throw ConfigResolutionException(message);
    }

    if (dependentCandidates.length > 1) {
      final paths = dependentCandidates
          .map(
            (candidate) =>
                '${candidate.packageName}: ${candidate.pubspec.path}',
          )
          .join('; ');
      final message =
          'Ambiguous FFmpegKit configuration: multiple in-workspace packages '
          'define ffmpeg_kit_extended_config. Remove all but one configuration '
          'or place a shared configuration in ${rootPubspec.path}: $paths';
      log('Error: $message');
      throw ConfigResolutionException(message);
    }

    if (packageGraph == null && candidates.isNotEmpty) {
      final message =
          'Unable to determine which package may provide '
          'ffmpeg_kit_extended_config because .dart_tool/package_graph.json '
          'is unavailable. Run `flutter pub get` to rebuild package metadata, '
          'or define a shared configuration in ${rootPubspec.path}.';
      log('Error: $message');
      throw ConfigResolutionException(message);
    }

    if (dependentCandidates.length == 1) {
      final candidate = dependentCandidates.single;
      log(
        'Using dependent in-workspace package configuration from '
        '${candidate.pubspec.path}',
      );
      return ConfigResult(
        candidate.config,
        p.dirname(candidate.pubspec.path),
        source: 'legacy ffmpeg_kit_extended_config',
      );
    }

    if (candidates.isNotEmpty && packageGraph != null) {
      log(
        'Ignoring configured workspace packages that are not package-graph '
        'roots depending on $packageName. Using the default configuration.',
      );
    }

    if (rootPubspecData != null) {
      if (workspaceRootDetected) {
        if (candidates.isNotEmpty && packageGraph != null) {
          log(
            'Warning: Dart Pub Workspace detected at $configRoot, but no '
            'dependent in-workspace package defines '
            'ffmpeg_kit_extended_config for $packageName. Falling back to '
            'the default "base" '
            'LGPL small build.',
          );
        } else {
          log(
            'Warning: Dart Pub Workspace detected at $configRoot, but no '
            'unique in-workspace package defines ffmpeg_kit_extended_config. '
            'Place one configuration in an in-workspace package or in '
            '${rootPubspec.path}. Falling back to the default "base" LGPL '
            'small build.',
          );
        }
      } else {
        log(
          'Found configuration-root pubspec at ${rootPubspec.path} but no '
          'ffmpeg_kit_extended_config',
        );
      }
    }
  }

  // Preserve the package-local fallback for callers without package metadata.
  // With package_config.json available, the package itself is deliberately
  // excluded from workspace candidates and must not be selected implicitly.
  if (packageConfig == null) {
    final packagePubspec = File(p.join(normalizedPackageRoot, 'pubspec.yaml'));
    if (packagePubspec.existsSync()) {
      final pubspec = _readTrackedPubspec(
        packagePubspec,
        readPubspec,
        addDependency,
      );
      if (pubspec?.config != null) {
        log('Using package-local configuration from ${packagePubspec.path}');
        return ConfigResult(
          pubspec!.config,
          normalizedPackageRoot,
          source: 'legacy ffmpeg_kit_extended_config',
        );
      }
    }
  }

  // Last resort: default configuration.
  if (!workspaceRootDetected) {
    log('No configuration found. Using default "base" LGPL small build.');
  }
  return ConfigResult(
    {'type': 'base', 'gpl': false, 'small': true},
    normalizedPackageRoot,
    source: 'defaults',
  );
}