Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Side by Side Diff: sdk/lib/_internal/pub/lib/src/hosted_source.dart

Issue 14680005: Add offline support to pub install and update. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Revise. Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 hosted_source; 5 library hosted_source;
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:json' as json; 9 import 'dart:json' as json;
10 import 'dart:uri'; 10 import 'dart:uri';
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 }); 91 });
92 }); 92 });
93 } 93 }
94 94
95 /// The system cache directory for the hosted source contains subdirectories 95 /// The system cache directory for the hosted source contains subdirectories
96 /// for each separate repository URL that's used on the system. Each of these 96 /// for each separate repository URL that's used on the system. Each of these
97 /// subdirectories then contains a subdirectory for each package installed 97 /// subdirectories then contains a subdirectory for each package installed
98 /// from that site. 98 /// from that site.
99 Future<String> systemCacheDirectory(PackageId id) { 99 Future<String> systemCacheDirectory(PackageId id) {
100 var parsed = _parseDescription(id.description); 100 var parsed = _parseDescription(id.description);
101 var url = _getSourceDirectory(parsed.last); 101 var dir = _getSourceDirectory(parsed.last);
102 var urlDir = replace(url, new RegExp(r'[<>:"\\/|?*%]'), (match) {
103 return '%${match[0].codeUnitAt(0)}';
104 });
105 102
106 return new Future.value( 103 return new Future.value(
107 path.join(systemCacheRoot, urlDir, "${parsed.first}-${id.version}")); 104 path.join(systemCacheRoot, dir, "${parsed.first}-${id.version}"));
108 } 105 }
109 106
110 String packageName(description) => _parseDescription(description).first; 107 String packageName(description) => _parseDescription(description).first;
111 108
112 bool descriptionsEqual(description1, description2) => 109 bool descriptionsEqual(description1, description2) =>
113 _parseDescription(description1) == _parseDescription(description2); 110 _parseDescription(description1) == _parseDescription(description2);
114 111
115 /// Ensures that [description] is a valid hosted package description. 112 /// Ensures that [description] is a valid hosted package description.
116 /// 113 ///
117 /// There are two valid formats. A plain string refers to a package with the 114 /// There are two valid formats. A plain string refers to a package with the
118 /// given name from the default host, while a map with keys "name" and "url" 115 /// given name from the default host, while a map with keys "name" and "url"
119 /// refers to a package with the given name from the host at the given URL. 116 /// refers to a package with the given name from the host at the given URL.
120 dynamic parseDescription(String containingPath, description, 117 dynamic parseDescription(String containingPath, description,
121 {bool fromLockFile: false}) { 118 {bool fromLockFile: false}) {
122 _parseDescription(description); 119 _parseDescription(description);
123 return description; 120 return description;
124 } 121 }
125 122
126 List<Package> getCachedPackages() { 123 List<Package> getCachedPackages([String url]) {
124 if (url == null) url = _defaultUrl;
125
127 var cacheDir = path.join(systemCacheRoot, 126 var cacheDir = path.join(systemCacheRoot,
128 _getSourceDirectory(_defaultUrl)); 127 _getSourceDirectory(url));
129 if (!dirExists(cacheDir)) return []; 128 if (!dirExists(cacheDir)) return [];
130 129
131 return listDir(path.join(cacheDir)).map((entry) { 130 return listDir(path.join(cacheDir)).map((entry) {
132 // TODO(keertip): instead of catching exception in pubspec parse with 131 // TODO(keertip): instead of catching exception in pubspec parse with
133 // sdk dependency, fix to parse and report usage of sdk dependency. 132 // sdk dependency, fix to parse and report usage of sdk dependency.
134 // dartbug.com/10190 133 // dartbug.com/10190
135 try { 134 try {
136 return new Package.load(null, entry, systemCache.sources); 135 return new Package.load(null, entry, systemCache.sources);
137 } on ArgumentError catch (e) { 136 } on ArgumentError catch (e) {
138 log.error(e); 137 log.error(e);
139 } 138 }
140 }).where((package) => package != null).toList(); 139 }).where((package) => package != null).toList();
141 } 140 }
142 141
143 /// When an error occurs trying to read something about [package] from [url], 142 /// When an error occurs trying to read something about [package] from [url],
144 /// this tries to translate into a more user friendly error message. Always 143 /// this tries to translate into a more user friendly error message. Always
145 /// throws an error, either the original one or a better one. 144 /// throws an error, either the original one or a better one.
146 void _throwFriendlyError(error, package, url) { 145 void _throwFriendlyError(error, package, url) {
147 if (error is PubHttpException && 146 if (error is PubHttpException &&
148 error.response.statusCode == 404) { 147 error.response.statusCode == 404) {
149 fail('Could not find package "$package" at $url.'); 148 fail('Could not find package "$package" at $url.');
150 } 149 }
151 150
152 if (error is TimeoutException) { 151 if (error is TimeoutException) {
153 fail('Timed out trying to find package "$package" at $url.'); 152 fail('Timed out trying to find package "$package" at $url.');
154 } 153 }
155 154
156 if (error is io.SocketIOException) { 155 if (error is io.SocketIOException) {
157 fail('Got socket error trying to find package "$package" at $url.\n' 156 fail('Got socket error trying to find package "$package" at $url.\n'
158 '${error.osError}'); 157 '${error.osError}');
159 } 158 }
160 159
161 // Otherwise re-throw the original exception. 160 // Otherwise re-throw the original exception.
162 throw error; 161 throw error;
163 } 162 }
163 }
164 164
165 /// This is the modified hosted source used when pub install or update are run
166 /// with "--offline". This uses the system cache to get the list of available
167 /// packages and does no network access.
168 class OfflineHostedSource extends HostedSource {
169 /// Gets the list of all versions of [name] that are in the system cache.
170 Future<List<Version>> getVersions(String name, description) {
171 return new Future(() {
172 var parsed = _parseDescription(description);
173 var server = parsed.last;
174 log.io("Finding versions of $name in "
175 "${systemCache.rootDir}/${_getSourceDirectory(server)}");
176 return getCachedPackages(server)
177 .where((package) => package.name == name)
178 .map((package) => package.version)
179 .toList();
180 }).then((versions) {
181 // If there are no versions in the cache, report a clearer error.
182 if (versions.isEmpty) fail('Could not find package "$name" in cache.');
183
184 return versions;
185 });
186 }
187
188 Future<bool> install(PackageId id, String destPath) {
189 // Since HostedSource returns `true` for [shouldCache], install will only
190 // be called for uncached packages.
191 throw new UnsupportedError("Cannot install packages when offline.");
192 }
193
194 Future<Pubspec> describe(PackageId id) {
195 // [getVersions()] will only return packages that are already cached.
196 // SystemCache should only call [describe()] on a package after it has
197 // failed to find it in the cache, so this code should not be reached.
198 throw new UnsupportedError("Cannot describe packages when offline.");
199 }
165 } 200 }
166 201
167 /// The URL of the default package repository. 202 /// The URL of the default package repository.
168 final _defaultUrl = "https://pub.dartlang.org"; 203 final _defaultUrl = "https://pub.dartlang.org";
169 204
170 String _getSourceDirectory(String url) { 205 String _getSourceDirectory(String url) {
171 return url.replaceAll(new RegExp(r"^https?://"), ""); 206 url = url.replaceAll(new RegExp(r"^https?://"), "");
207 return replace(url, new RegExp(r'[<>:"\\/|?*%]'),
208 (match) => '%${match[0].codeUnitAt(0)}');
172 } 209 }
173 210
174 /// Parses [description] into its server and package name components, then 211 /// Parses [description] into its server and package name components, then
175 /// converts that to a Uri given [pattern]. Ensures the package name is 212 /// converts that to a Uri given [pattern]. Ensures the package name is
176 /// properly URL encoded. 213 /// properly URL encoded.
177 Uri _makeUrl(description, String pattern(String server, String package)) { 214 Uri _makeUrl(description, String pattern(String server, String package)) {
178 var parsed = _parseDescription(description); 215 var parsed = _parseDescription(description);
179 var server = parsed.last; 216 var server = parsed.last;
180 var package = encodeUriComponent(parsed.first); 217 var package = encodeUriComponent(parsed.first);
181 return new Uri(pattern(server, package)); 218 return new Uri(pattern(server, package));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 } 250 }
214 251
215 var name = description["name"]; 252 var name = description["name"];
216 if (name is! String) { 253 if (name is! String) {
217 throw new FormatException("The 'name' key must have a string value."); 254 throw new FormatException("The 'name' key must have a string value.");
218 } 255 }
219 256
220 var url = description.containsKey("url") ? description["url"] : _defaultUrl; 257 var url = description.containsKey("url") ? description["url"] : _defaultUrl;
221 return new Pair<String, String>(name, url); 258 return new Pair<String, String>(name, url);
222 } 259 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/pub/lib/src/command_uploader.dart ('k') | sdk/lib/_internal/pub/lib/src/system_cache.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698