| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #library('package'); | 5 #library('package'); |
| 6 | 6 |
| 7 #import('io.dart'); | 7 #import('io.dart'); |
| 8 #import('pubspec.dart'); | 8 #import('pubspec.dart'); |
| 9 #import('source.dart'); | 9 #import('source.dart'); |
| 10 #import('source_registry.dart'); | 10 #import('source_registry.dart'); |
| 11 #import('version.dart'); | 11 #import('version.dart'); |
| 12 | 12 |
| 13 /** | 13 /** |
| 14 * A named, versioned, unit of code and resource reuse. | 14 * A named, versioned, unit of code and resource reuse. |
| 15 */ | 15 */ |
| 16 class Package { | 16 class Package { |
| 17 /** | 17 /** |
| 18 * Loads the package whose root directory is [packageDir]. | 18 * Loads the package whose root directory is [packageDir]. [name] is the |
| 19 * expected name of that package (e.g. the name given in the dependency), or |
| 20 * null if the package being loaded is the entrypoint package. |
| 19 */ | 21 */ |
| 20 static Future<Package> load(String packageDir, SourceRegistry sources) { | 22 static Future<Package> load(String name, String packageDir, |
| 23 SourceRegistry sources) { |
| 21 var pubspecPath = join(packageDir, 'pubspec.yaml'); | 24 var pubspecPath = join(packageDir, 'pubspec.yaml'); |
| 22 | 25 |
| 23 return fileExists(pubspecPath).chain((exists) { | 26 return fileExists(pubspecPath).chain((exists) { |
| 24 if (exists) { | 27 if (!exists) throw new PubspecNotFoundException(name); |
| 25 return readTextFile(pubspecPath).transform((contents) { | 28 return readTextFile(pubspecPath); |
| 26 return new Pubspec.parse(contents, sources); | 29 }).transform((contents) { |
| 27 }); | 30 var pubspec = new Pubspec.parse(contents, sources); |
| 28 } else { | 31 if (pubspec.name == null) throw new PubspecHasNoNameException(name); |
| 29 // If there is no pubspec, we implicitly treat that as a package with | 32 if (name != null && pubspec.name != name) { |
| 30 // no dependencies. | 33 throw new PubspecNameMismatchException(name, pubspec.name); |
| 31 return new Future.immediate(new Pubspec.empty()); | |
| 32 } | 34 } |
| 33 }).transform((pubspec) { | |
| 34 return new Package._(packageDir, pubspec); | 35 return new Package._(packageDir, pubspec); |
| 35 }); | 36 }); |
| 36 } | 37 } |
| 37 | 38 |
| 38 /** | 39 /** |
| 39 * The path to the directory containing the package. | 40 * The path to the directory containing the package. |
| 40 */ | 41 */ |
| 41 final String dir; | 42 final String dir; |
| 42 | 43 |
| 43 /** | 44 /** |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 /** | 88 /** |
| 88 * An unambiguous resolved reference to a package. A package ID contains enough | 89 * An unambiguous resolved reference to a package. A package ID contains enough |
| 89 * information to correctly install the package. | 90 * information to correctly install the package. |
| 90 * | 91 * |
| 91 * Note that it's possible for multiple distinct package IDs to point to | 92 * Note that it's possible for multiple distinct package IDs to point to |
| 92 * different directories that happen to contain identical packages. For example, | 93 * different directories that happen to contain identical packages. For example, |
| 93 * the same package may be available from multiple sources. As far as Pub is | 94 * the same package may be available from multiple sources. As far as Pub is |
| 94 * concerned, those packages are different. | 95 * concerned, those packages are different. |
| 95 */ | 96 */ |
| 96 class PackageId implements Comparable, Hashable { | 97 class PackageId implements Comparable, Hashable { |
| 98 /// The name of the package being identified. |
| 99 final String name; |
| 100 |
| 97 /** | 101 /** |
| 98 * The [Source] used to look up this package given its [description]. | 102 * The [Source] used to look up this package given its [description]. |
| 99 */ | 103 */ |
| 100 final Source source; | 104 final Source source; |
| 101 | 105 |
| 102 /** | 106 /** |
| 103 * The package's version. | 107 * The package's version. |
| 104 */ | 108 */ |
| 105 final Version version; | 109 final Version version; |
| 106 | 110 |
| 107 /** | 111 /** |
| 108 * The metadata used by the package's [source] to identify and locate it. It | 112 * The metadata used by the package's [source] to identify and locate it. It |
| 109 * contains whatever [Source]-specific data it needs to be able to install | 113 * contains whatever [Source]-specific data it needs to be able to install |
| 110 * the package. For example, the description of a git sourced package might | 114 * the package. For example, the description of a git sourced package might |
| 111 * by the URL "git://github.com/dart/uilib.git". | 115 * by the URL "git://github.com/dart/uilib.git". |
| 112 */ | 116 */ |
| 113 final description; | 117 final description; |
| 114 | 118 |
| 115 PackageId(this.source, this.version, this.description); | 119 PackageId(this.name, this.source, this.version, this.description); |
| 116 | |
| 117 /** | |
| 118 * The name of the package being identified. This will be the human-friendly | |
| 119 * name like "uilib". | |
| 120 */ | |
| 121 String get name => source.packageName(description); | |
| 122 | 120 |
| 123 int hashCode() => name.hashCode() ^ | 121 int hashCode() => name.hashCode() ^ |
| 124 source.name.hashCode() ^ | 122 source.name.hashCode() ^ |
| 125 version.hashCode(); | 123 version.hashCode(); |
| 126 | 124 |
| 127 bool operator ==(other) { | 125 bool operator ==(other) { |
| 128 if (other is! PackageId) return false; | 126 if (other is! PackageId) return false; |
| 129 // TODO(rnystrom): We're assuming here the name/version/source tuple is | 127 // TODO(rnystrom): We're assuming here the name/version/source tuple is |
| 130 // enough to uniquely identify the package and that we don't need to delve | 128 // enough to uniquely identify the package and that we don't need to delve |
| 131 // into the description. | 129 // into the description. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 158 */ | 156 */ |
| 159 Future<PackageId> get resolved => source.resolveId(this); | 157 Future<PackageId> get resolved => source.resolveId(this); |
| 160 } | 158 } |
| 161 | 159 |
| 162 /** | 160 /** |
| 163 * A reference to a package. Unlike a [PackageId], a PackageRef may not | 161 * A reference to a package. Unlike a [PackageId], a PackageRef may not |
| 164 * unambiguously refer to a single package. It may describe a range of allowed | 162 * unambiguously refer to a single package. It may describe a range of allowed |
| 165 * packages. | 163 * packages. |
| 166 */ | 164 */ |
| 167 class PackageRef { | 165 class PackageRef { |
| 166 /// The name of the package being identified. |
| 167 final String name; |
| 168 |
| 168 /** | 169 /** |
| 169 * The [Source] used to look up the package. | 170 * The [Source] used to look up the package. |
| 170 */ | 171 */ |
| 171 final Source source; | 172 final Source source; |
| 172 | 173 |
| 173 /** | 174 /** |
| 174 * The allowed package versions. | 175 * The allowed package versions. |
| 175 */ | 176 */ |
| 176 final VersionConstraint constraint; | 177 final VersionConstraint constraint; |
| 177 | 178 |
| 178 /** | 179 /** |
| 179 * The metadata used to identify the package being referenced. The | 180 * The metadata used to identify the package being referenced. The |
| 180 * interpretation of this will vary based on the [source]. | 181 * interpretation of this will vary based on the [source]. |
| 181 */ | 182 */ |
| 182 final description; | 183 final description; |
| 183 | 184 |
| 184 /** | 185 PackageRef(this.name, this.source, this.constraint, this.description); |
| 185 * The name of the package being referenced. | |
| 186 */ | |
| 187 String get name => source.packageName(description); | |
| 188 | |
| 189 PackageRef(this.source, this.constraint, this.description); | |
| 190 | 186 |
| 191 String toString() => "$name $constraint from $source ($description)"; | 187 String toString() => "$name $constraint from $source ($description)"; |
| 192 | 188 |
| 193 /** | 189 /** |
| 194 * Returns a [PackageId] generated from this [PackageRef] with the given | 190 * Returns a [PackageId] generated from this [PackageRef] with the given |
| 195 * concrete version. | 191 * concrete version. |
| 196 */ | 192 */ |
| 197 PackageId atVersion(Version version) => | 193 PackageId atVersion(Version version) => |
| 198 new PackageId(source, version, description); | 194 new PackageId(name, source, version, description); |
| 199 } | 195 } |
| 196 |
| 197 class PubspecNotFoundException implements Exception { |
| 198 final String name; |
| 199 |
| 200 PubspecNotFoundException(this.name); |
| 201 |
| 202 String toString() => 'Package "$name" doesn\'t have a pubspec.yaml file.'; |
| 203 } |
| 204 |
| 205 class PubspecHasNoNameException implements Exception { |
| 206 final String name; |
| 207 |
| 208 PubspecHasNoNameException(this.name); |
| 209 |
| 210 String toString() => 'Package "$name"\'s pubspec.yaml file is missing the ' |
| 211 'required "name" field (e.g. "name: $name").'; |
| 212 } |
| 213 |
| 214 class PubspecNameMismatchException implements Exception { |
| 215 final String expectedName; |
| 216 final String actualName; |
| 217 |
| 218 PubspecNameMismatchException(this.expectedName, this.actualName); |
| 219 |
| 220 String toString() => 'The name you specified for your dependency, ' |
| 221 '"$expectedName", doesn\'t match the name "$actualName" in its pubspec.'; |
| 222 } |
| OLD | NEW |