| 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 |