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 import 'dart:io'; | 8 import 'dart:io'; |
9 | 9 |
10 import 'package:path/path.dart' as path; | 10 import 'package:package_config/packages_file.dart' as packages_file; |
11 import 'package:path/path.dart' as p; | |
11 import 'package:barback/barback.dart'; | 12 import 'package:barback/barback.dart'; |
12 | 13 |
13 import 'barback/asset_environment.dart'; | 14 import 'barback/asset_environment.dart'; |
14 import 'io.dart'; | 15 import 'io.dart'; |
15 import 'lock_file.dart'; | 16 import 'lock_file.dart'; |
16 import 'log.dart' as log; | 17 import 'log.dart' as log; |
17 import 'package.dart'; | 18 import 'package.dart'; |
18 import 'package_graph.dart'; | 19 import 'package_graph.dart'; |
19 import 'sdk.dart' as sdk; | 20 import 'sdk.dart' as sdk; |
20 import 'solver/version_solver.dart'; | 21 import 'solver/version_solver.dart'; |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
194 /// Precompile any transformed dependencies of the entrypoint. | 195 /// Precompile any transformed dependencies of the entrypoint. |
195 /// | 196 /// |
196 /// If [changed] is passed, only dependencies whose contents might be changed | 197 /// If [changed] is passed, only dependencies whose contents might be changed |
197 /// if one of the given packages changes will be recompiled. | 198 /// if one of the given packages changes will be recompiled. |
198 Future precompileDependencies({Iterable<String> changed}) async { | 199 Future precompileDependencies({Iterable<String> changed}) async { |
199 if (changed != null) changed = changed.toSet(); | 200 if (changed != null) changed = changed.toSet(); |
200 | 201 |
201 // Just precompile the debug version of a package. We're mostly interested | 202 // Just precompile the debug version of a package. We're mostly interested |
202 // in improving speed for development iteration loops, which usually use | 203 // in improving speed for development iteration loops, which usually use |
203 // debug mode. | 204 // debug mode. |
204 var depsDir = path.join('.pub', 'deps', 'debug'); | 205 var depsDir = p.join('.pub', 'deps', 'debug'); |
205 | 206 |
206 var dependenciesToPrecompile = packageGraph.packages.values | 207 var dependenciesToPrecompile = packageGraph.packages.values |
207 .where((package) { | 208 .where((package) { |
208 if (package.pubspec.transformers.isEmpty) return false; | 209 if (package.pubspec.transformers.isEmpty) return false; |
209 if (packageGraph.isPackageMutable(package.name)) return false; | 210 if (packageGraph.isPackageMutable(package.name)) return false; |
210 if (!dirExists(path.join(depsDir, package.name))) return true; | 211 if (!dirExists(p.join(depsDir, package.name))) return true; |
211 if (changed == null) return true; | 212 if (changed == null) return true; |
212 | 213 |
213 /// Only recompile [package] if any of its transitive dependencies have | 214 /// Only recompile [package] if any of its transitive dependencies have |
214 /// changed. We check all transitive dependencies because it's possible | 215 /// changed. We check all transitive dependencies because it's possible |
215 /// that a transformer makes decisions based on their contents. | 216 /// that a transformer makes decisions based on their contents. |
216 return overlaps( | 217 return overlaps( |
217 packageGraph.transitiveDependencies(package.name) | 218 packageGraph.transitiveDependencies(package.name) |
218 .map((package) => package.name).toSet(), | 219 .map((package) => package.name).toSet(), |
219 changed); | 220 changed); |
220 }).map((package) => package.name).toSet(); | 221 }).map((package) => package.name).toSet(); |
221 | 222 |
222 if (dirExists(depsDir)) { | 223 if (dirExists(depsDir)) { |
223 // Delete any cached dependencies that are going to be recached. | 224 // Delete any cached dependencies that are going to be recached. |
224 for (var package in dependenciesToPrecompile) { | 225 for (var package in dependenciesToPrecompile) { |
225 deleteEntry(path.join(depsDir, package)); | 226 deleteEntry(p.join(depsDir, package)); |
226 } | 227 } |
227 | 228 |
228 // Also delete any cached dependencies that should no longer be cached. | 229 // Also delete any cached dependencies that should no longer be cached. |
229 for (var subdir in listDir(depsDir)) { | 230 for (var subdir in listDir(depsDir)) { |
230 var package = packageGraph.packages[path.basename(subdir)]; | 231 var package = packageGraph.packages[p.basename(subdir)]; |
231 if (package == null || package.pubspec.transformers.isEmpty || | 232 if (package == null || package.pubspec.transformers.isEmpty || |
232 packageGraph.isPackageMutable(package.name)) { | 233 packageGraph.isPackageMutable(package.name)) { |
233 deleteEntry(subdir); | 234 deleteEntry(subdir); |
234 } | 235 } |
235 } | 236 } |
236 } | 237 } |
237 | 238 |
238 if (dependenciesToPrecompile.isEmpty) return; | 239 if (dependenciesToPrecompile.isEmpty) return; |
239 | 240 |
240 try { | 241 try { |
241 await log.progress("Precompiling dependencies", () async { | 242 await log.progress("Precompiling dependencies", () async { |
242 var packagesToLoad = | 243 var packagesToLoad = |
243 unionAll(dependenciesToPrecompile.map( | 244 unionAll(dependenciesToPrecompile.map( |
244 packageGraph.transitiveDependencies)) | 245 packageGraph.transitiveDependencies)) |
245 .map((package) => package.name).toSet(); | 246 .map((package) => package.name).toSet(); |
246 | 247 |
247 var environment = await AssetEnvironment.create(this, BarbackMode.DEBUG, | 248 var environment = await AssetEnvironment.create(this, BarbackMode.DEBUG, |
248 packages: packagesToLoad, useDart2JS: false); | 249 packages: packagesToLoad, useDart2JS: false); |
249 | 250 |
250 /// Ignore barback errors since they'll be emitted via [getAllAssets] | 251 /// Ignore barback errors since they'll be emitted via [getAllAssets] |
251 /// below. | 252 /// below. |
252 environment.barback.errors.listen((_) {}); | 253 environment.barback.errors.listen((_) {}); |
253 | 254 |
254 // TODO(nweiz): only get assets from [dependenciesToPrecompile] so as | 255 // TODO(nweiz): only get assets from [dependenciesToPrecompile] so as |
255 // not to trigger unnecessary lazy transformers. | 256 // not to trigger unnecessary lazy transformers. |
256 var assets = await environment.barback.getAllAssets(); | 257 var assets = await environment.barback.getAllAssets(); |
257 await waitAndPrintErrors(assets.map((asset) async { | 258 await waitAndPrintErrors(assets.map((asset) async { |
258 if (!dependenciesToPrecompile.contains(asset.id.package)) return; | 259 if (!dependenciesToPrecompile.contains(asset.id.package)) return; |
259 | 260 |
260 var destPath = path.join( | 261 var destPath = p.join( |
261 depsDir, asset.id.package, path.fromUri(asset.id.path)); | 262 depsDir, asset.id.package, p.fromUri(asset.id.path)); |
262 ensureDir(path.dirname(destPath)); | 263 ensureDir(p.dirname(destPath)); |
263 await createFileFromStream(asset.read(), destPath); | 264 await createFileFromStream(asset.read(), destPath); |
264 })); | 265 })); |
265 | 266 |
266 log.message("Precompiled " + | 267 log.message("Precompiled " + |
267 toSentence(ordered(dependenciesToPrecompile).map(log.bold)) + "."); | 268 toSentence(ordered(dependenciesToPrecompile).map(log.bold)) + "."); |
268 }); | 269 }); |
269 } catch (_) { | 270 } catch (_) { |
270 // TODO(nweiz): When barback does a better job of associating errors with | 271 // TODO(nweiz): When barback does a better job of associating errors with |
271 // assets (issue 19491), catch and handle compilation errors on a | 272 // assets (issue 19491), catch and handle compilation errors on a |
272 // per-package basis. | 273 // per-package basis. |
273 for (var package in dependenciesToPrecompile) { | 274 for (var package in dependenciesToPrecompile) { |
274 deleteEntry(path.join(depsDir, package)); | 275 deleteEntry(p.join(depsDir, package)); |
275 } | 276 } |
276 rethrow; | 277 rethrow; |
277 } | 278 } |
278 } | 279 } |
279 | 280 |
280 /// Precompiles all executables from dependencies that don't transitively | 281 /// Precompiles all executables from dependencies that don't transitively |
281 /// depend on [this] or on a path dependency. | 282 /// depend on [this] or on a path dependency. |
282 Future precompileExecutables({Iterable<String> changed}) async { | 283 Future precompileExecutables({Iterable<String> changed}) async { |
283 if (changed != null) changed = changed.toSet(); | 284 if (changed != null) changed = changed.toSet(); |
284 | 285 |
285 var binDir = path.join('.pub', 'bin'); | 286 var binDir = p.join('.pub', 'bin'); |
286 var sdkVersionPath = path.join(binDir, 'sdk-version'); | 287 var sdkVersionPath = p.join(binDir, 'sdk-version'); |
287 | 288 |
288 // If the existing executable was compiled with a different SDK, we need to | 289 // If the existing executable was compiled with a different SDK, we need to |
289 // recompile regardless of what changed. | 290 // recompile regardless of what changed. |
290 // TODO(nweiz): Use the VM to check this when issue 20802 is fixed. | 291 // TODO(nweiz): Use the VM to check this when issue 20802 is fixed. |
291 var sdkMatches = fileExists(sdkVersionPath) && | 292 var sdkMatches = fileExists(sdkVersionPath) && |
292 readTextFile(sdkVersionPath) == "${sdk.version}\n"; | 293 readTextFile(sdkVersionPath) == "${sdk.version}\n"; |
293 if (!sdkMatches) changed = null; | 294 if (!sdkMatches) changed = null; |
294 | 295 |
295 // Clean out any outdated snapshots. | 296 // Clean out any outdated snapshots. |
296 if (dirExists(binDir)) { | 297 if (dirExists(binDir)) { |
297 for (var entry in listDir(binDir)) { | 298 for (var entry in listDir(binDir)) { |
298 if (!dirExists(entry)) continue; | 299 if (!dirExists(entry)) continue; |
299 | 300 |
300 var package = path.basename(entry); | 301 var package = p.basename(entry); |
301 if (!packageGraph.packages.containsKey(package) || | 302 if (!packageGraph.packages.containsKey(package) || |
302 packageGraph.isPackageMutable(package)) { | 303 packageGraph.isPackageMutable(package)) { |
303 deleteEntry(entry); | 304 deleteEntry(entry); |
304 } | 305 } |
305 } | 306 } |
306 } | 307 } |
307 | 308 |
308 var executables = new Map.fromIterable(root.immediateDependencies, | 309 var executables = new Map.fromIterable(root.immediateDependencies, |
309 key: (dep) => dep.name, | 310 key: (dep) => dep.name, |
310 value: (dep) => _executablesForPackage(dep.name, changed)); | 311 value: (dep) => _executablesForPackage(dep.name, changed)); |
(...skipping 19 matching lines...) Expand all Loading... | |
330 executables.values.map((ids) => ids.toSet())); | 331 executables.values.map((ids) => ids.toSet())); |
331 var environment = await AssetEnvironment.create(this, BarbackMode.RELEASE, | 332 var environment = await AssetEnvironment.create(this, BarbackMode.RELEASE, |
332 packages: packagesToLoad, | 333 packages: packagesToLoad, |
333 entrypoints: executableIds, | 334 entrypoints: executableIds, |
334 useDart2JS: false); | 335 useDart2JS: false); |
335 environment.barback.errors.listen((error) { | 336 environment.barback.errors.listen((error) { |
336 log.error(log.red("Build error:\n$error")); | 337 log.error(log.red("Build error:\n$error")); |
337 }); | 338 }); |
338 | 339 |
339 await waitAndPrintErrors(executables.keys.map((package) async { | 340 await waitAndPrintErrors(executables.keys.map((package) async { |
340 var dir = path.join(binDir, package); | 341 var dir = p.join(binDir, package); |
341 cleanDir(dir); | 342 cleanDir(dir); |
342 await environment.precompileExecutables(package, dir, | 343 await environment.precompileExecutables(package, dir, |
343 executableIds: executables[package]); | 344 executableIds: executables[package]); |
344 })); | 345 })); |
345 }); | 346 }); |
346 } | 347 } |
347 | 348 |
348 /// Returns the list of all executable assets for [packageName] that should be | 349 /// Returns the list of all executable assets for [packageName] that should be |
349 /// precompiled. | 350 /// precompiled. |
350 /// | 351 /// |
(...skipping 15 matching lines...) Expand all Loading... | |
366 // If any of the package's dependencies changed, recompile the executables. | 367 // If any of the package's dependencies changed, recompile the executables. |
367 if (packageGraph.transitiveDependencies(packageName) | 368 if (packageGraph.transitiveDependencies(packageName) |
368 .any((package) => changed.contains(package.name))) { | 369 .any((package) => changed.contains(package.name))) { |
369 return executables; | 370 return executables; |
370 } | 371 } |
371 | 372 |
372 // If any executables don't exist, precompile them regardless of what | 373 // If any executables don't exist, precompile them regardless of what |
373 // changed. Since we delete the bin directory before recompiling, we need to | 374 // changed. Since we delete the bin directory before recompiling, we need to |
374 // recompile all executables. | 375 // recompile all executables. |
375 var executablesExist = executables.every((executable) => | 376 var executablesExist = executables.every((executable) => |
376 fileExists(path.join('.pub', 'bin', packageName, | 377 fileExists(p.join('.pub', 'bin', packageName, |
377 "${path.url.basename(executable.path)}.snapshot"))); | 378 "${p.url.basename(executable.path)}.snapshot"))); |
378 if (!executablesExist) return executables; | 379 if (!executablesExist) return executables; |
379 | 380 |
380 // Otherwise, we don't need to recompile. | 381 // Otherwise, we don't need to recompile. |
381 return []; | 382 return []; |
382 } | 383 } |
383 | 384 |
384 /// Makes sure the package at [id] is locally available. | 385 /// Makes sure the package at [id] is locally available. |
385 /// | 386 /// |
386 /// This automatically downloads the package to the system-wide cache as well | 387 /// This automatically downloads the package to the system-wide cache as well |
387 /// if it requires network access to retrieve (specifically, if the package's | 388 /// if it requires network access to retrieve (specifically, if the package's |
388 /// source is a [CachedSource]). | 389 /// source is a [CachedSource]). |
389 Future<PackageId> _get(PackageId id) { | 390 Future<PackageId> _get(PackageId id) { |
390 if (id.isRoot) return new Future.value(id); | 391 if (id.isRoot) return new Future.value(id); |
391 | 392 |
392 var source = cache.sources[id.source]; | 393 var source = cache.sources[id.source]; |
393 return new Future.sync(() { | 394 return new Future.sync(() { |
394 if (!_packageSymlinks) { | 395 if (!_packageSymlinks) { |
395 if (source is! CachedSource) return null; | 396 if (source is! CachedSource) return null; |
396 return source.downloadToSystemCache(id); | 397 return source.downloadToSystemCache(id); |
397 } | 398 } |
398 | 399 |
399 var packageDir = path.join(packagesDir, id.name); | 400 var packageDir = p.join(packagesDir, id.name); |
400 if (entryExists(packageDir)) deleteEntry(packageDir); | 401 if (entryExists(packageDir)) deleteEntry(packageDir); |
401 return source.get(id, packageDir); | 402 return source.get(id, packageDir); |
402 }).then((_) => source.resolveId(id)); | 403 }).then((_) => source.resolveId(id)); |
403 } | 404 } |
404 | 405 |
405 /// Throws a [DataError] if the `.packages` file doesn't exist or if it's | 406 /// Throws a [DataError] if the `.packages` file doesn't exist or if it's |
406 /// out-of-date relative to the lockfile or the pubspec. | 407 /// out-of-date relative to the lockfile or the pubspec. |
407 void assertUpToDate() { | 408 void assertUpToDate() { |
408 if (_inMemory) return; | 409 if (_inMemory) return; |
409 | 410 |
410 if (!entryExists(lockFilePath)) { | 411 if (!entryExists(lockFilePath)) { |
411 dataError('No pubspec.lock file found, please run "pub get" first.'); | 412 dataError('No pubspec.lock file found, please run "pub get" first.'); |
412 } | 413 } |
413 | 414 |
414 if (!entryExists(packagesFile)) { | 415 if (!entryExists(packagesFile)) { |
415 dataError('No .packages file found, please run "pub get" first.'); | 416 dataError('No .packages file found, please run "pub get" first.'); |
416 } | 417 } |
417 | 418 |
418 var packagesModified = new File(packagesFile).lastModifiedSync(); | |
419 var pubspecModified = new File(pubspecPath).lastModifiedSync(); | 419 var pubspecModified = new File(pubspecPath).lastModifiedSync(); |
420 if (packagesModified.isBefore(pubspecModified)) { | 420 var lockFileModified = new File(lockFilePath).lastModifiedSync(); |
421 dataError('The pubspec.yaml file has changed since the .packages file ' | 421 |
422 'was generated, please run "pub get" again.'); | 422 var touchedLockFile = false; |
423 if (lockFileModified.isBefore(pubspecModified)) { | |
424 if (_isLockFileUpToDate() && _arePackagesAvailable()) { | |
425 touchedLockFile = true; | |
426 touch(lockFilePath); | |
427 } else { | |
428 dataError('The pubspec.yaml file has changed since the pubspec.lock ' | |
429 'file was generated, please run "pub get" again.'); | |
430 } | |
423 } | 431 } |
424 | 432 |
425 var lockFileModified = new File(lockFilePath).lastModifiedSync(); | 433 var packagesModified = new File(packagesFile).lastModifiedSync(); |
426 if (packagesModified.isBefore(lockFileModified)) { | 434 if (packagesModified.isBefore(lockFileModified)) { |
427 dataError('The pubspec.lock file has changed since the .packages file ' | 435 if (_isPackagesFileUpToDate()) { |
428 'was generated, please run "pub get" again.'); | 436 touch(packagesFile); |
437 } else { | |
438 dataError('The pubspec.lock file has changed since the .packages file ' | |
439 'was generated, please run "pub get" again.'); | |
440 } | |
441 } else if (touchedLockFile) { | |
442 touch(packagesFile); | |
429 } | 443 } |
430 } | 444 } |
431 | 445 |
446 /// Determines whether or not the lockfile is out of date with respect to the | |
447 /// pubspec. | |
448 /// | |
449 /// This will be `false` if the pubspec contains dependencies that are not in | |
450 /// the lockfile or that don't match what's in there. | |
451 bool _isLockFileUpToDate() { | |
452 return root.immediateDependencies.every((package) { | |
453 var locked = lockFile.packages[package.name]; | |
454 if (locked == null) return false; | |
455 | |
456 if (package.source != locked.source) return false; | |
457 | |
458 if (!package.constraint.allows(locked.version)) return false; | |
459 | |
460 var source = cache.sources[package.source]; | |
461 if (source == null) return false; | |
462 | |
463 return source.descriptionsEqual(package.description, locked.description); | |
464 }); | |
465 } | |
466 | |
467 /// Determines whether all of the packages in the lockfile are already | |
468 /// installed and available. | |
469 /// | |
470 /// Note: this assumes [_isLockFileUpToDate] has already been called and | |
471 /// returned `true`. | |
472 bool _arePackagesAvailable() { | |
473 return lockFile.packages.values.every((package) { | |
474 var source = cache.sources[package.source]; | |
475 | |
476 // This should only be called after [_isLockFileUpToDate] has returned | |
477 // `true`, which ensures all of the sources in the lock file are valid. | |
478 assert(source != null); | |
479 | |
480 // We only care about cached sources. Uncached sources aren't "installed". | |
481 // If one of those is missing, we want to show the user the file not | |
482 // found error later since installing won't accomplish anything. | |
483 if (source is! CachedSource) return true; | |
484 | |
485 // Get the directory. | |
486 var dir = source.getDirectory(package); | |
487 // See if the directory is there and looks like a package. | |
488 return dirExists(dir) && fileExists(p.join(dir, "pubspec.yaml")); | |
489 }); | |
490 } | |
491 | |
492 /// Determines whether or not the `.packages` file is out of date with respect | |
493 /// to the lockfile. | |
494 /// | |
495 /// This will be `false` if the packages file contains dependencies that are | |
496 /// not in the lockfile or that don't match what's in there. | |
497 bool _isPackagesFileUpToDate() { | |
498 var packages = packages_file.parse( | |
499 new File(packagesFile).readAsBytesSync(), | |
500 p.toUri(packagesFile)); | |
501 | |
502 return lockFile.packages.values.every((lockFileId) { | |
503 var source = cache.sources[lockFileId.source]; | |
504 | |
505 // It's very unlikely that the lockfile is invalid here, but it's not | |
506 // impossible—for example, the user may have a very old application | |
507 // package with a checked-in lockfile that's newer than the pubspec, but | |
508 // that contains sdk dependencies. | |
509 if (source == null) return false; | |
510 | |
511 var packagesFileUri = packages[lockFileId.name]; | |
512 if (packagesFileUri == null) return false; | |
513 | |
514 // Pub only generates "file:" and relative URIs. | |
515 if (packagesFileUri.scheme != 'file' && | |
516 packagesFileUri.scheme.isNotEmpty) { | |
517 return false; | |
518 } | |
519 | |
520 // Get the dirname of the .packages path, since it's pointing to lib/. | |
521 var packagesFilePath = p.dirname( | |
522 p.join(root.dir, p.fromUri(packagesFileUri))); | |
523 var lockFilePath = p.join(root.dir, source.getDirectory(lockFileId)); | |
524 | |
525 // For cached sources, Make sure the directory exists and looks like a | |
Bob Nystrom
2015/08/31 19:32:21
"Make" -> "make"
nweiz
2015/08/31 20:41:29
Done.
| |
526 // package. This is also done by [_arePackagesAvailable] but that may not | |
527 // be run if the lockfile is newer than the pubspec. | |
528 if (source is CachedSource && | |
529 !dirExists(packagesFilePath) || | |
530 !fileExists(p.join(packagesFilePath, "pubspec.yaml"))) { | |
531 return false; | |
532 } | |
533 | |
534 // Make sure that the packages file agrees with the lock file about the | |
535 // path to the package. | |
536 return p.normalize(packagesFilePath) == p.normalize(lockFilePath); | |
537 }); | |
538 } | |
539 | |
432 /// Saves a list of concrete package versions to the `pubspec.lock` file. | 540 /// Saves a list of concrete package versions to the `pubspec.lock` file. |
433 void _saveLockFile(List<PackageId> packageIds) { | 541 void _saveLockFile(List<PackageId> packageIds) { |
434 _lockFile = new LockFile(packageIds, cache.sources); | 542 _lockFile = new LockFile(packageIds, cache.sources); |
435 var lockFilePath = root.path('pubspec.lock'); | 543 var lockFilePath = root.path('pubspec.lock'); |
436 writeTextFile(lockFilePath, _lockFile.serialize(root.dir)); | 544 writeTextFile(lockFilePath, _lockFile.serialize(root.dir)); |
437 } | 545 } |
438 | 546 |
439 /// Creates a self-referential symlink in the `packages` directory that allows | 547 /// Creates a self-referential symlink in the `packages` directory that allows |
440 /// a package to import its own files using `package:`. | 548 /// a package to import its own files using `package:`. |
441 void _linkSelf() { | 549 void _linkSelf() { |
442 var linkPath = path.join(packagesDir, root.name); | 550 var linkPath = p.join(packagesDir, root.name); |
443 // Create the symlink if it doesn't exist. | 551 // Create the symlink if it doesn't exist. |
444 if (entryExists(linkPath)) return; | 552 if (entryExists(linkPath)) return; |
445 ensureDir(packagesDir); | 553 ensureDir(packagesDir); |
446 createPackageSymlink(root.name, root.dir, linkPath, | 554 createPackageSymlink(root.name, root.dir, linkPath, |
447 isSelfLink: true, relative: true); | 555 isSelfLink: true, relative: true); |
448 } | 556 } |
449 | 557 |
450 /// If [packageSymlinks] is true, add "packages" directories to the whitelist | 558 /// If [packageSymlinks] is true, add "packages" directories to the whitelist |
451 /// of directories that may contain Dart entrypoints. | 559 /// of directories that may contain Dart entrypoints. |
452 /// | 560 /// |
(...skipping 22 matching lines...) Expand all Loading... | |
475 _listDirWithoutPackages(dir) | 583 _listDirWithoutPackages(dir) |
476 .where(dirExists) | 584 .where(dirExists) |
477 .forEach(_linkOrDeleteSecondaryPackageDir); | 585 .forEach(_linkOrDeleteSecondaryPackageDir); |
478 } | 586 } |
479 | 587 |
480 // TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed. | 588 // TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed. |
481 /// Recursively lists the contents of [dir], excluding hidden `.DS_Store` | 589 /// Recursively lists the contents of [dir], excluding hidden `.DS_Store` |
482 /// files and `package` files. | 590 /// files and `package` files. |
483 List<String> _listDirWithoutPackages(dir) { | 591 List<String> _listDirWithoutPackages(dir) { |
484 return flatten(listDir(dir).map((file) { | 592 return flatten(listDir(dir).map((file) { |
485 if (path.basename(file) == 'packages') return []; | 593 if (p.basename(file) == 'packages') return []; |
486 if (!dirExists(file)) return []; | 594 if (!dirExists(file)) return []; |
487 var fileAndSubfiles = [file]; | 595 var fileAndSubfiles = [file]; |
488 fileAndSubfiles.addAll(_listDirWithoutPackages(file)); | 596 fileAndSubfiles.addAll(_listDirWithoutPackages(file)); |
489 return fileAndSubfiles; | 597 return fileAndSubfiles; |
490 })); | 598 })); |
491 } | 599 } |
492 | 600 |
493 /// If [packageSymlinks] is true, creates a symlink to the "packages" | 601 /// If [packageSymlinks] is true, creates a symlink to the "packages" |
494 /// directory in [dir]. | 602 /// directory in [dir]. |
495 /// | 603 /// |
496 /// Otherwise, deletes a "packages" directories in [dir] if one exists. | 604 /// Otherwise, deletes a "packages" directories in [dir] if one exists. |
497 void _linkOrDeleteSecondaryPackageDir(String dir) { | 605 void _linkOrDeleteSecondaryPackageDir(String dir) { |
498 var symlink = path.join(dir, 'packages'); | 606 var symlink = p.join(dir, 'packages'); |
499 if (entryExists(symlink)) deleteEntry(symlink); | 607 if (entryExists(symlink)) deleteEntry(symlink); |
500 if (_packageSymlinks) createSymlink(packagesDir, symlink, relative: true); | 608 if (_packageSymlinks) createSymlink(packagesDir, symlink, relative: true); |
501 } | 609 } |
502 } | 610 } |
OLD | NEW |