Unverified Commit e85655c4 authored by stuartmorgan's avatar stuartmorgan Committed by GitHub

Specify encoding for vswhere output (#59607)

On Windows, Process.run assumes the output uses the system codepage by default. This allows specifying it in our wrapper, and sets the encoding for vswhere to UTF-8 since we're passing a flag that forces it to use UTF-8 output.

Fixes #53515
parent 32be39bf
......@@ -236,6 +236,7 @@ abstract class ProcessUtils {
String workingDirectory,
Map<String, String> environment,
bool allowReentrantFlutter = false,
Encoding encoding = systemEncoding,
});
/// This runs the command in the background from the specified working
......@@ -412,12 +413,15 @@ class _DefaultProcessUtils implements ProcessUtils {
String workingDirectory,
Map<String, String> environment,
bool allowReentrantFlutter = false,
Encoding encoding = systemEncoding,
}) {
_traceCommand(cmd, workingDirectory: workingDirectory);
final ProcessResult results = _processManager.runSync(
cmd,
workingDirectory: workingDirectory,
environment: _environment(allowReentrantFlutter, environment),
stderrEncoding: encoding,
stdoutEncoding: encoding,
);
final RunResult runResult = RunResult(results, cmd);
......
......@@ -283,7 +283,7 @@ class VisualStudio {
...defaultArguments,
...?additionalArguments,
...?requirementArguments,
]);
], encoding: utf8);
if (whereResult.exitCode == 0) {
final List<Map<String, dynamic>> installations =
(json.decode(whereResult.stdout) as List<dynamic>).cast<Map<String, dynamic>>();
......
......@@ -236,6 +236,8 @@ void main() {
any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
stdoutEncoding: utf8,
stderrEncoding: utf8,
)).thenThrow(const ProcessException('vswhere', <String>[]));
final VisualStudio visualStudio = VisualStudio(
logger: BufferLogger.test(),
......@@ -253,6 +255,8 @@ void main() {
any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
stdoutEncoding: utf8,
stderrEncoding: utf8,
)).thenThrow(const ProcessException('vswhere', <String>[]));
final VisualStudio visualStudio = VisualStudio(
logger: BufferLogger.test(),
......@@ -271,6 +275,8 @@ void main() {
any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
stdoutEncoding: utf8,
stderrEncoding: utf8,
)).thenAnswer((Invocation invocation) {
return FakeProcessResult(exitCode: 1, stderr: '', stdout: '');
});
......
......@@ -22,6 +22,7 @@ class FakeCommand {
@required this.command,
this.workingDirectory,
this.environment,
this.encoding,
this.duration = const Duration(),
this.onRun,
this.exitCode = 0,
......@@ -51,6 +52,12 @@ class FakeCommand {
/// value that matches the one given here for the [FakeCommand] to match.
final Map<String, String> environment;
/// The stdout and stderr encoding that must be matched for this [FakeCommand]
/// to be considered correct.
///
/// If this is null, then the encodings are ignored.
final Encoding encoding;
/// The time to allow to elapse before returning the [exitCode], if this command
/// is "executed".
///
......@@ -87,7 +94,12 @@ class FakeCommand {
/// [FakeProcess].
final IOSink stdin;
void _matches(List<String> command, String workingDirectory, Map<String, String> environment) {
void _matches(
List<String> command,
String workingDirectory,
Map<String, String> environment,
Encoding encoding,
) {
expect(command, equals(this.command));
if (this.workingDirectory != null) {
expect(this.workingDirectory, workingDirectory);
......@@ -95,6 +107,9 @@ class FakeCommand {
if (this.environment != null) {
expect(this.environment, environment);
}
if (this.encoding != null) {
expect(this.encoding, encoding);
}
}
}
......@@ -190,13 +205,23 @@ abstract class FakeProcessManager implements ProcessManager {
bool get hasRemainingExpectations;
@protected
FakeCommand findCommand(List<String> command, String workingDirectory, Map<String, String> environment);
FakeCommand findCommand(
List<String> command,
String workingDirectory,
Map<String, String> environment,
Encoding encoding,
);
int _pid = 9999;
_FakeProcess _runCommand(List<String> command, String workingDirectory, Map<String, String> environment) {
_FakeProcess _runCommand(
List<String> command,
String workingDirectory,
Map<String, String> environment,
Encoding encoding,
) {
_pid += 1;
final FakeCommand fakeCommand = findCommand(command, workingDirectory, environment);
final FakeCommand fakeCommand = findCommand(command, workingDirectory, environment, encoding);
return _FakeProcess(
fakeCommand.exitCode,
fakeCommand.duration,
......@@ -217,7 +242,7 @@ abstract class FakeProcessManager implements ProcessManager {
bool includeParentEnvironment = true, // ignored
bool runInShell = false, // ignored
ProcessStartMode mode = ProcessStartMode.normal, // ignored
}) async => _runCommand(command.cast<String>(), workingDirectory, environment);
}) async => _runCommand(command.cast<String>(), workingDirectory, environment, systemEncoding);
@override
Future<ProcessResult> run(
......@@ -229,7 +254,7 @@ abstract class FakeProcessManager implements ProcessManager {
Encoding stdoutEncoding = systemEncoding,
Encoding stderrEncoding = systemEncoding,
}) async {
final _FakeProcess process = _runCommand(command.cast<String>(), workingDirectory, environment);
final _FakeProcess process = _runCommand(command.cast<String>(), workingDirectory, environment, stdoutEncoding);
await process.exitCode;
return ProcessResult(
process.pid,
......@@ -249,7 +274,7 @@ abstract class FakeProcessManager implements ProcessManager {
Encoding stdoutEncoding = systemEncoding, // actual encoder is ignored
Encoding stderrEncoding = systemEncoding, // actual encoder is ignored
}) {
final _FakeProcess process = _runCommand(command.cast<String>(), workingDirectory, environment);
final _FakeProcess process = _runCommand(command.cast<String>(), workingDirectory, environment, stdoutEncoding);
return ProcessResult(
process.pid,
process._exitCode,
......@@ -272,11 +297,17 @@ class _FakeAnyProcessManager extends FakeProcessManager {
_FakeAnyProcessManager() : super._();
@override
FakeCommand findCommand(List<String> command, String workingDirectory, Map<String, String> environment) {
FakeCommand findCommand(
List<String> command,
String workingDirectory,
Map<String, String> environment,
Encoding encoding,
) {
return FakeCommand(
command: command,
workingDirectory: workingDirectory,
environment: environment,
encoding: encoding,
duration: const Duration(),
exitCode: 0,
stdout: '',
......@@ -297,12 +328,17 @@ class _SequenceProcessManager extends FakeProcessManager {
final List<FakeCommand> _commands;
@override
FakeCommand findCommand(List<String> command, String workingDirectory, Map<String, String> environment) {
FakeCommand findCommand(
List<String> command,
String workingDirectory,
Map<String, String> environment,
Encoding encoding,
) {
expect(_commands, isNotEmpty,
reason: 'ProcessManager was told to execute $command (in $workingDirectory) '
'but the FakeProcessManager.list expected no more processes.'
);
_commands.first._matches(command, workingDirectory, environment);
_commands.first._matches(command, workingDirectory, environment, encoding);
return _commands.removeAt(0);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment