Skip to content

Commit 3335c31

Browse files
authored
better support rebuilds after package graph updates (#137)
When starting up we now catch the `PackageNotFoundException` and treat that as a delete. Added an e2e_example which creates a fake packages directory for all dependencies to validate the behavior.
1 parent ebf3b19 commit 3335c31

File tree

5 files changed

+62
-6
lines changed

5 files changed

+62
-6
lines changed

e2e_example/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
**/*.txt.copy
2+
web/_packages
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4+
import 'dart:async';
5+
6+
import 'package:path/path.dart' as p;
7+
8+
import 'package:build/build.dart';
9+
import 'package:build/src/generate/input_set.dart';
10+
import 'package:build/src/generate/phase.dart';
11+
12+
// Makes copies of things!
13+
class PackagesDirBuilder extends Builder {
14+
final String outputDir;
15+
final String outputPackage;
16+
17+
PackagesDirBuilder(this.outputPackage, this.outputDir);
18+
19+
@override
20+
Future build(BuildStep buildStep) async {
21+
var input = buildStep.input;
22+
var copy = new Asset(_copiedAssetId(input.id), input.stringContents);
23+
await buildStep.writeAsString(copy);
24+
}
25+
26+
@override
27+
List<AssetId> declareOutputs(AssetId inputId) => [_copiedAssetId(inputId)];
28+
29+
static void addPhases(PhaseGroup group, PackageGraph graph) {
30+
var builder = new PackagesDirBuilder(graph.root.name, 'web');
31+
var phase = group.newPhase();
32+
for (var package in graph.allPackages.values) {
33+
phase.addAction(builder, new InputSet(package.name, ['lib/**']));
34+
}
35+
}
36+
37+
AssetId _copiedAssetId(AssetId inputId) => new AssetId(
38+
outputPackage,
39+
// Creating a folder actually called `packages` breaks things.
40+
p.join(outputDir, '_packages', inputId.package,
41+
inputId.path.replaceFirst('lib/', '')));
42+
}

e2e_example/tool/watch.dart

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,20 @@ import 'dart:async';
66
import 'package:build/build.dart';
77

88
import 'package:e2e_example/copy_builder.dart';
9+
import 'package:e2e_example/packages_dir_builder.dart';
910

1011
Future main() async {
11-
/// Builds a full package dependency graph for the current package.
12+
// Builds a full package dependency graph for the current package.
1213
var graph = new PackageGraph.forThisPackage();
1314
var phases = new PhaseGroup();
1415

15-
/// Give [Builder]s access to a [PackageGraph] so they can choose which
16-
/// packages to run on. This simplifies user code a lot, and helps to mitigate
17-
/// the transitive deps issue.
16+
// Give [Builder]s access to a [PackageGraph] so they can choose which
17+
// packages to run on. This simplifies user code a lot, and helps to mitigate
18+
// the transitive deps issue.
1819
CopyBuilder.addPhases(phases, graph);
1920

21+
// Adds all the phases necessary to copy all files into a fake packages dir!
22+
PackagesDirBuilder.addPhases(phases, graph);
23+
2024
watch(phases);
2125
}

lib/src/asset/file_based.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,17 @@ class FileBasedAssetReader implements AssetReader {
4747
var packageNode = packageGraph[inputSet.package];
4848
if (packageNode == null) {
4949
throw new ArgumentError(
50-
"Could not find inputSet.package '${inputSet.package}'.");
50+
"Could not find package '${inputSet.package}' which was listed as "
51+
"an input. Please ensure you have that package in your deps, or "
52+
"remove it from your input sets.");
5153
}
5254
var packagePath = packageNode.location.toFilePath();
5355
for (var glob in inputSet.globs) {
5456
var fileStream = glob.list(followLinks: false, root: packagePath).where(
5557
(e) => e is File && !ignoredDirs.contains(path.split(e.path)[1]));
5658
await for (var entity in fileStream) {
59+
// TODO(jakemac): Where do these files come from???
60+
if (path.basename(entity.path).startsWith('._')) continue;
5761
var id = _fileToAssetId(entity, packageNode);
5862
if (!seenAssets.add(id)) continue;
5963
yield id;

lib/src/generate/build_impl.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,12 @@ class BuildImpl {
256256
node is! GeneratedAssetNode ||
257257
(node as GeneratedAssetNode).wasOutput)
258258
.map((node) async {
259-
var exists = await _reader.hasInput(node.id);
259+
bool exists;
260+
try {
261+
exists = await _reader.hasInput(node.id);
262+
} on PackageNotFoundException catch(_) {
263+
exists = false;
264+
}
260265
if (!exists) {
261266
updates[node.id] = ChangeType.REMOVE;
262267
return;

0 commit comments

Comments
 (0)