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 pub.source.hosted; | 5 library pub.source.hosted; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io' as io; | 8 import 'dart:io' as io; |
9 import "dart:convert"; | 9 import "dart:convert"; |
10 | 10 |
11 import 'package:http/http.dart' as http; | 11 import 'package:http/http.dart' as http; |
12 import 'package:path/path.dart' as path; | 12 import 'package:path/path.dart' as path; |
13 import 'package:pub_semver/pub_semver.dart'; | 13 import 'package:pub_semver/pub_semver.dart'; |
14 | 14 |
15 import '../exceptions.dart'; | 15 import '../exceptions.dart'; |
16 import '../http.dart'; | 16 import '../http.dart'; |
17 import '../io.dart'; | 17 import '../io.dart'; |
18 import '../log.dart' as log; | 18 import '../log.dart' as log; |
19 import '../package.dart'; | 19 import '../package.dart'; |
20 import '../pubspec.dart'; | 20 import '../pubspec.dart'; |
21 import '../utils.dart'; | 21 import '../utils.dart'; |
22 import 'cached.dart'; | 22 import 'cached.dart'; |
23 | 23 |
24 /// A package source that gets packages from a package hosting site that uses | 24 /// A package source that gets packages from a package hosting site that uses |
25 /// the same API as pub.dartlang.org. | 25 /// the same API as pub.dartlang.org. |
26 class HostedSource extends CachedSource { | 26 class HostedSource extends CachedSource { |
| 27 /// Returns a reference to a hosted package named [name]. |
| 28 /// |
| 29 /// If [url] is passed, it's the URL of the pub server from which the package |
| 30 /// should be downloaded. It can be a [Uri] or a [String]. |
| 31 static PackageRef refFor(String name, {url}) => |
| 32 new PackageRef(name, 'hosted', _descriptionFor(name, url)); |
| 33 |
| 34 /// Returns an ID for a hosted package named [name] at [version]. |
| 35 /// |
| 36 /// If [url] is passed, it's the URL of the pub server from which the package |
| 37 /// should be downloaded. It can be a [Uri] or a [String]. |
| 38 static PackageId idFor(String name, Version version, {url}) => |
| 39 new PackageId(name, 'hosted', version, _descriptionFor(name, url)); |
| 40 |
| 41 /// Returns the description for a hosted package named [name] with the |
| 42 /// given package server [url]. |
| 43 static _descriptionFor(String name, [url]) { |
| 44 if (url == null) return name; |
| 45 |
| 46 if (url is! String && url is! Uri) { |
| 47 throw new ArgumentError.value(url, 'url', 'must be a Uri or a String.'); |
| 48 } |
| 49 |
| 50 return {'name': name, 'url': url.toString()}; |
| 51 } |
| 52 |
27 final name = "hosted"; | 53 final name = "hosted"; |
28 final hasMultipleVersions = true; | 54 final hasMultipleVersions = true; |
29 | 55 |
30 /// Gets the default URL for the package server for hosted dependencies. | 56 /// Gets the default URL for the package server for hosted dependencies. |
31 static String get defaultUrl { | 57 static String get defaultUrl { |
32 var url = io.Platform.environment["PUB_HOSTED_URL"]; | 58 var url = io.Platform.environment["PUB_HOSTED_URL"]; |
33 if (url != null) return url; | 59 if (url != null) return url; |
34 | 60 |
35 return "https://pub.dartlang.org"; | 61 return "https://pub.dartlang.org"; |
36 } | 62 } |
(...skipping 12 matching lines...) Expand all Loading... |
49 } catch (error, stackTrace) { | 75 } catch (error, stackTrace) { |
50 var parsed = _parseDescription(ref.description); | 76 var parsed = _parseDescription(ref.description); |
51 _throwFriendlyError(error, stackTrace, parsed.first, parsed.last); | 77 _throwFriendlyError(error, stackTrace, parsed.first, parsed.last); |
52 } | 78 } |
53 | 79 |
54 var doc = JSON.decode(body); | 80 var doc = JSON.decode(body); |
55 return doc['versions'].map((map) { | 81 return doc['versions'].map((map) { |
56 var pubspec = new Pubspec.fromMap( | 82 var pubspec = new Pubspec.fromMap( |
57 map['pubspec'], systemCache.sources, | 83 map['pubspec'], systemCache.sources, |
58 expectedName: ref.name, location: url); | 84 expectedName: ref.name, location: url); |
59 var id = ref.atVersion(pubspec.version); | 85 var id = idFor(ref.name, pubspec.version); |
60 memoizePubspec(id, pubspec); | 86 memoizePubspec(id, pubspec); |
61 | 87 |
62 return id; | 88 return id; |
63 }).toList(); | 89 }).toList(); |
64 } | 90 } |
65 | 91 |
66 /// Downloads and parses the pubspec for a specific version of a package that | 92 /// Downloads and parses the pubspec for a specific version of a package that |
67 /// is available from the site. | 93 /// is available from the site. |
68 Future<Pubspec> describeUncached(PackageId id) async { | 94 Future<Pubspec> describeUncached(PackageId id) async { |
69 // Request it from the server. | 95 // Request it from the server. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 String packageName(description) => _parseDescription(description).first; | 137 String packageName(description) => _parseDescription(description).first; |
112 | 138 |
113 bool descriptionsEqual(description1, description2) => | 139 bool descriptionsEqual(description1, description2) => |
114 _parseDescription(description1) == _parseDescription(description2); | 140 _parseDescription(description1) == _parseDescription(description2); |
115 | 141 |
116 /// Ensures that [description] is a valid hosted package description. | 142 /// Ensures that [description] is a valid hosted package description. |
117 /// | 143 /// |
118 /// There are two valid formats. A plain string refers to a package with the | 144 /// There are two valid formats. A plain string refers to a package with the |
119 /// given name from the default host, while a map with keys "name" and "url" | 145 /// given name from the default host, while a map with keys "name" and "url" |
120 /// refers to a package with the given name from the host at the given URL. | 146 /// refers to a package with the given name from the host at the given URL. |
121 dynamic parseDescription(String containingPath, description, | 147 PackageRef parseRef(String name, description, {String containingPath}) { |
122 {bool fromLockFile: false}) { | |
123 _parseDescription(description); | 148 _parseDescription(description); |
124 return description; | 149 return new PackageRef(name, this.name, description); |
| 150 } |
| 151 |
| 152 PackageId parseId(String name, Version version, description) { |
| 153 _parseDescription(description); |
| 154 return new PackageId(name, this.name, version, description); |
125 } | 155 } |
126 | 156 |
127 /// Re-downloads all packages that have been previously downloaded into the | 157 /// Re-downloads all packages that have been previously downloaded into the |
128 /// system cache from any server. | 158 /// system cache from any server. |
129 Future<Pair<List<PackageId>, List<PackageId>>> repairCachedPackages() async { | 159 Future<Pair<List<PackageId>, List<PackageId>>> repairCachedPackages() async { |
130 if (!dirExists(systemCacheRoot)) return new Pair([], []); | 160 if (!dirExists(systemCacheRoot)) return new Pair([], []); |
131 | 161 |
132 var successes = []; | 162 var successes = []; |
133 var failures = []; | 163 var failures = []; |
134 | 164 |
135 for (var serverDir in listDir(systemCacheRoot)) { | 165 for (var serverDir in listDir(systemCacheRoot)) { |
136 var url = _directoryToUrl(path.basename(serverDir)); | 166 var url = _directoryToUrl(path.basename(serverDir)); |
137 var packages = _getCachedPackagesInDirectory(path.basename(serverDir)); | 167 var packages = _getCachedPackagesInDirectory(path.basename(serverDir)); |
138 packages.sort(Package.orderByNameAndVersion); | 168 packages.sort(Package.orderByNameAndVersion); |
139 | 169 |
140 for (var package in packages) { | 170 for (var package in packages) { |
141 var id = new PackageId(package.name, this.name, package.version, null); | 171 var id = idFor(package.name, package.version); |
142 | 172 |
143 try { | 173 try { |
144 await _download(url, package.name, package.version, package.dir); | 174 await _download(url, package.name, package.version, package.dir); |
145 successes.add(id); | 175 successes.add(id); |
146 } catch (error, stackTrace) { | 176 } catch (error, stackTrace) { |
147 failures.add(id); | 177 failures.add(id); |
148 var message = "Failed to repair ${log.bold(package.name)} " | 178 var message = "Failed to repair ${log.bold(package.name)} " |
149 "${package.version}"; | 179 "${package.version}"; |
150 if (url != defaultUrl) message += " from $url"; | 180 if (url != defaultUrl) message += " from $url"; |
151 log.error("$message. Error:\n$error"); | 181 log.error("$message. Error:\n$error"); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 log.io("Finding versions of ${ref.name} in " | 264 log.io("Finding versions of ${ref.name} in " |
235 "$systemCacheRoot/${_urlToDirectory(server)}"); | 265 "$systemCacheRoot/${_urlToDirectory(server)}"); |
236 | 266 |
237 var dir = path.join(systemCacheRoot, _urlToDirectory(server)); | 267 var dir = path.join(systemCacheRoot, _urlToDirectory(server)); |
238 | 268 |
239 var versions; | 269 var versions; |
240 if (dirExists(dir)) { | 270 if (dirExists(dir)) { |
241 versions = await listDir(dir).map((entry) { | 271 versions = await listDir(dir).map((entry) { |
242 var components = path.basename(entry).split("-"); | 272 var components = path.basename(entry).split("-"); |
243 if (components.first != ref.name) return null; | 273 if (components.first != ref.name) return null; |
244 return ref.atVersion(new Version.parse(components.last)); | 274 return HostedSource.idFor(ref.name, new Version.parse(components.last)); |
245 }).where((id) => id != null).toList(); | 275 }).where((id) => id != null).toList(); |
246 } else { | 276 } else { |
247 versions = []; | 277 versions = []; |
248 } | 278 } |
249 | 279 |
250 // If there are no versions in the cache, report a clearer error. | 280 // If there are no versions in the cache, report a clearer error. |
251 if (versions.isEmpty) { | 281 if (versions.isEmpty) { |
252 throw new PackageNotFoundException( | 282 throw new PackageNotFoundException( |
253 "Could not find package ${ref.name} in cache."); | 283 "Could not find package ${ref.name} in cache."); |
254 } | 284 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 var name = description["name"]; | 389 var name = description["name"]; |
360 if (name is! String) { | 390 if (name is! String) { |
361 throw new FormatException("The 'name' key must have a string value."); | 391 throw new FormatException("The 'name' key must have a string value."); |
362 } | 392 } |
363 | 393 |
364 var url = description["url"]; | 394 var url = description["url"]; |
365 if (url == null) url = HostedSource.defaultUrl; | 395 if (url == null) url = HostedSource.defaultUrl; |
366 | 396 |
367 return new Pair<String, String>(name, url); | 397 return new Pair<String, String>(name, url); |
368 } | 398 } |
OLD | NEW |