Chromium Code Reviews| Index: utils/pub/pubspec.dart |
| diff --git a/utils/pub/pubspec.dart b/utils/pub/pubspec.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a9c46974b5688d3fdede9b950cfdcb454c45a77e |
| --- /dev/null |
| +++ b/utils/pub/pubspec.dart |
| @@ -0,0 +1,122 @@ |
| +// Copyright (c) 2012, 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. |
| + |
| +#library('pub_pubspec'); |
| + |
| +#import('io.dart'); |
| +#import('pub.dart'); |
| +#import('utils.dart'); |
| +#import('version.dart'); |
| +#import('yaml/yaml.dart'); |
| + |
| +/** |
| + * The parsed and validated contents of a pubspec file. |
| + */ |
| +class Pubspec { |
| + /** |
| + * Parses the pubspec at the given path. |
| + */ |
| + static Future<Pubspec> parse(String path, SourceRegistry sources) { |
| + var version = Version.none; |
| + var dependencies = <PackageRef>[]; |
| + var completer = new Completer<Pubspec>(); |
| + complete() => completer.complete(new Pubspec(version, dependencies)); |
| + |
| + // TODO(rnystrom): Handle the directory not existing. |
| + // TODO(rnystrom): Error-handling. |
| + var readFuture = readTextFile(path); |
| + readFuture.handleException((error) { |
| + // If there is no pubspec, we implicitly treat that as a package with no |
| + // dependencies. |
| + // TODO(rnystrom): Distinguish file not found from other real errors. |
| + complete(); |
| + return true; |
| + }); |
| + |
| + readFuture.then((pubspec) { |
| + if (pubspec.trim() == '') { |
| + complete(); |
| + return; |
| + } |
| + |
| + var parsedPubspec = loadYaml(pubspec); |
| + if (parsedPubspec is! Map) { |
| + completer.completeException('The pubspec must be a YAML mapping.'); |
| + } |
| + |
| + if (parsedPubspec.containsKey('version')) { |
| + version = new Version.parse(parsedPubspec['version']); |
| + } |
| + |
| + if (!parsedPubspec.containsKey('dependencies')) { |
| + complete(); |
| + return; |
| + } |
| + |
| + var dependencyEntries = parsedPubspec['dependencies']; |
| + if (dependencyEntries is! Map || |
| + dependencyEntries.getKeys().some((e) => e is! String)) { |
| + completer.completeException( |
| + 'The pubspec dependencies must be a map of package names.'); |
| + } |
| + |
| + dependencyEntries.forEach((name, spec) { |
| + var description, source; |
| + // TODO(nweiz): parse the version once we have version handling |
|
nweiz
2012/05/18 00:08:24
You can remove this now
Bob Nystrom
2012/05/18 20:02:38
Done.
|
| + if (spec == null || spec is String) { |
|
nweiz
2012/05/18 00:08:24
If spec is a string, you should parse it as a vers
Bob Nystrom
2012/05/18 20:02:38
Done.
|
| + description = name; |
| + source = sources.defaultSource; |
| + } else if (spec is Map) { |
| + if (spec.containsKey('version')) { |
| + // TODO(rnystrom): Support parsing version constraints like |
| + // ">= 2.0.0 < 3.1.3". |
| + version = new Version.parse(spec['version']); |
|
nweiz
2012/05/18 00:08:24
Replace spec['version'] here with spec.remove('ver
Bob Nystrom
2012/05/18 20:02:38
Done.
|
| + spec.remove('version'); |
| + } |
| + |
| + var sourceNames = spec.getKeys(); |
| + if (sourceNames.length > 1) { |
| + completer.completeException( |
| + 'Dependency $name may not have multiple sources: ' |
| + '$sourceNames.'); |
| + return; |
| + } |
| + |
| + var sourceName = only(sourceNames); |
| + if (sourceName is! String) { |
| + completer.completeException( |
| + 'Source name $sourceName must be a string.'); |
| + return; |
| + } |
| + source = sources[sourceName]; |
| + description = spec[sourceName]; |
| + } else { |
| + completer.completeException( |
| + 'Dependency specification $spec must be a string or a mapping.'); |
| + return; |
| + } |
| + |
| + dependencies.add(new PackageRef( |
| + name, source, Version.none, description)); |
| + }); |
| + |
| + complete(); |
| + }); |
| + |
| + return completer.future; |
| + } |
| + |
| + /** |
| + * This package's version. Defaults to [Version.none] if not present in |
| + * the pubspec. |
|
nweiz
2012/05/18 00:08:24
I wouldn't document the default here when it only
Bob Nystrom
2012/05/18 20:02:38
Done.
|
| + */ |
| + final Version version; |
| + |
| + /** |
| + * The packages this package depends on. |
| + */ |
| + List<PackageRef> dependencies; |
| + |
| + Pubspec(this.version, this.dependencies); |
| +} |