blob: c9e3103231129922ecf08c7ecfda8db93985166d [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'dart:io' show ProcessStartMode, SYSTEM_ENCODING;
import 'manifest_entry.dart';
/// Gets a `ProcessStartMode` value by its string name.
ProcessStartMode _getProcessStartMode(String value) {
if (value != null) {
for (ProcessStartMode mode in ProcessStartMode.values) {
if (mode.toString() == value) {
return mode;
}
}
throw new FormatException('Invalid value for mode: $value');
}
return null;
}
/// Gets an `Encoding` instance by the encoding name.
Encoding _getEncoding(String encoding) {
if (encoding == 'system') {
return SYSTEM_ENCODING;
} else if (encoding != null) {
return Encoding.getByName(encoding);
}
return null;
}
/// An entry in the process invocation manifest for running an executable.
class RunManifestEntry extends ManifestEntry {
@override
final String type = 'run';
/// The process id.
final int pid;
/// The base file name for this entry. `stdout` and `stderr` files for this
/// process will be serialized in the recording directory as
/// `$basename.stdout` and `$basename.stderr`, respectively.
final String basename;
/// The command that was run. The first element is the executable, and the
/// remaining elements are the arguments to the executable.
final List<String> command;
/// The process' working directory when it was spawned.
final String workingDirectory;
/// The environment variables that were passed to the process.
final Map<String, String> environment;
/// Whether the invoker's environment was made available to the process.
final bool includeParentEnvironment;
/// Whether the process was spawned through a system shell.
final bool runInShell;
/// The mode with which the process was spawned.
final ProcessStartMode mode;
/// The encoding used for the `stdout` of the process.
final Encoding stdoutEncoding;
/// The encoding used for the `stderr` of the process.
final Encoding stderrEncoding;
/// The exit code of the process.
int exitCode;
/// Creates a new manifest entry with the given properties.
RunManifestEntry({
this.pid,
this.basename,
this.command,
this.workingDirectory,
this.environment,
this.includeParentEnvironment,
this.runInShell,
this.mode,
this.stdoutEncoding,
this.stderrEncoding,
this.exitCode,
});
/// Creates a new manifest entry populated with the specified JSON [data].
///
/// If any required fields are missing from the JSON data, this will throw
/// a [FormatException].
factory RunManifestEntry.fromJson(Map<String, dynamic> data) {
checkRequiredField(data, 'pid');
checkRequiredField(data, 'basename');
checkRequiredField(data, 'command');
RunManifestEntry entry = new RunManifestEntry(
pid: data['pid'],
basename: data['basename'],
command: data['command'],
workingDirectory: data['workingDirectory'],
environment: data['environment'],
includeParentEnvironment: data['includeParentEnvironment'],
runInShell: data['runInShell'],
mode: _getProcessStartMode(data['mode']),
stdoutEncoding: _getEncoding(data['stdoutEncoding']),
stderrEncoding: _getEncoding(data['stderrEncoding']),
exitCode: data['exitCode'],
);
entry.daemon = data['daemon'];
entry.notResponding = data['notResponding'];
return entry;
}
/// The executable that was invoked.
String get executable => command.first;
/// The arguments that were passed to [executable].
List<String> get arguments => command.skip(1).toList();
/// Indicates that the process is a daemon.
bool get daemon => _daemon;
bool _daemon = false;
set daemon(bool value) => _daemon = value ?? false;
/// Indicates that the process did not respond to `SIGTERM`.
bool get notResponding => _notResponding;
bool _notResponding = false;
set notResponding(bool value) => _notResponding = value ?? false;
/// Returns a JSON-encodable representation of this manifest entry.
@override
Map<String, dynamic> toJson() => new JsonBuilder()
.add('pid', pid)
.add('basename', basename)
.add('command', command)
.add('workingDirectory', workingDirectory)
.add('environment', environment)
.add('includeParentEnvironment', includeParentEnvironment)
.add('runInShell', runInShell)
.add('mode', mode, () => mode.toString())
.add('stdoutEncoding', stdoutEncoding, () => stdoutEncoding.name)
.add('stderrEncoding', stderrEncoding, () => stderrEncoding.name)
.add('daemon', daemon)
.add('notResponding', notResponding)
.add('exitCode', exitCode)
.entry;
}