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.entrypoint; | 5 library pub.entrypoint; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:path/path.dart' as path; | 9 import 'package:path/path.dart' as path; |
10 | 10 |
(...skipping 25 matching lines...) Expand all Loading... |
36 /// contains a reusable library may not be the entrypoint when used by an app, | 36 /// contains a reusable library may not be the entrypoint when used by an app, |
37 /// but may be the entrypoint when you're running its tests. | 37 /// but may be the entrypoint when you're running its tests. |
38 class Entrypoint { | 38 class Entrypoint { |
39 /// The root package this entrypoint is associated with. | 39 /// The root package this entrypoint is associated with. |
40 final Package root; | 40 final Package root; |
41 | 41 |
42 /// The system-wide cache which caches packages that need to be fetched over | 42 /// The system-wide cache which caches packages that need to be fetched over |
43 /// the network. | 43 /// the network. |
44 final SystemCache cache; | 44 final SystemCache cache; |
45 | 45 |
| 46 /// Whether to create and symlink a "packages" directory containing links to |
| 47 /// the installed packages. |
| 48 final bool _packageSymlinks; |
| 49 |
46 /// The lockfile for the entrypoint. | 50 /// The lockfile for the entrypoint. |
47 /// | 51 /// |
48 /// If not provided to the entrypoint, it will be laoded lazily from disc. | 52 /// If not provided to the entrypoint, it will be laoded lazily from disc. |
49 LockFile _lockFile; | 53 LockFile _lockFile; |
50 | 54 |
51 /// Loads the entrypoint from a package at [rootDir]. | 55 /// Loads the entrypoint from a package at [rootDir]. |
52 Entrypoint(String rootDir, SystemCache cache) | 56 /// |
| 57 /// If [packageSymlinks] is `true`, this will create a "packages" directory |
| 58 /// with symlinks to the installed packages. This directory will be symlinked |
| 59 /// into any directory that might contain an entrypoint. |
| 60 Entrypoint(String rootDir, SystemCache cache, {bool packageSymlinks: true}) |
53 : root = new Package.load(null, rootDir, cache.sources), | 61 : root = new Package.load(null, rootDir, cache.sources), |
54 cache = cache; | 62 cache = cache, |
| 63 _packageSymlinks = packageSymlinks; |
55 | 64 |
56 /// Creates an entrypoint given package and lockfile objects. | 65 /// Creates an entrypoint given package and lockfile objects. |
57 Entrypoint.inMemory(this.root, this._lockFile, this.cache); | 66 Entrypoint.inMemory(this.root, this._lockFile, this.cache) |
| 67 : _packageSymlinks = false; |
58 | 68 |
59 /// The path to the entrypoint's "packages" directory. | 69 /// The path to the entrypoint's "packages" directory. |
60 String get packagesDir => path.join(root.dir, 'packages'); | 70 String get packagesDir => path.join(root.dir, 'packages'); |
61 | 71 |
62 /// `true` if the entrypoint package currently has a lock file. | 72 /// `true` if the entrypoint package currently has a lock file. |
63 bool get lockFileExists => _lockFile != null || entryExists(lockFilePath); | 73 bool get lockFileExists => _lockFile != null || entryExists(lockFilePath); |
64 | 74 |
65 LockFile get lockFile { | 75 LockFile get lockFile { |
66 if (_lockFile != null) return _lockFile; | 76 if (_lockFile != null) return _lockFile; |
67 | 77 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 }).then((result) { | 112 }).then((result) { |
103 if (!result.succeeded) throw result.error; | 113 if (!result.succeeded) throw result.error; |
104 | 114 |
105 result.showReport(type); | 115 result.showReport(type); |
106 | 116 |
107 if (dryRun) { | 117 if (dryRun) { |
108 result.summarizeChanges(type, dryRun: dryRun); | 118 result.summarizeChanges(type, dryRun: dryRun); |
109 return null; | 119 return null; |
110 } | 120 } |
111 | 121 |
112 // Install the packages. | 122 // Install the packages and maybe link them into the entrypoint. |
113 cleanDir(packagesDir); | 123 if (_packageSymlinks) { |
| 124 cleanDir(packagesDir); |
| 125 } else { |
| 126 deleteEntry(packagesDir); |
| 127 } |
| 128 |
114 return Future.wait(result.packages.map(_get)).then((ids) { | 129 return Future.wait(result.packages.map(_get)).then((ids) { |
115 _saveLockFile(ids); | 130 _saveLockFile(ids); |
116 _linkSelf(); | 131 |
117 _linkSecondaryPackageDirs(); | 132 if (_packageSymlinks) _linkSelf(); |
| 133 _linkOrDeleteSecondaryPackageDirs(); |
| 134 |
118 result.summarizeChanges(type, dryRun: dryRun); | 135 result.summarizeChanges(type, dryRun: dryRun); |
119 }); | 136 }); |
120 }); | 137 }); |
121 } | 138 } |
122 | 139 |
123 /// Makes sure the package at [id] is locally available. | 140 /// Makes sure the package at [id] is locally available. |
124 /// | 141 /// |
125 /// This automatically downloads the package to the system-wide cache as well | 142 /// This automatically downloads the package to the system-wide cache as well |
126 /// if it requires network access to retrieve (specifically, if the package's | 143 /// if it requires network access to retrieve (specifically, if the package's |
127 /// source is a [CachedSource]). | 144 /// source is a [CachedSource]). |
128 Future<PackageId> _get(PackageId id) { | 145 Future<PackageId> _get(PackageId id) { |
129 if (id.isRoot) return new Future.value(id); | 146 if (id.isRoot) return new Future.value(id); |
130 | 147 |
131 var packageDir = path.join(packagesDir, id.name); | 148 var source = cache.sources[id.source]; |
132 if (entryExists(packageDir)) deleteEntry(packageDir); | 149 return syncFuture(() { |
| 150 if (!_packageSymlinks) { |
| 151 if (source is! CachedSource) return null; |
| 152 return source.downloadToSystemCache(id); |
| 153 } |
133 | 154 |
134 var source = cache.sources[id.source]; | 155 var packageDir = path.join(packagesDir, id.name); |
135 return source.get(id, packageDir).then((_) => source.resolveId(id)); | 156 if (entryExists(packageDir)) deleteEntry(packageDir); |
| 157 return source.get(id, packageDir); |
| 158 }).then((_) => source.resolveId(id)); |
136 } | 159 } |
137 | 160 |
138 /// Determines whether or not the lockfile is out of date with respect to the | 161 /// Determines whether or not the lockfile is out of date with respect to the |
139 /// pubspec. | 162 /// pubspec. |
140 /// | 163 /// |
141 /// This will be `false` if there is no lockfile at all, or if the pubspec | 164 /// This will be `false` if there is no lockfile at all, or if the pubspec |
142 /// contains dependencies that are not in the lockfile or that don't match | 165 /// contains dependencies that are not in the lockfile or that don't match |
143 /// what's in there. | 166 /// what's in there. |
144 bool _isLockFileUpToDate(LockFile lockFile) { | 167 bool _isLockFileUpToDate(LockFile lockFile) { |
145 return root.immediateDependencies.every((package) { | 168 return root.immediateDependencies.every((package) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 /// a package to import its own files using `package:`. | 273 /// a package to import its own files using `package:`. |
251 void _linkSelf() { | 274 void _linkSelf() { |
252 var linkPath = path.join(packagesDir, root.name); | 275 var linkPath = path.join(packagesDir, root.name); |
253 // Create the symlink if it doesn't exist. | 276 // Create the symlink if it doesn't exist. |
254 if (entryExists(linkPath)) return; | 277 if (entryExists(linkPath)) return; |
255 ensureDir(packagesDir); | 278 ensureDir(packagesDir); |
256 createPackageSymlink(root.name, root.dir, linkPath, | 279 createPackageSymlink(root.name, root.dir, linkPath, |
257 isSelfLink: true, relative: true); | 280 isSelfLink: true, relative: true); |
258 } | 281 } |
259 | 282 |
260 /// Add "packages" directories to the whitelist of directories that may | 283 /// If [packageSymlinks] is true, add "packages" directories to the whitelist |
261 /// contain Dart entrypoints. | 284 /// of directories that may contain Dart entrypoints. |
262 void _linkSecondaryPackageDirs() { | 285 /// |
| 286 /// Otherwise, delete any "packages" directories in the whitelist of |
| 287 /// directories that may contain Dart entrypoints. |
| 288 void _linkOrDeleteSecondaryPackageDirs() { |
263 // Only the main "bin" directory gets a "packages" directory, not its | 289 // Only the main "bin" directory gets a "packages" directory, not its |
264 // subdirectories. | 290 // subdirectories. |
265 var binDir = path.join(root.dir, 'bin'); | 291 var binDir = path.join(root.dir, 'bin'); |
266 if (dirExists(binDir)) _linkSecondaryPackageDir(binDir); | 292 if (dirExists(binDir)) _linkOrDeleteSecondaryPackageDir(binDir); |
267 | 293 |
268 // The others get "packages" directories in subdirectories too. | 294 // The others get "packages" directories in subdirectories too. |
269 for (var dir in ['benchmark', 'example', 'test', 'tool', 'web']) { | 295 for (var dir in ['benchmark', 'example', 'test', 'tool', 'web']) { |
270 _linkSecondaryPackageDirsRecursively(path.join(root.dir, dir)); | 296 _linkOrDeleteSecondaryPackageDirsRecursively(path.join(root.dir, dir)); |
271 } | 297 } |
272 } | 298 } |
273 | 299 |
274 /// Creates a symlink to the `packages` directory in [dir] and all its | 300 /// If [packageSymlinks] is true, creates a symlink to the "packages" |
| 301 /// directory in [dir] and all its subdirectories. |
| 302 /// |
| 303 /// Otherwise, deletes any "packages" directories in [dir] and all its |
275 /// subdirectories. | 304 /// subdirectories. |
276 void _linkSecondaryPackageDirsRecursively(String dir) { | 305 void _linkOrDeleteSecondaryPackageDirsRecursively(String dir) { |
277 if (!dirExists(dir)) return; | 306 if (!dirExists(dir)) return; |
278 _linkSecondaryPackageDir(dir); | 307 _linkOrDeleteSecondaryPackageDir(dir); |
279 _listDirWithoutPackages(dir) | 308 _listDirWithoutPackages(dir) |
280 .where(dirExists) | 309 .where(dirExists) |
281 .forEach(_linkSecondaryPackageDir); | 310 .forEach(_linkOrDeleteSecondaryPackageDir); |
282 } | 311 } |
283 | 312 |
284 // TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed. | 313 // TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed. |
285 /// Recursively lists the contents of [dir], excluding hidden `.DS_Store` | 314 /// Recursively lists the contents of [dir], excluding hidden `.DS_Store` |
286 /// files and `package` files. | 315 /// files and `package` files. |
287 List<String> _listDirWithoutPackages(dir) { | 316 List<String> _listDirWithoutPackages(dir) { |
288 return flatten(listDir(dir).map((file) { | 317 return flatten(listDir(dir).map((file) { |
289 if (path.basename(file) == 'packages') return []; | 318 if (path.basename(file) == 'packages') return []; |
290 if (!dirExists(file)) return []; | 319 if (!dirExists(file)) return []; |
291 var fileAndSubfiles = [file]; | 320 var fileAndSubfiles = [file]; |
292 fileAndSubfiles.addAll(_listDirWithoutPackages(file)); | 321 fileAndSubfiles.addAll(_listDirWithoutPackages(file)); |
293 return fileAndSubfiles; | 322 return fileAndSubfiles; |
294 })); | 323 })); |
295 } | 324 } |
296 | 325 |
297 /// Creates a symlink to the `packages` directory in [dir]. Will replace one | 326 /// If [packageSymlinks] is true, creates a symlink to the "packages" |
298 /// if already there. | 327 /// directory in [dir]. |
299 void _linkSecondaryPackageDir(String dir) { | 328 /// |
| 329 /// Otherwise, deletes a "packages" directories in [dir] if one exists. |
| 330 void _linkOrDeleteSecondaryPackageDir(String dir) { |
300 var symlink = path.join(dir, 'packages'); | 331 var symlink = path.join(dir, 'packages'); |
301 if (entryExists(symlink)) deleteEntry(symlink); | 332 if (entryExists(symlink)) deleteEntry(symlink); |
302 createSymlink(packagesDir, symlink, relative: true); | 333 if (_packageSymlinks) createSymlink(packagesDir, symlink, relative: true); |
303 } | 334 } |
304 } | 335 } |
OLD | NEW |