in build_runner/lib/src/entrypoint/run_script.dart [77:194]
FutureOr<int> _run(SharedOptions options) async {
var logSubscription =
Logger.root.onRecord.listen(stdIOLogListener(verbose: options.verbose));
var argResults = this.argResults!;
try {
// Ensure that the user passed the name of a file to run.
if (argResults.rest.isEmpty) {
logger
..severe('Must specify an executable to run.')
..severe(usage);
return ExitCode.usage.code;
}
var scriptName = argResults.rest[0];
var passedArgs = argResults.rest.skip(1).toList();
// Ensure the extension is .dart.
if (p.extension(scriptName) != '.dart') {
logger.severe('$scriptName is not a valid Dart file '
'and cannot be run in the VM.');
return ExitCode.usage.code;
}
// Create a temporary directory in which to execute the script.
var tempPath = Directory.systemTemp
.createTempSync('build_runner_run_script')
.absolute
.uri
.toFilePath();
// Create two ReceivePorts, so that we can quit when the isolate is done.
//
// Define these before starting the isolate, so that we can close
// them if there is a spawn exception.
ReceivePort? onExit, onError;
// Use a completer to determine the exit code.
var exitCodeCompleter = Completer<int>();
try {
var buildDirs = (options.buildDirs)
..add(BuildDirectory('',
outputLocation: OutputLocation(tempPath,
useSymlinks: options.outputSymlinksOnly, hoist: false)));
var result = await build(
builderApplications,
deleteFilesByDefault: options.deleteFilesByDefault,
enableLowResourcesMode: options.enableLowResourcesMode,
configKey: options.configKey,
buildDirs: buildDirs,
packageGraph: packageGraph,
verbose: options.verbose,
builderConfigOverrides: options.builderConfigOverrides,
isReleaseBuild: options.isReleaseBuild,
trackPerformance: options.trackPerformance,
skipBuildScriptCheck: options.skipBuildScriptCheck,
logPerformanceDir: options.logPerformanceDir,
buildFilters: options.buildFilters,
);
if (result.status == BuildStatus.failure) {
logger.warning('Skipping script run due to build failure');
return result.failureType?.exitCode ?? 1;
}
// Find the path of the script to run.
var scriptPath = p.join(tempPath, scriptName);
var packageConfigPath = p.join(tempPath, '.packages');
onExit = ReceivePort();
onError = ReceivePort();
// Cleanup after exit.
onExit.listen((_) {
// If no error was thrown, return 0.
if (!exitCodeCompleter.isCompleted) exitCodeCompleter.complete(0);
});
// On an error, kill the isolate, and log the error.
onError.listen((e) {
onExit?.close();
onError?.close();
logger.severe('Unhandled error from script: $scriptName', e[0],
StackTrace.fromString(e[1].toString()));
if (!exitCodeCompleter.isCompleted) exitCodeCompleter.complete(1);
});
await Isolate.spawnUri(
p.toUri(scriptPath),
passedArgs,
null,
errorsAreFatal: true,
onExit: onExit.sendPort,
onError: onError.sendPort,
packageConfig: p.toUri(packageConfigPath),
);
return await exitCodeCompleter.future;
} on IsolateSpawnException catch (e) {
logger.severe(
'Could not spawn isolate. Ensure that your file is in a valid directory (i.e. "bin", "benchmark", "example", "test", "tool").',
e);
return ExitCode.ioError.code;
} finally {
// Clean up the output dir.
var dir = Directory(tempPath);
if (await dir.exists()) await dir.delete(recursive: true);
onExit?.close();
onError?.close();
if (!exitCodeCompleter.isCompleted) {
exitCodeCompleter.complete(ExitCode.success.code);
}
}
} finally {
await logSubscription.cancel();
}
}