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

Unified Diff: lib/src/entrypoint.dart

Issue 1809993003: Add a --no-precompile flag. (Closed) Base URL: git@github.com:dart-lang/pub.git@master
Patch Set: Code review changes Created 4 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/src/command/upgrade.dart ('k') | test/get/cache_transformed_dependency_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/entrypoint.dart
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 1cb84628b32a8ac3982b54fd8242638eefae455d..dc1a4a445f6f95eacab95ac2e73ee75c5f2fddd2 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -109,6 +109,16 @@ class Entrypoint {
/// The path to the entrypoint package's lockfile.
String get lockFilePath => root.path('pubspec.lock');
+ /// The path to the directory containing precompiled dependencies.
+ ///
+ /// We just precompile the debug version of a package. We're mostly interested
+ /// in improving speed for development iteration loops, which usually use
+ /// debug mode.
+ String get _precompiledDepsPath => root.path('.pub', 'deps', 'debug');
+
+ /// The path to the directory containing dependency executable snapshots.
+ String get _snapshotPath => root.path('.pub', 'bin');
+
/// Loads the entrypoint from a package at [rootDir].
///
/// If [packageSymlinks] is `true`, this will create a "packages" directory
@@ -152,9 +162,12 @@ class Entrypoint {
/// the report. Otherwise, only dependencies that were changed are shown. If
/// [dryRun] is `true`, no physical changes are made.
///
+ /// If [precompile] is `true` (the default), this snapshots dependencies'
+ /// executables and runs transformers on transformed dependencies.
+ ///
/// Updates [lockFile] and [packageRoot] accordingly.
Future acquireDependencies(SolveType type, {List<String> useLatest,
- bool dryRun: false}) async {
+ bool dryRun: false, bool precompile: true}) async {
var result = await resolveVersions(type, cache.sources, root,
lockFile: lockFile, useLatest: useLatest);
if (!result.succeeded) throw result.error;
@@ -187,8 +200,16 @@ class Entrypoint {
packageGraph.loadTransformerCache().clearIfOutdated(result.changedPackages);
try {
- await precompileDependencies(changed: result.changedPackages);
- await precompileExecutables(changed: result.changedPackages);
+ if (precompile) {
+ await _precompileDependencies(changed: result.changedPackages);
+ await precompileExecutables(changed: result.changedPackages);
+ } else {
+ // If precompilation is disabled, delete any stale cached dependencies
+ // or snapshots.
+ _deletePrecompiledDependencies(
+ _dependenciesToPrecompile(changed: result.changedPackages));
+ _deleteExecutableSnapshots(changed: result.changedPackages);
+ }
} catch (error, stackTrace) {
// Just log exceptions here. Since the method is just about acquiring
// dependencies, it shouldn't fail unless that fails.
@@ -202,46 +223,11 @@ class Entrypoint {
///
/// If [changed] is passed, only dependencies whose contents might be changed
/// if one of the given packages changes will be recompiled.
- Future precompileDependencies({Iterable<String> changed}) async {
+ Future _precompileDependencies({Iterable<String> changed}) async {
if (changed != null) changed = changed.toSet();
- // Just precompile the debug version of a package. We're mostly interested
- // in improving speed for development iteration loops, which usually use
- // debug mode.
- var depsDir = p.join('.pub', 'deps', 'debug');
-
- var dependenciesToPrecompile = packageGraph.packages.values
- .where((package) {
- if (package.pubspec.transformers.isEmpty) return false;
- if (packageGraph.isPackageMutable(package.name)) return false;
- if (!dirExists(p.join(depsDir, package.name))) return true;
- if (changed == null) return true;
-
- /// Only recompile [package] if any of its transitive dependencies have
- /// changed. We check all transitive dependencies because it's possible
- /// that a transformer makes decisions based on their contents.
- return overlaps(
- packageGraph.transitiveDependencies(package.name)
- .map((package) => package.name).toSet(),
- changed);
- }).map((package) => package.name).toSet();
-
- if (dirExists(depsDir)) {
- // Delete any cached dependencies that are going to be recached.
- for (var package in dependenciesToPrecompile) {
- deleteEntry(p.join(depsDir, package));
- }
-
- // Also delete any cached dependencies that should no longer be cached.
- for (var subdir in listDir(depsDir)) {
- var package = packageGraph.packages[p.basename(subdir)];
- if (package == null || package.pubspec.transformers.isEmpty ||
- packageGraph.isPackageMutable(package.name)) {
- deleteEntry(subdir);
- }
- }
- }
-
+ var dependenciesToPrecompile = _dependenciesToPrecompile(changed: changed);
+ _deletePrecompiledDependencies(dependenciesToPrecompile);
if (dependenciesToPrecompile.isEmpty) return;
try {
@@ -265,7 +251,7 @@ class Entrypoint {
if (!dependenciesToPrecompile.contains(asset.id.package)) return;
var destPath = p.join(
- depsDir, asset.id.package, p.fromUri(asset.id.path));
+ _precompiledDepsPath, asset.id.package, p.fromUri(asset.id.path));
ensureDir(p.dirname(destPath));
await createFileFromStream(asset.read(), destPath);
}));
@@ -278,57 +264,78 @@ class Entrypoint {
// assets (issue 19491), catch and handle compilation errors on a
// per-package basis.
for (var package in dependenciesToPrecompile) {
- deleteEntry(p.join(depsDir, package));
+ deleteEntry(p.join(_precompiledDepsPath, package));
}
rethrow;
}
}
- /// Precompiles all executables from dependencies that don't transitively
- /// depend on [this] or on a path dependency.
- Future precompileExecutables({Iterable<String> changed}) async {
- if (changed != null) changed = changed.toSet();
+ /// Returns the set of dependencies that need to be precompiled.
+ ///
+ /// If [changed] is passed, only dependencies whose contents might be changed
+ /// if one of the given packages changes will be returned.
+ Set<String> _dependenciesToPrecompile({Iterable<String> changed}) {
+ return packageGraph.packages.values.where((package) {
+ if (package.pubspec.transformers.isEmpty) return false;
+ if (packageGraph.isPackageMutable(package.name)) return false;
+ if (!dirExists(p.join(_precompiledDepsPath, package.name))) return true;
+ if (changed == null) return true;
- var binDir = p.join('.pub', 'bin');
- var sdkVersionPath = p.join(binDir, 'sdk-version');
+ /// Only recompile [package] if any of its transitive dependencies have
+ /// changed. We check all transitive dependencies because it's possible
+ /// that a transformer makes decisions based on their contents.
+ return overlaps(
+ packageGraph.transitiveDependencies(package.name)
+ .map((package) => package.name).toSet(),
+ changed);
+ }).map((package) => package.name).toSet();
+ }
- // If the existing executable was compiled with a different SDK, we need to
- // recompile regardless of what changed.
- // TODO(nweiz): Use the VM to check this when issue 20802 is fixed.
- var sdkMatches = fileExists(sdkVersionPath) &&
- readTextFile(sdkVersionPath) == "${sdk.version}\n";
- if (!sdkMatches) changed = null;
+ /// Deletes outdated precompiled dependencies.
+ ///
+ /// This deletes the precompilations of all packages in [packages], as well as
+ /// any packages that are now untransformed or mutable.
+ void _deletePrecompiledDependencies([Iterable<String> packages]) {
+ if (!dirExists(_precompiledDepsPath)) return;
+
+ // Delete any cached dependencies that are going to be recached.
+ packages ??= [];
+ for (var package in packages) {
+ var path = p.join(_precompiledDepsPath, package);
+ if (dirExists(path)) deleteEntry(path);
+ }
- // Clean out any outdated snapshots.
- if (dirExists(binDir)) {
- for (var entry in listDir(binDir)) {
- if (!dirExists(entry)) continue;
-
- var package = p.basename(entry);
- if (!packageGraph.packages.containsKey(package) ||
- packageGraph.isPackageMutable(package)) {
- deleteEntry(entry);
- }
+ // Also delete any cached dependencies that should no longer be cached.
+ for (var subdir in listDir(_precompiledDepsPath)) {
+ var package = packageGraph.packages[p.basename(subdir)];
+ if (package == null || package.pubspec.transformers.isEmpty ||
+ packageGraph.isPackageMutable(package.name)) {
+ deleteEntry(subdir);
}
}
+ }
+
+ /// Precompiles all executables from dependencies that don't transitively
+ /// depend on [this] or on a path dependency.
+ Future precompileExecutables({Iterable<String> changed}) async {
+ _deleteExecutableSnapshots(changed: changed);
var executables = new Map.fromIterable(root.immediateDependencies,
key: (dep) => dep.name,
- value: (dep) => _executablesForPackage(dep.name, changed));
+ value: (dep) => _executablesForPackage(dep.name));
for (var package in executables.keys.toList()) {
if (executables[package].isEmpty) executables.remove(package);
}
- if (!sdkMatches) deleteEntry(binDir);
if (executables.isEmpty) return;
await log.progress("Precompiling executables", () async {
- ensureDir(binDir);
+ ensureDir(_snapshotPath);
// Make sure there's a trailing newline so our version file matches the
// SDK's.
- writeTextFile(sdkVersionPath, "${sdk.version}\n");
+ writeTextFile(p.join(_snapshotPath, 'sdk-version'), "${sdk.version}\n");
var packagesToLoad =
unionAll(executables.keys.map(packageGraph.transitiveDependencies))
@@ -344,7 +351,7 @@ class Entrypoint {
});
await waitAndPrintErrors(executables.keys.map((package) async {
- var dir = p.join(binDir, package);
+ var dir = p.join(_snapshotPath, package);
cleanDir(dir);
await environment.precompileExecutables(package, dir,
executableIds: executables[package]);
@@ -352,13 +359,47 @@ class Entrypoint {
});
}
+ /// Deletes outdated cached executable snapshots.
+ ///
+ /// If [changed] is passed, only dependencies whose contents might be changed
+ /// if one of the given packages changes will have their executables deleted.
+ void _deleteExecutableSnapshots({Iterable<String> changed}) {
+ if (!dirExists(_snapshotPath)) return;
+
+ // If we don't know what changed, we can't safely re-use any snapshots.
+ if (changed == null) {
+ deleteEntry(_snapshotPath);
+ return;
+ }
+ changed = changed.toSet();
+
+ // If the existing executable was compiled with a different SDK, we need to
+ // recompile regardless of what changed.
+ // TODO(nweiz): Use the VM to check this when issue 20802 is fixed.
+ var sdkVersionPath = p.join(_snapshotPath, 'sdk-version');
+ if (!fileExists(sdkVersionPath) ||
+ readTextFile(sdkVersionPath) != "${sdk.version}\n") {
+ deleteEntry(_snapshotPath);
+ return;
+ }
+
+ // Clean out any outdated snapshots.
+ for (var entry in listDir(_snapshotPath)) {
+ if (!dirExists(entry)) continue;
+
+ var package = p.basename(entry);
+ if (!packageGraph.packages.containsKey(package) ||
+ packageGraph.isPackageMutable(package) ||
+ packageGraph.transitiveDependencies(package)
+ .any((dep) => changed.contains(dep.name))) {
+ deleteEntry(entry);
+ }
+ }
+ }
+
/// Returns the list of all executable assets for [packageName] that should be
/// precompiled.
- ///
- /// If [changed] isn't `null`, executables for [packageName] will only be
- /// compiled if they might depend on a package in [changed].
- List<AssetId> _executablesForPackage(String packageName,
- Set<String> changed) {
+ List<AssetId> _executablesForPackage(String packageName) {
var package = packageGraph.packages[packageName];
var binDir = package.path('bin');
if (!dirExists(binDir)) return [];
@@ -366,21 +407,15 @@ class Entrypoint {
var executables = package.executableIds;
- // If we don't know which packages were changed, always precompile the
- // executables.
- if (changed == null) return executables;
-
- // If any of the package's dependencies changed, recompile the executables.
- if (packageGraph.transitiveDependencies(packageName)
- .any((package) => changed.contains(package.name))) {
- return executables;
- }
-
- // If any executables don't exist, precompile them regardless of what
- // changed. Since we delete the bin directory before recompiling, we need to
- // recompile all executables.
+ // If any executables don't exist, recompile all executables.
+ //
+ // Normally, [_deleteExecutableSnapshots] will ensure that all the outdated
+ // executable directories will be deleted, any checking for any non-existent
+ // executable will save us a few IO operations over checking each one. If
+ // some executables do exist and some do not, the directory is corrupted and
+ // it's good to start from scratch anyway.
var executablesExist = executables.every((executable) =>
- fileExists(p.join('.pub', 'bin', packageName,
+ fileExists(p.join(_snapshotPath, packageName,
"${p.url.basename(executable.path)}.snapshot")));
if (!executablesExist) return executables;
« no previous file with comments | « lib/src/command/upgrade.dart ('k') | test/get/cache_transformed_dependency_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698