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

Side by Side Diff: lib/src/global_packages.dart

Issue 2044253003: Refactor Source and SourceRegistry. (Closed) Base URL: git@github.com:dart-lang/pub.git@master
Patch Set: Rename LiveSource to BoundSource. Created 4 years, 6 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
« no previous file with comments | « lib/src/entrypoint.dart ('k') | lib/src/lock_file.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 import 'dart:async'; 5 import 'dart:async';
6 import 'dart:io'; 6 import 'dart:io';
7 7
8 import 'package:path/path.dart' as p; 8 import 'package:path/path.dart' as p;
9 import 'package:barback/barback.dart'; 9 import 'package:barback/barback.dart';
10 import 'package:pub_semver/pub_semver.dart'; 10 import 'package:pub_semver/pub_semver.dart';
11 11
12 import 'barback/asset_environment.dart'; 12 import 'barback/asset_environment.dart';
13 import 'entrypoint.dart'; 13 import 'entrypoint.dart';
14 import 'exceptions.dart'; 14 import 'exceptions.dart';
15 import 'executable.dart' as exe; 15 import 'executable.dart' as exe;
16 import 'io.dart'; 16 import 'io.dart';
17 import 'lock_file.dart'; 17 import 'lock_file.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 'sdk.dart' as sdk; 21 import 'sdk.dart' as sdk;
22 import 'solver/version_solver.dart'; 22 import 'solver/version_solver.dart';
23 import 'source/cached.dart'; 23 import 'source/cached.dart';
24 import 'source/git.dart';
25 import 'source/hosted.dart';
26 import 'source/path.dart';
27 import 'system_cache.dart'; 24 import 'system_cache.dart';
28 import 'utils.dart'; 25 import 'utils.dart';
29 26
30 /// Maintains the set of packages that have been globally activated. 27 /// Maintains the set of packages that have been globally activated.
31 /// 28 ///
32 /// These have been hand-chosen by the user to make their executables in bin/ 29 /// These have been hand-chosen by the user to make their executables in bin/
33 /// available to the entire system. This lets them access them even when the 30 /// available to the entire system. This lets them access them even when the
34 /// current working directory is not inside another entrypoint package. 31 /// current working directory is not inside another entrypoint package.
35 /// 32 ///
36 /// Only one version of a given package name can be globally activated at a 33 /// Only one version of a given package name can be globally activated at a
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 /// 70 ///
74 /// [executables] is the names of the executables that should have binstubs. 71 /// [executables] is the names of the executables that should have binstubs.
75 /// If `null`, all executables in the package will get binstubs. If empty, no 72 /// If `null`, all executables in the package will get binstubs. If empty, no
76 /// binstubs will be created. 73 /// binstubs will be created.
77 /// 74 ///
78 /// if [overwriteBinStubs] is `true`, any binstubs that collide with 75 /// if [overwriteBinStubs] is `true`, any binstubs that collide with
79 /// existing binstubs in other packages will be overwritten by this one's. 76 /// existing binstubs in other packages will be overwritten by this one's.
80 /// Otherwise, the previous ones will be preserved. 77 /// Otherwise, the previous ones will be preserved.
81 Future activateGit(String repo, List<String> executables, 78 Future activateGit(String repo, List<String> executables,
82 {bool overwriteBinStubs}) async { 79 {bool overwriteBinStubs}) async {
83 var source = cache.sources["git"] as GitSource; 80 var name = await cache.git.getPackageNameFromRepo(repo);
84 var name = await source.getPackageNameFromRepo(repo);
85 // Call this just to log what the current active package is, if any. 81 // Call this just to log what the current active package is, if any.
86 _describeActive(name); 82 _describeActive(name);
87 83
88 // TODO(nweiz): Add some special handling for git repos that contain path 84 // TODO(nweiz): Add some special handling for git repos that contain path
89 // dependencies. Their executables shouldn't be cached, and there should 85 // dependencies. Their executables shouldn't be cached, and there should
90 // be a mechanism for redoing dependency resolution if a path pubspec has 86 // be a mechanism for redoing dependency resolution if a path pubspec has
91 // changed (see also issue 20499). 87 // changed (see also issue 20499).
92 await _installInCache( 88 await _installInCache(
93 GitSource.refFor(name, repo).withConstraint(VersionConstraint.any), 89 cache.git.source.refFor(name, repo)
90 .withConstraint(VersionConstraint.any),
94 executables, overwriteBinStubs: overwriteBinStubs); 91 executables, overwriteBinStubs: overwriteBinStubs);
95 } 92 }
96 93
97 /// Finds the latest version of the hosted package with [name] that matches 94 /// Finds the latest version of the hosted package with [name] that matches
98 /// [constraint] and makes it the active global version. 95 /// [constraint] and makes it the active global version.
99 /// 96 ///
100 /// [executables] is the names of the executables that should have binstubs. 97 /// [executables] is the names of the executables that should have binstubs.
101 /// If `null`, all executables in the package will get binstubs. If empty, no 98 /// If `null`, all executables in the package will get binstubs. If empty, no
102 /// binstubs will be created. 99 /// binstubs will be created.
103 /// 100 ///
104 /// if [overwriteBinStubs] is `true`, any binstubs that collide with 101 /// if [overwriteBinStubs] is `true`, any binstubs that collide with
105 /// existing binstubs in other packages will be overwritten by this one's. 102 /// existing binstubs in other packages will be overwritten by this one's.
106 /// Otherwise, the previous ones will be preserved. 103 /// Otherwise, the previous ones will be preserved.
107 Future activateHosted(String name, VersionConstraint constraint, 104 Future activateHosted(String name, VersionConstraint constraint,
108 List<String> executables, {bool overwriteBinStubs}) async { 105 List<String> executables, {bool overwriteBinStubs}) async {
109 _describeActive(name); 106 _describeActive(name);
110 await _installInCache(HostedSource.refFor(name).withConstraint(constraint), 107 await _installInCache(
111 executables, overwriteBinStubs: overwriteBinStubs); 108 cache.hosted.source.refFor(name).withConstraint(constraint),
109 executables,
110 overwriteBinStubs: overwriteBinStubs);
112 } 111 }
113 112
114 /// Makes the local package at [path] globally active. 113 /// Makes the local package at [path] globally active.
115 /// 114 ///
116 /// [executables] is the names of the executables that should have binstubs. 115 /// [executables] is the names of the executables that should have binstubs.
117 /// If `null`, all executables in the package will get binstubs. If empty, no 116 /// If `null`, all executables in the package will get binstubs. If empty, no
118 /// binstubs will be created. 117 /// binstubs will be created.
119 /// 118 ///
120 /// if [overwriteBinStubs] is `true`, any binstubs that collide with 119 /// if [overwriteBinStubs] is `true`, any binstubs that collide with
121 /// existing binstubs in other packages will be overwritten by this one's. 120 /// existing binstubs in other packages will be overwritten by this one's.
122 /// Otherwise, the previous ones will be preserved. 121 /// Otherwise, the previous ones will be preserved.
123 Future activatePath(String path, List<String> executables, 122 Future activatePath(String path, List<String> executables,
124 {bool overwriteBinStubs}) async { 123 {bool overwriteBinStubs}) async {
125 var entrypoint = new Entrypoint(path, cache, isGlobal: true); 124 var entrypoint = new Entrypoint(path, cache, isGlobal: true);
126 125
127 // Get the package's dependencies. 126 // Get the package's dependencies.
128 await entrypoint.acquireDependencies(SolveType.GET); 127 await entrypoint.acquireDependencies(SolveType.GET);
129 var name = entrypoint.root.name; 128 var name = entrypoint.root.name;
130 129
131 // Call this just to log what the current active package is, if any. 130 // Call this just to log what the current active package is, if any.
132 _describeActive(name); 131 _describeActive(name);
133 132
134 // Write a lockfile that points to the local package. 133 // Write a lockfile that points to the local package.
135 var fullPath = canonicalize(entrypoint.root.dir); 134 var fullPath = canonicalize(entrypoint.root.dir);
136 var id = PathSource.idFor(name, entrypoint.root.version, fullPath); 135 var id = cache.path.source.idFor(name, entrypoint.root.version, fullPath);
137 136
138 // TODO(rnystrom): Look in "bin" and display list of binaries that 137 // TODO(rnystrom): Look in "bin" and display list of binaries that
139 // user can run. 138 // user can run.
140 _writeLockFile(name, new LockFile([id], cache.sources)); 139 _writeLockFile(name, new LockFile([id], cache.sources));
141 140
142 var binDir = p.join(_directory, name, 'bin'); 141 var binDir = p.join(_directory, name, 'bin');
143 if (dirExists(binDir)) deleteEntry(binDir); 142 if (dirExists(binDir)) deleteEntry(binDir);
144 143
145 _updateBinStubs(entrypoint.root, executables, 144 _updateBinStubs(entrypoint.root, executables,
146 overwriteBinStubs: overwriteBinStubs); 145 overwriteBinStubs: overwriteBinStubs);
147 } 146 }
148 147
149 /// Installs the package [dep] and its dependencies into the system cache. 148 /// Installs the package [dep] and its dependencies into the system cache.
150 Future _installInCache(PackageDep dep, List<String> executables, 149 Future _installInCache(PackageDep dep, List<String> executables,
151 {bool overwriteBinStubs}) async { 150 {bool overwriteBinStubs}) async {
152 // Create a dummy package with just [dep] so we can do resolution on it. 151 // Create a dummy package with just [dep] so we can do resolution on it.
153 var root = new Package.inMemory(new Pubspec("pub global activate", 152 var root = new Package.inMemory(new Pubspec("pub global activate",
154 dependencies: [dep], sources: cache.sources)); 153 dependencies: [dep], sources: cache.sources));
155 154
156 // Resolve it and download its dependencies. 155 // Resolve it and download its dependencies.
157 var result = await resolveVersions(SolveType.GET, cache.sources, root); 156 var result = await resolveVersions(SolveType.GET, cache, root);
158 if (!result.succeeded) { 157 if (!result.succeeded) {
159 // If the package specified by the user doesn't exist, we want to 158 // If the package specified by the user doesn't exist, we want to
160 // surface that as a [DataError] with the associated exit code. 159 // surface that as a [DataError] with the associated exit code.
161 if (result.error.package != dep.name) throw result.error; 160 if (result.error.package != dep.name) throw result.error;
162 if (result.error is NoVersionException) dataError(result.error.message); 161 if (result.error is NoVersionException) dataError(result.error.message);
163 throw result.error; 162 throw result.error;
164 } 163 }
165 result.showReport(SolveType.GET); 164 result.showReport(SolveType.GET);
166 165
167 // Make sure all of the dependencies are locally installed. 166 // Make sure all of the dependencies are locally installed.
168 await Future.wait(result.packages.map(_cacheDependency)); 167 await Future.wait(result.packages.map(_cacheDependency));
169 168
170 // Load the package graph from [result] so we don't need to re-parse all 169 // Load the package graph from [result] so we don't need to re-parse all
171 // the pubspecs. 170 // the pubspecs.
172 var entrypoint = new Entrypoint.fromSolveResult(root, cache, result, 171 var entrypoint = new Entrypoint.fromSolveResult(root, cache, result,
173 isGlobal: true); 172 isGlobal: true);
174 var snapshots = await _precompileExecutables(entrypoint, dep.name); 173 var snapshots = await _precompileExecutables(entrypoint, dep.name);
175 174
176 var lockFile = result.lockFile; 175 var lockFile = result.lockFile;
177 _writeLockFile(dep.name, lockFile); 176 _writeLockFile(dep.name, lockFile);
178 writeTextFile(_getPackagesFilePath(dep.name), lockFile.packagesFile()); 177 writeTextFile(_getPackagesFilePath(dep.name), lockFile.packagesFile(cache));
179 178
180 _updateBinStubs(entrypoint.packageGraph.packages[dep.name], executables, 179 _updateBinStubs(entrypoint.packageGraph.packages[dep.name], executables,
181 overwriteBinStubs: overwriteBinStubs, snapshots: snapshots); 180 overwriteBinStubs: overwriteBinStubs, snapshots: snapshots);
182 } 181 }
183 182
184 /// Precompiles the executables for [package] and saves them in the global 183 /// Precompiles the executables for [package] and saves them in the global
185 /// cache. 184 /// cache.
186 /// 185 ///
187 /// Returns a map from executable name to path for the snapshots that were 186 /// Returns a map from executable name to path for the snapshots that were
188 /// successfully precompiled. 187 /// successfully precompiled.
(...skipping 12 matching lines...) Expand all
201 }); 200 });
202 201
203 return environment.precompileExecutables(package, binDir); 202 return environment.precompileExecutables(package, binDir);
204 }); 203 });
205 } 204 }
206 205
207 /// Downloads [id] into the system cache if it's a cached package. 206 /// Downloads [id] into the system cache if it's a cached package.
208 Future _cacheDependency(PackageId id) async { 207 Future _cacheDependency(PackageId id) async {
209 if (id.isRoot) return; 208 if (id.isRoot) return;
210 209
211 var source = cache.sources[id.source]; 210 var source = cache.source(id.source);
212 if (source is! CachedSource) return; 211 if (source is! CachedSource) return;
213 212
214 await source.downloadToSystemCache(id); 213 await source.downloadToSystemCache(id);
215 } 214 }
216 215
217 /// Finishes activating package [package] by saving [lockFile] in the cache. 216 /// Finishes activating package [package] by saving [lockFile] in the cache.
218 void _writeLockFile(String package, LockFile lockFile) { 217 void _writeLockFile(String package, LockFile lockFile) {
219 ensureDir(p.join(_directory, package)); 218 ensureDir(p.join(_directory, package));
220 219
221 // TODO(nweiz): This cleans up Dart 1.6's old lockfile location. Remove it 220 // TODO(nweiz): This cleans up Dart 1.6's old lockfile location. Remove it
222 // when Dart 1.6 is old enough that we don't think anyone will have these 221 // when Dart 1.6 is old enough that we don't think anyone will have these
223 // lockfiles anymore (issue 20703). 222 // lockfiles anymore (issue 20703).
224 var oldPath = p.join(_directory, "$package.lock"); 223 var oldPath = p.join(_directory, "$package.lock");
225 if (fileExists(oldPath)) deleteEntry(oldPath); 224 if (fileExists(oldPath)) deleteEntry(oldPath);
226 225
227 writeTextFile(_getLockFilePath(package), lockFile.serialize(cache.rootDir)); 226 writeTextFile(_getLockFilePath(package), lockFile.serialize(cache.rootDir));
228 227
229 var id = lockFile.packages[package]; 228 var id = lockFile.packages[package];
230 log.message('Activated ${_formatPackage(id)}.'); 229 log.message('Activated ${_formatPackage(id)}.');
231 } 230 }
232 231
233 /// Shows the user the currently active package with [name], if any. 232 /// Shows the user the currently active package with [name], if any.
234 void _describeActive(String name) { 233 void _describeActive(String name) {
235 try { 234 try {
236 var lockFile = new LockFile.load(_getLockFilePath(name), cache.sources); 235 var lockFile = new LockFile.load(_getLockFilePath(name), cache.sources);
237 var id = lockFile.packages[name]; 236 var id = lockFile.packages[name];
238 237
239 if (id.source == 'git') { 238 if (id.source == 'git') {
240 var url = GitSource.urlFromDescription(id.description); 239 var url = cache.git.source.urlFromDescription(id.description);
241 log.message('Package ${log.bold(name)} is currently active from Git ' 240 log.message('Package ${log.bold(name)} is currently active from Git '
242 'repository "${url}".'); 241 'repository "${url}".');
243 } else if (id.source == 'path') { 242 } else if (id.source == 'path') {
244 var path = PathSource.pathFromDescription(id.description); 243 var path = cache.path.source.pathFromDescription(id.description);
245 log.message('Package ${log.bold(name)} is currently active at path ' 244 log.message('Package ${log.bold(name)} is currently active at path '
246 '"$path".'); 245 '"$path".');
247 } else { 246 } else {
248 log.message('Package ${log.bold(name)} is currently active at version ' 247 log.message('Package ${log.bold(name)} is currently active at version '
249 '${log.bold(id.version)}.'); 248 '${log.bold(id.version)}.');
250 } 249 }
251 } on IOException { 250 } on IOException {
252 // If we couldn't read the lock file, it's not activated. 251 // If we couldn't read the lock file, it's not activated.
253 return null; 252 return null;
254 } 253 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 ensureDir(p.dirname(lockFilePath)); 295 ensureDir(p.dirname(lockFilePath));
297 new File(oldLockFilePath).renameSync(lockFilePath); 296 new File(oldLockFilePath).renameSync(lockFilePath);
298 } 297 }
299 298
300 // Remove the package itself from the lockfile. We put it in there so we 299 // Remove the package itself from the lockfile. We put it in there so we
301 // could find and load the [Package] object, but normally an entrypoint 300 // could find and load the [Package] object, but normally an entrypoint
302 // doesn't expect to be in its own lockfile. 301 // doesn't expect to be in its own lockfile.
303 var id = lockFile.packages[name]; 302 var id = lockFile.packages[name];
304 lockFile = lockFile.removePackage(name); 303 lockFile = lockFile.removePackage(name);
305 304
306 var source = cache.sources[id.source]; 305 var source = cache.source(id.source);
307 var entrypoint; 306 var entrypoint;
308 if (source is CachedSource) { 307 if (source is CachedSource) {
309 // For cached sources, the package itself is in the cache and the 308 // For cached sources, the package itself is in the cache and the
310 // lockfile is the one we just loaded. 309 // lockfile is the one we just loaded.
311 entrypoint = new Entrypoint.inMemory( 310 entrypoint = new Entrypoint.inMemory(
312 cache.sources.load(id), lockFile, cache, isGlobal: true); 311 cache.load(id), lockFile, cache, isGlobal: true);
313 } else { 312 } else {
314 // For uncached sources (i.e. path), the ID just points to the real 313 // For uncached sources (i.e. path), the ID just points to the real
315 // directory for the package. 314 // directory for the package.
316 assert(id.source == "path"); 315 assert(id.source == "path");
317 entrypoint = new Entrypoint( 316 entrypoint = new Entrypoint(
318 PathSource.pathFromDescription(id.description), cache, 317 cache.path.source.pathFromDescription(id.description), cache,
319 isGlobal: true); 318 isGlobal: true);
320 } 319 }
321 320
322 if (entrypoint.root.pubspec.environment.sdkVersion.allows(sdk.version)) { 321 if (entrypoint.root.pubspec.environment.sdkVersion.allows(sdk.version)) {
323 return entrypoint; 322 return entrypoint;
324 } 323 }
325 324
326 dataError("${log.bold(name)} ${entrypoint.root.version} doesn't support " 325 dataError("${log.bold(name)} ${entrypoint.root.version} doesn't support "
327 "Dart ${sdk.version}."); 326 "Dart ${sdk.version}.");
328 } 327 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 throw new FormatException("Pubspec for activated package $name didn't " 400 throw new FormatException("Pubspec for activated package $name didn't "
402 "contain an entry for itself."); 401 "contain an entry for itself.");
403 } 402 }
404 403
405 return id; 404 return id;
406 } 405 }
407 406
408 /// Returns formatted string representing the package [id]. 407 /// Returns formatted string representing the package [id].
409 String _formatPackage(PackageId id) { 408 String _formatPackage(PackageId id) {
410 if (id.source == 'git') { 409 if (id.source == 'git') {
411 var url = GitSource.urlFromDescription(id.description); 410 var url = cache.sources.git.urlFromDescription(id.description);
412 return '${log.bold(id.name)} ${id.version} from Git repository "$url"'; 411 return '${log.bold(id.name)} ${id.version} from Git repository "$url"';
413 } else if (id.source == 'path') { 412 } else if (id.source == 'path') {
414 var path = PathSource.pathFromDescription(id.description); 413 var path = cache.sources.path.pathFromDescription(id.description);
415 return '${log.bold(id.name)} ${id.version} at path "$path"'; 414 return '${log.bold(id.name)} ${id.version} at path "$path"';
416 } else { 415 } else {
417 return '${log.bold(id.name)} ${id.version}'; 416 return '${log.bold(id.name)} ${id.version}';
418 } 417 }
419 } 418 }
420 419
421 /// Repairs any corrupted globally-activated packages and their binstubs. 420 /// Repairs any corrupted globally-activated packages and their binstubs.
422 /// 421 ///
423 /// Returns a pair of two lists of strings. The first indicates which packages 422 /// Returns a pair of two lists of strings. The first indicates which packages
424 /// were successfully re-activated; the second indicates which failed. 423 /// were successfully re-activated; the second indicates which failed.
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 } 787 }
789 788
790 /// Returns the value of the property named [name] in the bin stub script 789 /// Returns the value of the property named [name] in the bin stub script
791 /// [source]. 790 /// [source].
792 String _binStubProperty(String source, String name) { 791 String _binStubProperty(String source, String name) {
793 var pattern = new RegExp(quoteRegExp(name) + r": ([a-zA-Z0-9_-]+)"); 792 var pattern = new RegExp(quoteRegExp(name) + r": ([a-zA-Z0-9_-]+)");
794 var match = pattern.firstMatch(source); 793 var match = pattern.firstMatch(source);
795 return match == null ? null : match[1]; 794 return match == null ? null : match[1];
796 } 795 }
797 } 796 }
OLDNEW
« no previous file with comments | « lib/src/entrypoint.dart ('k') | lib/src/lock_file.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698