Chromium Code Reviews| 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 |