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