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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:io'; | 6 import 'dart:io'; |
| 7 | 7 |
| 8 import 'package:barback/barback.dart'; | 8 import 'package:barback/barback.dart'; |
| 9 import 'package:package_config/packages_file.dart' as packages_file; | 9 import 'package:package_config/packages_file.dart' as packages_file; |
| 10 import 'package:path/path.dart' as p; | 10 import 'package:path/path.dart' as p; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 /// contains a reusable library may not be the entrypoint when used by an app, | 64 /// contains a reusable library may not be the entrypoint when used by an app, |
| 65 /// but may be the entrypoint when you're running its tests. | 65 /// but may be the entrypoint when you're running its tests. |
| 66 class Entrypoint { | 66 class Entrypoint { |
| 67 /// The root package this entrypoint is associated with. | 67 /// The root package this entrypoint is associated with. |
| 68 final Package root; | 68 final Package root; |
| 69 | 69 |
| 70 /// The system-wide cache which caches packages that need to be fetched over | 70 /// The system-wide cache which caches packages that need to be fetched over |
| 71 /// the network. | 71 /// the network. |
| 72 final SystemCache cache; | 72 final SystemCache cache; |
| 73 | 73 |
| 74 /// Whether to create and symlink a "packages" directory containing links to | |
| 75 /// the installed packages. | |
| 76 final bool _packageSymlinks; | |
| 77 | |
| 78 /// Whether this entrypoint is in memory only, as opposed to representing a | 74 /// Whether this entrypoint is in memory only, as opposed to representing a |
| 79 /// real directory on disk. | 75 /// real directory on disk. |
| 80 final bool _inMemory; | 76 final bool _inMemory; |
| 81 | 77 |
| 82 /// Whether this is an entrypoint for a globally-activated package. | 78 /// Whether this is an entrypoint for a globally-activated package. |
| 83 final bool isGlobal; | 79 final bool isGlobal; |
| 84 | 80 |
| 85 /// The lockfile for the entrypoint. | 81 /// The lockfile for the entrypoint. |
| 86 /// | 82 /// |
| 87 /// If not provided to the entrypoint, it will be loaded lazily from disk. | 83 /// If not provided to the entrypoint, it will be loaded lazily from disk. |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 112 key: (id) => id.name, | 108 key: (id) => id.name, |
| 113 value: (id) => cache.load(id)); | 109 value: (id) => cache.load(id)); |
| 114 packages[root.name] = root; | 110 packages[root.name] = root; |
| 115 | 111 |
| 116 _packageGraph = new PackageGraph(this, lockFile, packages); | 112 _packageGraph = new PackageGraph(this, lockFile, packages); |
| 117 return _packageGraph; | 113 return _packageGraph; |
| 118 } | 114 } |
| 119 PackageGraph _packageGraph; | 115 PackageGraph _packageGraph; |
| 120 | 116 |
| 121 /// The path to the entrypoint's "packages" directory. | 117 /// The path to the entrypoint's "packages" directory. |
| 122 String get packagesDir => root.path('packages'); | 118 String get packagesPath => root.path('packages'); |
| 123 | 119 |
| 124 /// The path to the entrypoint's ".packages" file. | 120 /// The path to the entrypoint's ".packages" file. |
| 125 String get packagesFile => root.path('.packages'); | 121 String get packagesFile => root.path('.packages'); |
| 126 | 122 |
| 127 /// The path to the entrypoint package's pubspec. | 123 /// The path to the entrypoint package's pubspec. |
| 128 String get pubspecPath => root.path('pubspec.yaml'); | 124 String get pubspecPath => root.path('pubspec.yaml'); |
| 129 | 125 |
| 130 /// The path to the entrypoint package's lockfile. | 126 /// The path to the entrypoint package's lockfile. |
| 131 String get lockFilePath => root.path('pubspec.lock'); | 127 String get lockFilePath => root.path('pubspec.lock'); |
| 132 | 128 |
| 133 /// The path to the directory containing precompiled dependencies. | 129 /// The path to the directory containing precompiled dependencies. |
| 134 /// | 130 /// |
| 135 /// We just precompile the debug version of a package. We're mostly interested | 131 /// We just precompile the debug version of a package. We're mostly interested |
| 136 /// in improving speed for development iteration loops, which usually use | 132 /// in improving speed for development iteration loops, which usually use |
| 137 /// debug mode. | 133 /// debug mode. |
| 138 String get _precompiledDepsPath => root.path('.pub', 'deps', 'debug'); | 134 String get _precompiledDepsPath => root.path('.pub', 'deps', 'debug'); |
| 139 | 135 |
| 140 /// The path to the directory containing dependency executable snapshots. | 136 /// The path to the directory containing dependency executable snapshots. |
| 141 String get _snapshotPath => root.path('.pub', 'bin'); | 137 String get _snapshotPath => root.path('.pub', 'bin'); |
| 142 | 138 |
| 143 /// Loads the entrypoint from a package at [rootDir]. | 139 /// Loads the entrypoint from a package at [rootDir]. |
| 144 /// | 140 Entrypoint(String rootDir, SystemCache cache, {this.isGlobal: false}) |
| 145 /// If [packageSymlinks] is `true`, this will create a "packages" directory | |
| 146 /// with symlinks to the installed packages. This directory will be symlinked | |
| 147 /// into any directory that might contain an entrypoint. | |
| 148 Entrypoint(String rootDir, SystemCache cache, {bool packageSymlinks: true, | |
| 149 this.isGlobal: false}) | |
| 150 : root = new Package.load(null, rootDir, cache.sources), | 141 : root = new Package.load(null, rootDir, cache.sources), |
| 151 cache = cache, | 142 cache = cache, |
| 152 _packageSymlinks = packageSymlinks, | |
| 153 _inMemory = false; | 143 _inMemory = false; |
| 154 | 144 |
| 155 /// Creates an entrypoint given package and lockfile objects. | 145 /// Creates an entrypoint given package and lockfile objects. |
| 156 Entrypoint.inMemory(this.root, this._lockFile, this.cache, | 146 Entrypoint.inMemory(this.root, this._lockFile, this.cache, |
| 157 {this.isGlobal: false}) | 147 {this.isGlobal: false}) |
| 158 : _packageSymlinks = false, | 148 : _inMemory = true; |
| 159 _inMemory = true; | |
| 160 | 149 |
| 161 /// Creates an entrypoint given a package and a [solveResult], from which the | 150 /// Creates an entrypoint given a package and a [solveResult], from which the |
| 162 /// package graph and lockfile will be computed. | 151 /// package graph and lockfile will be computed. |
| 163 Entrypoint.fromSolveResult(this.root, this.cache, SolveResult solveResult, | 152 Entrypoint.fromSolveResult(this.root, this.cache, SolveResult solveResult, |
| 164 {this.isGlobal: false}) | 153 {this.isGlobal: false}) |
| 165 : _packageSymlinks = false, | 154 : _inMemory = true { |
| 166 _inMemory = true { | |
| 167 _packageGraph = new PackageGraph.fromSolveResult(this, solveResult); | 155 _packageGraph = new PackageGraph.fromSolveResult(this, solveResult); |
| 168 _lockFile = _packageGraph.lockFile; | 156 _lockFile = _packageGraph.lockFile; |
| 169 } | 157 } |
| 170 | 158 |
| 171 /// Gets all dependencies of the [root] package. | 159 /// Gets all dependencies of the [root] package. |
| 172 /// | 160 /// |
| 173 /// Performs version resolution according to [SolveType]. | 161 /// Performs version resolution according to [SolveType]. |
| 174 /// | 162 /// |
| 175 /// [useLatest], if provided, defines a list of packages that will be | 163 /// [useLatest], if provided, defines a list of packages that will be |
| 176 /// unlocked and forced to their latest versions. If [upgradeAll] is | 164 /// unlocked and forced to their latest versions. If [upgradeAll] is |
| 177 /// true, the previous lockfile is ignored and all packages are re-resolved | 165 /// true, the previous lockfile is ignored and all packages are re-resolved |
| 178 /// from scratch. Otherwise, it will attempt to preserve the versions of all | 166 /// from scratch. Otherwise, it will attempt to preserve the versions of all |
| 179 /// previously locked packages. | 167 /// previously locked packages. |
| 180 /// | 168 /// |
| 181 /// Shows a report of the changes made relative to the previous lockfile. If | 169 /// Shows a report of the changes made relative to the previous lockfile. If |
| 182 /// this is an upgrade or downgrade, all transitive dependencies are shown in | 170 /// this is an upgrade or downgrade, all transitive dependencies are shown in |
| 183 /// the report. Otherwise, only dependencies that were changed are shown. If | 171 /// the report. Otherwise, only dependencies that were changed are shown. If |
| 184 /// [dryRun] is `true`, no physical changes are made. | 172 /// [dryRun] is `true`, no physical changes are made. |
| 185 /// | 173 /// |
| 186 /// If [precompile] is `true` (the default), this snapshots dependencies' | 174 /// If [precompile] is `true` (the default), this snapshots dependencies' |
| 187 /// executables and runs transformers on transformed dependencies. | 175 /// executables and runs transformers on transformed dependencies. |
| 188 /// | 176 /// |
| 177 /// If [packagesDir] is `true`, this will create "packages" directory with | |
| 178 /// symlinks to the installed packages. This directory will be symlinked into | |
| 179 /// any directory that might contain an entrypoint. | |
| 180 /// | |
| 189 /// Updates [lockFile] and [packageRoot] accordingly. | 181 /// Updates [lockFile] and [packageRoot] accordingly. |
| 190 Future acquireDependencies(SolveType type, {List<String> useLatest, | 182 Future acquireDependencies(SolveType type, {List<String> useLatest, |
| 191 bool dryRun: false, bool precompile: true}) async { | 183 bool dryRun: false, bool precompile: true, bool packagesDir: false}) |
|
Bob Nystrom
2016/08/16 22:19:43
The name "packagesDir" reads like it *is* the pack
nweiz
2016/08/16 22:27:57
I generally prefer short names to totally unambigu
| |
| 184 async { | |
| 192 var result = await resolveVersions(type, cache, root, | 185 var result = await resolveVersions(type, cache, root, |
| 193 lockFile: lockFile, useLatest: useLatest); | 186 lockFile: lockFile, useLatest: useLatest); |
| 194 if (!result.succeeded) throw result.error; | 187 if (!result.succeeded) throw result.error; |
| 195 | 188 |
| 196 result.showReport(type); | 189 result.showReport(type); |
| 197 | 190 |
| 198 if (dryRun) { | 191 if (dryRun) { |
| 199 result.summarizeChanges(type, dryRun: dryRun); | 192 result.summarizeChanges(type, dryRun: dryRun); |
| 200 return; | 193 return; |
| 201 } | 194 } |
| 202 | 195 |
| 203 // Install the packages and maybe link them into the entrypoint. | 196 // Install the packages and maybe link them into the entrypoint. |
| 204 if (_packageSymlinks) { | 197 if (packagesDir) { |
| 205 cleanDir(packagesDir); | 198 cleanDir(packagesPath); |
| 206 } else { | 199 } else { |
| 207 deleteEntry(packagesDir); | 200 deleteEntry(packagesPath); |
| 208 } | 201 } |
| 209 | 202 |
| 210 await Future.wait(result.packages.map(_get)); | 203 await Future.wait(result.packages |
| 204 .map((id) => _get(id, packagesDir: packagesDir))); | |
| 211 _saveLockFile(result); | 205 _saveLockFile(result); |
| 212 | 206 |
| 213 if (_packageSymlinks) _linkSelf(); | 207 if (packagesDir) _linkSelf(); |
| 214 _linkOrDeleteSecondaryPackageDirs(); | 208 _linkOrDeleteSecondaryPackageDirs(packagesDir: packagesDir); |
| 215 | 209 |
| 216 result.summarizeChanges(type, dryRun: dryRun); | 210 result.summarizeChanges(type, dryRun: dryRun); |
| 217 | 211 |
| 218 /// Build a package graph from the version solver results so we don't | 212 /// Build a package graph from the version solver results so we don't |
| 219 /// have to reload and reparse all the pubspecs. | 213 /// have to reload and reparse all the pubspecs. |
| 220 _packageGraph = new PackageGraph.fromSolveResult(this, result); | 214 _packageGraph = new PackageGraph.fromSolveResult(this, result); |
| 221 packageGraph.loadTransformerCache().clearIfOutdated(result.changedPackages); | 215 packageGraph.loadTransformerCache().clearIfOutdated(result.changedPackages); |
| 222 | 216 |
| 223 try { | 217 try { |
| 224 if (precompile) { | 218 if (precompile) { |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 442 | 436 |
| 443 // Otherwise, we don't need to recompile. | 437 // Otherwise, we don't need to recompile. |
| 444 return []; | 438 return []; |
| 445 } | 439 } |
| 446 | 440 |
| 447 /// Makes sure the package at [id] is locally available. | 441 /// Makes sure the package at [id] is locally available. |
| 448 /// | 442 /// |
| 449 /// This automatically downloads the package to the system-wide cache as well | 443 /// This automatically downloads the package to the system-wide cache as well |
| 450 /// if it requires network access to retrieve (specifically, if the package's | 444 /// if it requires network access to retrieve (specifically, if the package's |
| 451 /// source is a [CachedSource]). | 445 /// source is a [CachedSource]). |
| 452 Future _get(PackageId id) async { | 446 Future _get(PackageId id, {bool packagesDir: false}) async { |
| 453 if (id.isRoot) return; | 447 if (id.isRoot) return; |
| 454 | 448 |
| 455 var source = cache.source(id.source); | 449 var source = cache.source(id.source); |
| 456 if (!_packageSymlinks) { | 450 if (!packagesDir) { |
| 457 if (source is CachedSource) await source.downloadToSystemCache(id); | 451 if (source is CachedSource) await source.downloadToSystemCache(id); |
| 458 return; | 452 return; |
| 459 } | 453 } |
| 460 | 454 |
| 461 var packageDir = p.join(packagesDir, id.name); | 455 var packagePath = p.join(packagesPath, id.name); |
| 462 if (entryExists(packageDir)) deleteEntry(packageDir); | 456 if (entryExists(packagePath)) deleteEntry(packagePath); |
| 463 await source.get(id, packageDir); | 457 await source.get(id, packagePath); |
| 464 } | 458 } |
| 465 | 459 |
| 466 /// Throws a [DataError] if the `.packages` file doesn't exist or if it's | 460 /// Throws a [DataError] if the `.packages` file doesn't exist or if it's |
| 467 /// out-of-date relative to the lockfile or the pubspec. | 461 /// out-of-date relative to the lockfile or the pubspec. |
| 468 void assertUpToDate() { | 462 void assertUpToDate() { |
| 469 if (_inMemory) return; | 463 if (_inMemory) return; |
| 470 | 464 |
| 471 if (!entryExists(lockFilePath)) { | 465 if (!entryExists(lockFilePath)) { |
| 472 dataError('No pubspec.lock file found, please run "pub get" first.'); | 466 dataError('No pubspec.lock file found, please run "pub get" first.'); |
| 473 } | 467 } |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 /// Saves a list of concrete package versions to the `pubspec.lock` file. | 641 /// Saves a list of concrete package versions to the `pubspec.lock` file. |
| 648 void _saveLockFile(SolveResult result) { | 642 void _saveLockFile(SolveResult result) { |
| 649 _lockFile = result.lockFile; | 643 _lockFile = result.lockFile; |
| 650 var lockFilePath = root.path('pubspec.lock'); | 644 var lockFilePath = root.path('pubspec.lock'); |
| 651 writeTextFile(lockFilePath, _lockFile.serialize(root.dir)); | 645 writeTextFile(lockFilePath, _lockFile.serialize(root.dir)); |
| 652 } | 646 } |
| 653 | 647 |
| 654 /// Creates a self-referential symlink in the `packages` directory that allows | 648 /// Creates a self-referential symlink in the `packages` directory that allows |
| 655 /// a package to import its own files using `package:`. | 649 /// a package to import its own files using `package:`. |
| 656 void _linkSelf() { | 650 void _linkSelf() { |
| 657 var linkPath = p.join(packagesDir, root.name); | 651 var linkPath = p.join(packagesPath, root.name); |
| 658 // Create the symlink if it doesn't exist. | 652 // Create the symlink if it doesn't exist. |
| 659 if (entryExists(linkPath)) return; | 653 if (entryExists(linkPath)) return; |
| 660 ensureDir(packagesDir); | 654 ensureDir(packagesPath); |
| 661 createPackageSymlink(root.name, root.dir, linkPath, | 655 createPackageSymlink(root.name, root.dir, linkPath, |
| 662 isSelfLink: true, relative: true); | 656 isSelfLink: true, relative: true); |
| 663 } | 657 } |
| 664 | 658 |
| 665 /// If [packageSymlinks] is true, add "packages" directories to the whitelist | 659 /// If [packagesDir] is true, add "packages" directories to the whitelist of |
| 666 /// of directories that may contain Dart entrypoints. | 660 /// directories that may contain Dart entrypoints. |
| 667 /// | 661 /// |
| 668 /// Otherwise, delete any "packages" directories in the whitelist of | 662 /// Otherwise, delete any "packages" directories in the whitelist of |
| 669 /// directories that may contain Dart entrypoints. | 663 /// directories that may contain Dart entrypoints. |
| 670 void _linkOrDeleteSecondaryPackageDirs() { | 664 void _linkOrDeleteSecondaryPackageDirs({bool packagesDir: false}) { |
| 671 // Only the main "bin" directory gets a "packages" directory, not its | 665 // Only the main "bin" directory gets a "packages" directory, not its |
| 672 // subdirectories. | 666 // subdirectories. |
| 673 var binDir = root.path('bin'); | 667 var binDir = root.path('bin'); |
| 674 if (dirExists(binDir)) _linkOrDeleteSecondaryPackageDir(binDir); | 668 if (dirExists(binDir)) { |
| 669 _linkOrDeleteSecondaryPackageDir(binDir, packagesDir: packagesDir); | |
| 670 } | |
| 675 | 671 |
| 676 // The others get "packages" directories in subdirectories too. | 672 // The others get "packages" directories in subdirectories too. |
| 677 for (var dir in ['benchmark', 'example', 'test', 'tool', 'web']) { | 673 for (var dir in ['benchmark', 'example', 'test', 'tool', 'web']) { |
| 678 _linkOrDeleteSecondaryPackageDirsRecursively(root.path(dir)); | 674 _linkOrDeleteSecondaryPackageDirsRecursively(root.path(dir), |
| 675 packagesDir: packagesDir); | |
| 679 } | 676 } |
| 680 } | 677 } |
| 681 | 678 |
| 682 /// If [packageSymlinks] is true, creates a symlink to the "packages" | 679 /// If [packagesDir] is true, creates a symlink to the "packages" directory in |
| 683 /// directory in [dir] and all its subdirectories. | 680 /// [dir] and all its subdirectories. |
| 684 /// | 681 /// |
| 685 /// Otherwise, deletes any "packages" directories in [dir] and all its | 682 /// Otherwise, deletes any "packages" directories in [dir] and all its |
| 686 /// subdirectories. | 683 /// subdirectories. |
| 687 void _linkOrDeleteSecondaryPackageDirsRecursively(String dir) { | 684 void _linkOrDeleteSecondaryPackageDirsRecursively(String dir, |
| 685 {bool packagesDir: false}) { | |
| 688 if (!dirExists(dir)) return; | 686 if (!dirExists(dir)) return; |
| 689 _linkOrDeleteSecondaryPackageDir(dir); | 687 _linkOrDeleteSecondaryPackageDir(dir, packagesDir: packagesDir); |
| 690 _listDirWithoutPackages(dir) | 688 for (var subdir in _listDirWithoutPackages(dir)) { |
| 691 .where(dirExists) | 689 if (!dirExists(subdir)) continue; |
| 692 .forEach(_linkOrDeleteSecondaryPackageDir); | 690 _linkOrDeleteSecondaryPackageDir(subdir, packagesDir: packagesDir); |
| 691 } | |
| 693 } | 692 } |
| 694 | 693 |
| 695 // TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed. | 694 // TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed. |
| 696 /// Recursively lists the contents of [dir], excluding hidden `.DS_Store` | 695 /// Recursively lists the contents of [dir], excluding hidden `.DS_Store` |
| 697 /// files and `package` files. | 696 /// files and `package` files. |
| 698 List<String> _listDirWithoutPackages(dir) { | 697 List<String> _listDirWithoutPackages(dir) { |
| 699 return listDir(dir).expand/*<String>*/((file) { | 698 return listDir(dir).expand/*<String>*/((file) { |
| 700 if (p.basename(file) == 'packages') return []; | 699 if (p.basename(file) == 'packages') return []; |
| 701 if (!dirExists(file)) return []; | 700 if (!dirExists(file)) return []; |
| 702 var fileAndSubfiles = [file]; | 701 var fileAndSubfiles = [file]; |
| 703 fileAndSubfiles.addAll(_listDirWithoutPackages(file)); | 702 fileAndSubfiles.addAll(_listDirWithoutPackages(file)); |
| 704 return fileAndSubfiles; | 703 return fileAndSubfiles; |
| 705 }); | 704 }); |
| 706 } | 705 } |
| 707 | 706 |
| 708 /// If [packageSymlinks] is true, creates a symlink to the "packages" | 707 /// If [packagesDir] is true, creates a symlink to the "packages" directory in |
| 709 /// directory in [dir]. | 708 /// [dir]. |
| 710 /// | 709 /// |
| 711 /// Otherwise, deletes a "packages" directories in [dir] if one exists. | 710 /// Otherwise, deletes a "packages" directories in [dir] if one exists. |
| 712 void _linkOrDeleteSecondaryPackageDir(String dir) { | 711 void _linkOrDeleteSecondaryPackageDir(String dir, {bool packagesDir: false}) { |
| 713 var symlink = p.join(dir, 'packages'); | 712 var symlink = p.join(dir, 'packages'); |
| 714 if (entryExists(symlink)) deleteEntry(symlink); | 713 if (entryExists(symlink)) deleteEntry(symlink); |
| 715 if (_packageSymlinks) createSymlink(packagesDir, symlink, relative: true); | 714 if (packagesDir) createSymlink(packagesPath, symlink, relative: true); |
| 716 } | 715 } |
| 717 } | 716 } |
| OLD | NEW |