@@ -8,14 +8,12 @@ import 'dart:convert';
88import 'package:analyzer/dart/analysis/utilities.dart' ;
99import 'package:analyzer/dart/ast/ast.dart' ;
1010import 'package:build/build.dart' ;
11- import 'package:built_collection/built_collection.dart' ;
1211import 'package:crypto/crypto.dart' ;
1312import 'package:glob/glob.dart' ;
1413import 'package:path/path.dart' as p;
1514import 'package:watcher/watcher.dart' ;
1615
1716import '../bootstrap/build_process_state.dart' ;
18- import '../build_plan/build_directory.dart' ;
1917import '../build_plan/build_options.dart' ;
2018import '../build_plan/build_phases.dart' ;
2119import '../build_plan/build_plan.dart' ;
@@ -24,6 +22,7 @@ import '../build_plan/phase.dart';
2422import '../build_plan/target_graph.dart' ;
2523import '../build_plan/testing_overrides.dart' ;
2624import '../constants.dart' ;
25+ import '../io/build_output_reader.dart' ;
2726import '../io/create_merged_dir.dart' ;
2827import '../io/reader_writer.dart' ;
2928import '../logging/build_log.dart' ;
@@ -33,12 +32,10 @@ import 'asset_graph/node.dart';
3332import 'asset_graph/post_process_build_step_id.dart' ;
3433import 'build_dirs.dart' ;
3534import 'build_result.dart' ;
36- import 'finalized_assets_view.dart' ;
3735import 'input_tracker.dart' ;
3836import 'library_cycle_graph/asset_deps_loader.dart' ;
3937import 'library_cycle_graph/library_cycle_graph.dart' ;
4038import 'library_cycle_graph/library_cycle_graph_loader.dart' ;
41- import 'optional_output_tracker.dart' ;
4239import 'performance_tracker.dart' ;
4340import 'performance_tracking_resolvers.dart' ;
4441import 'resolver/analysis_driver_model.dart' ;
@@ -110,6 +107,9 @@ class Build {
110107 /// transitive source.
111108 final Map <LibraryCycleGraph , bool > changedGraphs = Map .identity ();
112109
110+ /// The build output.
111+ final BuildOutputReader buildOutputReader;
112+
113113 Build ({
114114 required this .buildPlan,
115115 required this .readerWriter,
@@ -122,7 +122,12 @@ class Build {
122122 previousDepsLoader =
123123 assetGraph.previousPhasedAssetDeps == null
124124 ? null
125- : AssetDepsLoader .fromDeps (assetGraph.previousPhasedAssetDeps! );
125+ : AssetDepsLoader .fromDeps (assetGraph.previousPhasedAssetDeps! ),
126+ buildOutputReader = BuildOutputReader (
127+ buildPlan: buildPlan,
128+ readerWriter: readerWriter,
129+ assetGraph: assetGraph,
130+ );
126131
127132 BuildOptions get buildOptions => buildPlan.buildOptions;
128133 TestingOverrides get testingOverrides => buildPlan.testingOverrides;
@@ -138,13 +143,6 @@ class Build {
138143 (b) => b..rootPackageName = packageGraph.root.name,
139144 );
140145 var result = await _safeBuild (updates);
141- final optionalOutputTracker = OptionalOutputTracker (
142- assetGraph,
143- targetGraph,
144- BuildDirectory .buildPaths (buildPlan.buildOptions.buildDirs),
145- buildPlan.buildOptions.buildFilters,
146- buildPhases,
147- );
148146 if (result.status == BuildStatus .success) {
149147 final failures = < AssetNode > [];
150148 for (final output in processedOutputs) {
@@ -169,21 +167,31 @@ class Build {
169167 logger.severe (error);
170168 }
171169 }
172- result = BuildResult (
173- BuildStatus .failure,
174- result.outputs,
175- performance: result.performance,
176- );
170+ result = result.copyWith (buildStatus: BuildStatus .failure);
177171 }
178172 }
179173 readerWriter.cache.flush ();
180174 await resourceManager.disposeAll ();
181- result = await _finalizeBuild (
182- result,
183- FinalizedAssetsView (assetGraph, packageGraph, optionalOutputTracker),
184- readerWriter,
185- buildPlan.buildOptions.buildDirs,
186- );
175+
176+ // If requested, create output directories. If that fails, fail the build.
177+ if (buildPlan.buildOptions.buildDirs.any (
178+ (target) => target.outputLocation? .path.isNotEmpty ?? false ,
179+ ) &&
180+ result.status == BuildStatus .success) {
181+ if (! await createMergedOutputDirectories (
182+ packageGraph: packageGraph,
183+ outputSymlinksOnly: buildOptions.outputSymlinksOnly,
184+ buildDirs: buildOptions.buildDirs,
185+ buildOutputReader: buildOutputReader,
186+ readerWriter: readerWriter,
187+ )) {
188+ result = result.copyWith (
189+ buildStatus: BuildStatus .failure,
190+ failureType: FailureType .cantCreate,
191+ );
192+ }
193+ }
194+
187195 _resolvers.reset ();
188196 buildLog.finishBuild (
189197 result: result.status == BuildStatus .success,
@@ -282,7 +290,13 @@ class Build {
282290 buildLog.error (
283291 buildLog.renderThrowable ('Unhandled build failure!' , e, st),
284292 );
285- done.complete (BuildResult (BuildStatus .failure, []));
293+ done.complete (
294+ BuildResult (
295+ BuildStatus .failure,
296+ [],
297+ buildOutputReader: buildOutputReader,
298+ ),
299+ );
286300 }
287301 },
288302 );
@@ -370,11 +384,13 @@ class Build {
370384 (Future <Iterable <AssetId >> lazyOuts) async =>
371385 outputs.addAll (await lazyOuts),
372386 );
387+
373388 // Assume success, `_assetGraph.failedOutputs` will be checked later.
374389 return BuildResult (
375390 BuildStatus .success,
376391 outputs,
377392 performance: performanceTracker,
393+ buildOutputReader: buildOutputReader,
378394 );
379395 });
380396 }
@@ -394,7 +410,7 @@ class Build {
394410 .toList (growable: false )) {
395411 if (! shouldBuildForDirs (
396412 node.id,
397- buildDirs: BuildDirectory . buildPaths ( buildPlan.buildOptions.buildDirs) ,
413+ buildDirs: buildPlan.buildOptions.buildDirs,
398414 buildFilters: buildPlan.buildOptions.buildFilters,
399415 phase: phase,
400416 targetGraph: targetGraph,
@@ -1211,60 +1227,6 @@ class Build {
12111227 }
12121228
12131229 Future _delete (AssetId id) => readerWriter.delete (id);
1214-
1215- /// Invoked after each build, can modify the [BuildResult] in any way, even
1216- /// converting it to a failure.
1217- ///
1218- /// The [finalizedAssetsView] can only be used until the returned [Future]
1219- /// completes, it will expire afterwords since it can no longer guarantee a
1220- /// consistent state.
1221- ///
1222- /// By default this returns the original result.
1223- ///
1224- /// Any operation may be performed, as determined by environment.
1225- Future <BuildResult > _finalizeBuild (
1226- BuildResult buildResult,
1227- FinalizedAssetsView finalizedAssetsView,
1228- ReaderWriter readerWriter,
1229- BuiltSet <BuildDirectory > buildDirs,
1230- ) async {
1231- if (testingOverrides.finalizeBuild != null ) {
1232- return testingOverrides.finalizeBuild !(
1233- buildResult,
1234- finalizedAssetsView,
1235- readerWriter,
1236- buildDirs,
1237- );
1238- }
1239- if (buildDirs.any (
1240- (target) => target.outputLocation? .path.isNotEmpty ?? false ,
1241- ) &&
1242- buildResult.status == BuildStatus .success) {
1243- if (! await createMergedOutputDirectories (
1244- buildDirs,
1245- packageGraph,
1246- readerWriter,
1247- finalizedAssetsView,
1248- buildOptions.outputSymlinksOnly,
1249- )) {
1250- return _convertToFailure (
1251- buildResult,
1252- failureType: FailureType .cantCreate,
1253- );
1254- }
1255- }
1256- return buildResult;
1257- }
12581230}
12591231
12601232String _twoDigits (int n) => '$n ' .padLeft (2 , '0' );
1261-
1262- BuildResult _convertToFailure (
1263- BuildResult previous, {
1264- FailureType ? failureType,
1265- }) => BuildResult (
1266- BuildStatus .failure,
1267- previous.outputs,
1268- performance: previous.performance,
1269- failureType: failureType,
1270- );
0 commit comments