// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:io';

import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';

import '../command.dart';
import '../command_runner.dart';
import '../exceptions.dart';
import '../git.dart';
import '../io.dart';
import '../log.dart' as log;
import '../package_name.dart';
import '../pubspec.dart';
import '../pubspec_utils.dart';
import '../sdk.dart';
import '../solver.dart';
import '../source/git.dart';
import '../source/hosted.dart';
import '../source/path.dart';
import '../source/root.dart';
import '../utils.dart';

/// Handles the `add` pub command. Adds a dependency to `pubspec.yaml` and gets
/// the package. The user may pass in a git constraint, host url, or path as
/// requirements. If no such options are passed in, this command will do a
/// resolution to find the latest version of the package that is compatible with
/// the other dependencies in `pubspec.yaml`, and then enter that as the lower
/// bound in a ^x.y.z constraint.
///
/// The descriptor used to be given with args like --path, --sdk,
/// --git-<option>.
///
/// We still support these arguments, but now the documented way to give the
/// descriptor is to give a yaml-descriptor as in pubspec.yaml.
class AddCommand extends PubCommand {
  @override
  String get name => 'add';
  @override
  String get description => '''
Add dependencies to `pubspec.yaml`.

Invoking `dart pub add foo bar` will add `foo` and `bar` to `pubspec.yaml`
with a default constraint derived from latest compatible version.

Add to dev_dependencies by prefixing with "dev:".

Make dependency overrides by prefixing with "override:".

Add packages with specific constraints or other sources by giving a descriptor
after a colon.

For example (follow the same format including spaces):
  * Add a hosted dependency at newest compatible stable version:
    `$topLevelProgram pub add foo`
  * Add a hosted dev dependency at newest compatible stable version:
    `$topLevelProgram pub add dev:foo`
  * Add a hosted dependency with the given constraint
    `$topLevelProgram pub add foo:^1.2.3`
  * Add multiple dependencies:
    `$topLevelProgram pub add foo dev:bar`
  * Add a dependency override:
    `$topLevelProgram pub add override:foo:1.0.0`
  * Add a path dependency:
    `$topLevelProgram pub add "foo:{path: ../foo}"`
  * Add a hosted dependency:
    `$topLevelProgram pub add "foo:{hosted: https://my-pub.dev}"`
  * Add an sdk dependency:
    `$topLevelProgram pub add "foo:{sdk: flutter}"`
  * Add a git dependency:
    `$topLevelProgram pub add "foo:{git: https://github.com/foo/foo}"`
  * Add a git dependency with a path and ref specified:
    `$topLevelProgram pub add \\
      "foo:{git:{url: ../foo.git, ref: <branch>, path: <subdir>}}"`''';

  @override
  String get argumentsDescription =>
      '[options] [<section>:]<package>[:descriptor] '
      '[<section>:]<package2>[:descriptor] ...]';

  @override
  String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-add';
  @override
  bool get isOffline => argResults.flag('offline');

  AddCommand() {
    argParser.addFlag(
      'dev',
      abbr: 'd',
      negatable: false,
      help: 'Adds to the development dependencies instead.',
      hide: true,
    );

    // Following options are hidden/deprecated in favor of the new syntax:
    // [dev:]<package>[:descriptor] ...
    //
    // To avoid breaking changes we keep supporting them, but hide them from
    // --help to discourage further use. Combining these with new syntax will
    // fail.
    argParser.addOption('git-url', help: 'Git URL of the package', hide: true);
    argParser.addOption(
      'git-ref',
      help: 'Git branch or commit to be retrieved',
      hide: true,
    );
    argParser.addOption(
      'git-path',
      help: 'Path of git package in repository',
      hide: true,
    );
    argParser.addOption(
      'git-tag-pattern',
      help: 'The tag-pattern to search for versions in repository',
      hide: true,
    );
    argParser.addOption(
      'hosted-url',
      help: 'URL of package host server',
      hide: true,
    );
    argParser.addOption(
      'path',
      help: 'Add package from local path',
      hide: true,
    );
    argParser.addOption(
      'sdk',
      help: 'add package from SDK source',
      allowed: ['flutter'],
      valueHelp: '[flutter]',
      hide: true,
    );

    argParser.addFlag(
      'offline',
      help: 'Use cached packages instead of accessing the network.',
    );

    argParser.addFlag(
      'dry-run',
      abbr: 'n',
      negatable: false,
      help: "Report what dependencies would change but don't change any.",
    );

    argParser.addFlag(
      'precompile',
      help: 'Build executables in immediate dependencies.',
    );
    argParser.addOption(
      'directory',
      abbr: 'C',
      help: 'Run this in the directory <dir>.',
      valueHelp: 'dir',
    );
    argParser.addFlag(
      'example',
      defaultsTo: true,
      help:
          'Also update dependencies in `example/` after modifying pubspec.yaml in the root package (if it exists).',
    );
  }

  @override
  Future<void> runProtected() async {
    if (argResults.rest.length > 1) {
      if (argResults.gitUrl != null) {
        usageException('''
--git-url cannot be used with multiple packages.
Specify multiple git packages with descriptors.''');
      } else if (argResults.path != null) {
        usageException('''
--path cannot be used with multiple packages.
Specify multiple path packages with descriptors.''');
      } else if (argResults.sdk != null) {
        usageException('''
--sdk cannot be used with multiple packages.
Specify multiple sdk packages with descriptors.''');
      }
    }
    if (argResults.rest.isEmpty) {
      usageException('Must specify at least one package to be added.');
    }

    final updates =
        argResults.rest.map((p) => _parsePackage(p, argResults)).toList();

    /// Compute a pubspec that will depend on all the given packages, but the
    /// actual constraint will only be determined after a resolution decides the
    /// best version.
    var resolutionPubspec = entrypoint.workPackage.pubspec;
    for (final update in updates) {
      /// Perform version resolution in-memory.
      resolutionPubspec = await _addPackageToPubspec(resolutionPubspec, update);
    }

    final SolveResult solveResult;

    try {
      /// Use [SolveType.UPGRADE] to solve for the highest version of [package]
      /// in case [package] was already a transitive dependency. In the case
      /// where the user specifies a version constraint, this serves to ensure
      /// that a resolution exists before we update pubspec.yaml.
      // TODO(sigurdm): We should really use a spinner here.
      solveResult = await resolveVersions(
        SolveType.upgrade,
        cache,
        entrypoint.withWorkPubspec(resolutionPubspec).workspaceRoot,
      );
    } on GitException {
      final name = updates.first.ref.name;
      dataError(
        'Unable to resolve package "$name" with the given '
        'git parameters.',
      );
    } on SolveFailure catch (e) {
      dataError(e.message);
    } on WrappedException catch (e) {
      /// [WrappedException]s may appear if an invalid [hostUrl] is passed in.
      dataError(e.message);
    }

    /// Verify the results for each package.
    for (final update in updates) {
      final ref = update.ref;
      final name = ref.name;
      final resultPackage = solveResult.packages.firstWhere(
        (packageId) => packageId.name == name,
      );

      /// Assert that [resultPackage] is within the original user's
      /// expectations.
      final constraint = update.constraint;
      if (constraint != null && !constraint.allows(resultPackage.version)) {
        final dependencyOverrides = resolutionPubspec.dependencyOverrides;
        if (dependencyOverrides.isNotEmpty) {
          dataError(
            '"$name" resolved to "${resultPackage.version}" which '
            'does not satisfy constraint "$constraint". This could be '
            'caused by "dependency_overrides".',
          );
        }
      }
    }
    final newPubspecText = _updatePubspec(solveResult.packages, updates);
    if (!argResults.isDryRun) {
      /// Update the `pubspec.yaml` before calling [acquireDependencies] to
      /// ensure that the modification timestamp on `pubspec.lock` and
      /// `.dart_tool/package_config.json` is newer than `pubspec.yaml`,
      /// ensuring that [entrypoint.assertUptoDate] will pass.
      writeTextFile(entrypoint.workPackage.pubspecPath, newPubspecText);
    }

    String? overridesFileContents;
    final overridesPath = entrypoint.workPackage.pubspecOverridesPath;
    try {
      overridesFileContents = readTextFile(overridesPath);
    } on IOException {
      overridesFileContents = null;
    }

    /// Even if it is a dry run, run `acquireDependencies` so that the user
    /// gets a report on the other packages that might change version due
    /// to this new dependency.
    await entrypoint
        .withWorkPubspec(
          Pubspec.parse(
            newPubspecText,
            cache.sources,
            location: Uri.parse(entrypoint.workPackage.pubspecPath),
            overridesFileContents: overridesFileContents,
            overridesLocation: Uri.file(overridesPath),
            containingDescription: ResolvedRootDescription.fromDir(
              entrypoint.workPackage.dir,
            ),
          ),
        )
        .acquireDependencies(
          SolveType.get,
          dryRun: argResults.isDryRun,
          precompile: !argResults.isDryRun && argResults.shouldPrecompile,
        );

    if (!argResults.isDryRun && argResults.example) {
      for (final example in entrypoint.examples) {
        await example.acquireDependencies(
          SolveType.get,
          precompile: argResults.shouldPrecompile,
          summaryOnly: true,
        );
      }
    }

    if (isOffline) {
      log.warning(
        'Warning: Packages added when offline may not resolve to '
        'the latest compatible version available.',
      );
    }
  }

  /// Creates a new in-memory [Pubspec] by adding [package] to the
  /// dependencies of [original].
  Future<Pubspec> _addPackageToPubspec(
    Pubspec original,
    _ParseResult package,
  ) async {
    final name = package.ref.name;
    final dependencies = [...original.dependencies.values];
    final devDependencies = [...original.devDependencies.values];
    final dependencyOverrides = [...original.dependencyOverrides.values];

    final dependencyNames = dependencies.map((dependency) => dependency.name);
    final devDependencyNames = devDependencies.map(
      (devDependency) => devDependency.name,
    );
    final range = package.ref.withConstraint(
      package.constraint ?? VersionConstraint.any,
    );

    if (package.isOverride) {
      dependencyOverrides.add(range);
    } else if (package.isDev) {
      if (devDependencyNames.contains(name)) {
        log.message(
          '"$name" is already in "dev_dependencies". '
          'Will try to update the constraint.',
        );
        devDependencies.removeWhere((element) => element.name == name);
      }

      /// If package is originally in dependencies and we wish to add it to
      /// dev_dependencies, this is a redundant change, and we should not
      /// remove the package from dependencies, since it might cause the user's
      /// code to break.
      if (dependencyNames.contains(name)) {
        dataError(
          '"$name" is already in "dependencies". '
          'Use "pub remove $name" to remove it before adding it '
          'to "dev_dependencies"',
        );
      }

      devDependencies.add(range);
    } else {
      if (dependencyNames.contains(name)) {
        log.message(
          '"$name" is already in "dependencies". '
          'Will try to update the constraint.',
        );
        dependencies.removeWhere((element) => element.name == name);
      }

      /// If package is originally in dev_dependencies and we wish to add it to
      /// dependencies, we remove the package from dev_dependencies, since it is
      /// now redundant.
      if (devDependencyNames.contains(name)) {
        log.message(
          '"$name" was found in dev_dependencies. '
          'Removing "$name" and adding it to dependencies instead.',
        );
        devDependencies.removeWhere((element) => element.name == name);
      }

      dependencies.add(range);
    }

    return original.copyWith(
      dependencies: dependencies,
      devDependencies: devDependencies,
      dependencyOverrides: dependencyOverrides,
    );
  }

  static final _argRegExp = RegExp(
    r'^(?:(?<prefix>dev|override):)?'
    r'(?<name>[a-zA-Z0-9_.]+)'
    r'(?::(?<descriptor>.*))?$',
  );

  static final _lenientArgRegExp = RegExp(
    r'^(?:(?<prefix>[^:]*):)?'
    r'(?<name>[^:]*)'
    r'(?::(?<descriptor>.*))?$',
  );

  /// Split [arg] on ':' and interpret it with the flags in [argResults] either
  /// as an old-style or a new-style descriptor to produce a PackageRef].
  _ParseResult _parsePackage(String arg, ArgResults argResults) {
    var isDev = argResults.flag('dev');
    var isOverride = false;

    final match = _argRegExp.firstMatch(arg);
    if (match == null) {
      final match2 = _lenientArgRegExp.firstMatch(arg);
      if (match2 == null) {
        usageException('Could not parse $arg');
      } else {
        if (match2.namedGroup('prefix') != null &&
            match2.namedGroup('descriptor') != null) {
          usageException(
            'The only allowed prefixes are "dev:" and "override:"',
          );
        } else {
          final packageName =
              match2.namedGroup('descriptor') == null
                  ? match2.namedGroup('prefix')
                  : match2.namedGroup('name');
          usageException('Not a valid package name: "$packageName"');
        }
      }
    } else if (match.namedGroup('prefix') == 'dev') {
      if (argResults.isDev) {
        usageException("Cannot combine 'dev:' with --dev");
      }
      isDev = true;
    } else if (match.namedGroup('prefix') == 'override') {
      if (argResults.isDev) {
        usageException("Cannot combine 'override:' with --dev");
      }
      isOverride = true;
    }
    final packageName = match.namedGroup('name')!;
    if (!packageNameRegExp.hasMatch(packageName)) {
      usageException('Not a valid package name: "$packageName"');
    }
    final descriptor = match.namedGroup('descriptor');

    if (isOverride && descriptor == null) {
      usageException('A dependency override needs an explicit descriptor.');
    }
    final _PartialParseResult partial;
    if (argResults.hasOldStyleOptions) {
      partial = _parseDescriptorOldStyleArgs(
        packageName,
        descriptor,
        argResults,
      );
    } else {
      partial = _parseDescriptorNewStyle(packageName, descriptor);
    }

    return _ParseResult(
      partial.ref,
      partial.constraint,
      isDev: isDev,
      isOverride: isOverride,
    );
  }

  /// Parse [descriptor] to return the corresponding [_ParseResult] using the
  /// arguments given in [argResults] to configure the description.
  ///
  /// [descriptor] should be a constraint as parsed by
  /// [VersionConstraint.parse]. If it fails to parse as a version constraint
  /// but could parse with [_parseDescriptorNewStyle()] a specific usage
  /// description is issued.
  ///
  /// Examples:
  ///
  /// ```none
  /// retry
  /// retry:2.0.0
  /// retry:^2.0.0
  /// retry:'>=2.0.0'
  /// retry:'>2.0.0 <3.0.1'
  /// 'retry:>2.0.0 <3.0.1'
  /// retry:any
  /// ```
  ///
  /// If a version constraint is provided when the `--path` or any of the
  /// `--git-<option>` options are used, a [UsageException] will be thrown.
  ///
  /// Packages must either be a git, hosted, sdk, or path package. Mixing of
  /// options is not allowed and will cause a [UsageException] to be thrown.
  ///
  /// If any of the other git options are defined when `--git-url` is not
  /// defined, an error will be thrown.
  ///
  /// The returned [_PartialParseResult] will always have `ref!=null`.
  _PartialParseResult _parseDescriptorOldStyleArgs(
    String packageName,
    String? descriptor,
    ArgResults argResults,
  ) {
    final conflictingFlagSets = [
      ['git-url', 'git-ref', 'git-path'],
      ['hosted-url'],
      ['path'],
      ['sdk'],
    ];

    for (final flag in conflictingFlagSets
        .expand((s) => s)
        .where(argResults.wasParsed)) {
      final conflictingFlag = conflictingFlagSets
          .where((s) => !s.contains(flag))
          .expand((s) => s)
          .firstWhereOrNull(argResults.wasParsed);
      if (conflictingFlag != null) {
        usageException(
          'Packages can only have one source, "pub add" flags "--$flag" and '
          '"--$conflictingFlag" are conflicting.',
        );
      }
    }

    /// We want to allow for [constraint] to take on a `null` value here to
    /// preserve the fact that the user did not specify a constraint.
    VersionConstraint? constraint;
    try {
      constraint =
          descriptor == null ? null : VersionConstraint.parse(descriptor);
    } on FormatException catch (e) {
      var couldParseAsNewStyle = true;
      try {
        _parseDescriptorNewStyle(packageName, descriptor);
        // If parsing the descriptor as a new-style descriptor succeeds we
        // can give this more specific error message.
      } catch (_) {
        couldParseAsNewStyle = false;
      }
      if (couldParseAsNewStyle) {
        usageException(
          '--dev, --path, --sdk, --git-url, --git-path and --git-ref '
          'cannot be combined with a descriptor.',
        );
      } else {
        usageException('Invalid version constraint: ${e.message}');
      }
    }

    /// The package to be added.
    final PackageRef ref;
    final path = argResults.path;
    if (argResults.hasGitOptions) {
      final gitUrl = argResults.gitUrl;
      if (gitUrl == null) {
        usageException('The `--git-url` is required for git dependencies.');
      }
      if (argResults.gitRef != null && argResults.tagPattern != null) {
        usageException(
          'Cannot provide both `--git-ref` and `--git-tag-pattern`.',
        );
      }

      /// Process the git options to return the simplest representation to be
      /// added to the pubspec.
      try {
        ref = PackageRef(
          packageName,
          GitDescription(
            url: gitUrl.toString(),
            containingDir: p.current,
            ref: argResults.gitRef,
            path: argResults.gitPath,
            tagPattern: argResults.tagPattern,
          ),
        );
      } on FormatException catch (e) {
        usageException('The --git-url must be a valid url: ${e.message}.');
      }
    } else if (path != null) {
      ref = PackageRef(
        packageName,
        PathDescription(p.absolute(path), p.isRelative(path)),
      );
    } else if (argResults.sdk != null) {
      ref = cache.sdk.parseRef(
        packageName,
        argResults.sdk,
        containingDescription: ResolvedRootDescription.fromDir(p.current),
      );
    } else {
      ref = PackageRef(
        packageName,
        HostedDescription(
          packageName,
          argResults.hostedUrl ?? cache.hosted.defaultUrl,
        ),
      );
    }
    return _PartialParseResult(ref, constraint);
  }

  /// Parse [packageName] to return the corresponding [_ParseResult].
  ///
  /// [packageName] must be written in the format
  /// `<package-name>[:descriptor>]`, where quotations should be used if
  /// necessary.
  ///
  /// `descriptor` is what you would put in a pubspec.yaml in the dependencies
  /// section.
  ///
  /// Assumes that none of '--git-url', '--git-ref', '--git-path', '--path' and
  /// '--sdk' are present in [argResults].
  ///
  ///
  /// Examples:
  ///
  /// ```none
  /// retry
  /// retry:2.0.0
  /// dev:retry:^2.0.0
  /// retry:'>=2.0.0'
  /// retry:'>2.0.0 <3.0.1'
  /// 'retry:>2.0.0 <3.0.1'
  /// retry:any
  /// 'retry:{"path":"../foo"}'
  /// 'retry:{"git":{"url":"../foo","ref":"branchname"},"version":"^1.2.3"}'
  /// 'retry:{"sdk":"flutter"}'
  /// 'retry:{"hosted":"mypub.dev"}'
  /// ```
  ///
  /// The `--path`, `--sdk`, and `--git-<option>` arguments can't be
  /// combined with a non-string descriptor.
  ///
  /// If a version constraint is provided when the `--path` or any of the
  /// `--git-<option>` options are used, a [UsageException] will be thrown.
  ///
  /// Packages must either be a git, hosted, sdk, or path package. Mixing of
  /// options is not allowed and will cause a [UsageException] to be thrown.
  ///
  /// If any of the other git options are defined when `--git-url` is not
  /// defined, an error will be thrown.
  ///
  /// Returns a `ref` of `null` if the descriptor did not specify a source. Then
  /// the source will be determined by the old-style arguments.
  _PartialParseResult _parseDescriptorNewStyle(
    String packageName,
    String? descriptor,
  ) {
    /// We want to allow for [constraint] to take on a `null` value here to
    /// preserve the fact that the user did not specify a constraint.
    VersionConstraint? constraint;

    /// The package to be added.
    PackageRef? ref;

    if (descriptor != null) {
      try {
        // An unquoted version constraint is not always valid yaml.
        // But we want to allow it here anyways.
        constraint = VersionConstraint.parse(descriptor);
      } on FormatException {
        final parsedDescriptor = loadYaml(descriptor);
        // Use the pubspec parsing mechanism for parsing the descriptor.
        final Pubspec dummyPubspec;
        try {
          dummyPubspec = Pubspec.fromMap(
            {
              'dependencies': {packageName: parsedDescriptor},
              'environment': {'sdk': sdk.version.toString()},
            },
            cache.sources,
            // Resolve relative paths relative to current, not where the
            // pubspec.yaml is.
            containingDescription: ResolvedRootDescription.fromDir(p.current),
          );
        } on FormatException catch (e) {
          usageException('Failed parsing package specification: ${e.message}');
        }
        final range = dummyPubspec.dependencies[packageName]!;
        if (parsedDescriptor is String) {
          // Ref will be constructed by the default behavior below.
          ref = null;
        } else {
          ref = range.toRef();
        }
        final hasExplicitConstraint =
            parsedDescriptor is String ||
            (parsedDescriptor is Map &&
                parsedDescriptor.containsKey('version'));
        // If the descriptor has an explicit constraint, use that. Otherwise we
        // infer it.
        if (hasExplicitConstraint) {
          constraint = range.constraint;
        }
      }
    }
    return _PartialParseResult(
      ref ??
          PackageRef(
            packageName,
            HostedDescription(
              packageName,
              argResults.hostedUrl ?? cache.hosted.defaultUrl,
            ),
          ),
      constraint,
    );
  }

  /// Calculates the updates to the pubspec file.
  String _updatePubspec(
    List<PackageId> resultPackages,
    List<_ParseResult> updates,
  ) {
    final yamlEditor = YamlEditor(
      readTextFile(entrypoint.workPackage.pubspecPath),
    );
    log.io('Reading ${entrypoint.workPackage.pubspecPath}.');
    log.fine('Contents:\n$yamlEditor');

    for (final update in updates) {
      final dependencyKey =
          update.isDev
              ? 'dev_dependencies'
              : (update.isOverride ? 'dependency_overrides' : 'dependencies');
      final constraint = update.constraint;
      final ref = update.ref;
      final name = ref.name;
      final resultId = resultPackages.firstWhere((id) => id.name == name);

      final description = pubspecDescription(
        ref.withConstraint(
          constraint ??
              (ref.description.hasMultipleVersions
                  ? VersionConstraint.compatibleWith(resultId.version)
                  : VersionConstraint.any),
        ),
        cache,
        entrypoint.workPackage,
      );

      if (yamlEditor.parseAt([
            dependencyKey,
          ], orElse: () => YamlScalar.wrap(null)).value ==
          null) {
        // Handle the case where [dependencyKey] does not already exist.
        // We ensure it is in Block-style by default.
        yamlEditor.update(
          [dependencyKey],
          wrapAsYamlNode({
            name: description,
          }, collectionStyle: CollectionStyle.BLOCK),
        );
      } else {
        final packagePath = [dependencyKey, name];

        yamlEditor.update(packagePath, description);
      }

      /// Remove the package from dev_dependencies if we are adding it to
      /// dependencies. Refer to [_addPackageToPubspec] for additional
      /// discussion.
      if (!update.isDev && !update.isOverride) {
        final devDependenciesNode = yamlEditor.parseAt([
          'dev_dependencies',
        ], orElse: () => YamlScalar.wrap(null));

        if (devDependenciesNode is YamlMap &&
            devDependenciesNode.containsKey(name)) {
          if (devDependenciesNode.length == 1) {
            yamlEditor.remove(['dev_dependencies']);
          } else {
            yamlEditor.remove(['dev_dependencies', name]);
          }

          log.fine('Removed $name from "dev_dependencies".');
        }
      }
    }

    return yamlEditor.toString();
  }
}

class _PartialParseResult {
  final PackageRef ref;
  final VersionConstraint? constraint;
  _PartialParseResult(this.ref, this.constraint);
}

class _ParseResult {
  final PackageRef ref;
  final VersionConstraint? constraint;
  final bool isDev;
  final bool isOverride;
  _ParseResult(
    this.ref,
    this.constraint, {
    required this.isDev,
    required this.isOverride,
  });
}

extension on ArgResults {
  bool get isDev => flag('dev');
  bool get isDryRun => flag('dry-run');
  String? get gitUrl => this['git-url'] as String?;
  String? get gitPath => this['git-path'] as String?;
  String? get tagPattern => this['git-tag-pattern'] as String?;

  String? get gitRef => this['git-ref'] as String?;
  String? get hostedUrl => this['hosted-url'] as String?;
  String? get path => this['path'] as String?;
  String? get sdk => this['sdk'] as String?;
  bool get hasOldStyleOptions =>
      hasGitOptions ||
      path != null ||
      sdk != null ||
      hostedUrl != null ||
      isDev;
  bool get shouldPrecompile => flag('precompile');
  bool get example => flag('example');
  bool get hasGitOptions => gitUrl != null || gitRef != null || gitPath != null;
}
