blob: d80e35eb5113bf8a3c05b99cda2ed60bafd78307 [file] [log] [blame] [edit]
// Copyright 2020 The Chromium Authors. 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:async';
import 'dart:convert';
import 'dart:io';
import 'package:devtools_tool/model.dart';
import 'package:io/io.dart';
import 'package:path/path.dart' as path;
String convertProcessOutputToString(List<List<int>> output, String indent) {
String result = output.map((codes) => utf8.decode(codes)).join();
result = result.trim();
result = result
.split('\n')
.where((line) => line.isNotEmpty)
.map((line) => '$indent$line')
.join('\n');
return result;
}
abstract class DartSdkHelper {
static const commandDebugMessage = 'Consider running this command from your'
'Dart SDK directory locally to debug.';
static Future<void> fetchAndCheckoutMaster(
ProcessManager processManager,
) async {
final dartSdkLocation = localDartSdkLocation();
await processManager.runAll(
workingDirectory: dartSdkLocation,
additionalErrorMessage: commandDebugMessage,
commands: [
CliCommand('git fetch origin'),
CliCommand('git rebase-update'),
CliCommand('git checkout origin/main'),
],
);
}
}
String localDartSdkLocation() {
final localDartSdkLocation = Platform.environment['LOCAL_DART_SDK'];
if (localDartSdkLocation == null) {
throw Exception('LOCAL_DART_SDK environment variable not set. Please add '
'the following to your \'.bash_profile\' or \'.bash_rc\' file:\n'
'export LOCAL_DART_SDK=<absolute/path/to/my/dart/sdk>');
}
return localDartSdkLocation;
}
class CliCommand {
CliCommand._({
String? command,
String? exe,
List<String>? args,
this.throwOnException = true,
}) {
assert((command == null) != ((exe == null) && (args == null)));
final commandElements = command?.split(' ');
this.exe = exe ?? commandElements!.first;
this.args = args ?? commandElements!.sublist(1);
}
CliCommand(
String command, {
this.throwOnException = true,
}) : exe = command.split(' ').first,
args = command.split(' ').sublist(1);
factory CliCommand.from(
String exe,
List<String> args, {
bool throwOnException = true,
}) {
return CliCommand._(
exe: exe,
args: args,
throwOnException: throwOnException,
);
}
late final String exe;
late final List<String> args;
final bool throwOnException;
}
extension DevToolsProcessManagerExtension on ProcessManager {
Future<String> runProcess(
CliCommand command, {
String? workingDirectory,
String? additionalErrorMessage = '',
}) async {
String stdout = '';
final process = await spawn(
command.exe,
command.args,
workingDirectory: workingDirectory,
);
unawaited(
process.stdout
.transform(
utf8.decoder,
)
.forEach((x) => stdout = '$stdout$x'),
);
final code = await process.exitCode;
if (command.throwOnException && code != 0) {
throw ProcessException(
command.exe,
command.args,
'Failed with exit code: $code. $additionalErrorMessage',
code,
);
}
return stdout;
}
Future<void> runAll({
required List<CliCommand> commands,
String? workingDirectory,
String? additionalErrorMessage = '',
}) async {
for (final command in commands) {
await runProcess(
command,
workingDirectory: workingDirectory,
additionalErrorMessage: additionalErrorMessage,
);
}
}
}
String pathFromRepoRoot(String pathFromRoot) {
return path.join(DevToolsRepo.getInstance().repoPath, pathFromRoot);
}