xworkmate-app/lib/runtime/go_core.dart
2026-04-11 14:45:50 +08:00

94 lines
2.6 KiB
Dart

import 'dart:io';
enum GoCoreLaunchSource { buildArtifact }
class GoCoreLaunch {
const GoCoreLaunch({
required this.executable,
required this.source,
this.arguments = const <String>[],
this.workingDirectory,
});
final String executable;
final GoCoreLaunchSource source;
final List<String> arguments;
final String? workingDirectory;
}
typedef GoCoreBinaryExistsResolver = Future<bool> Function(String command);
class GoCoreLocator {
GoCoreLocator({
GoCoreBinaryExistsResolver? binaryExistsResolver,
String? workspaceRoot,
String Function()? resolvedExecutableResolver,
}) : _binaryExistsResolver = binaryExistsResolver,
_workspaceRoot = workspaceRoot,
_resolvedExecutableResolver = resolvedExecutableResolver;
final GoCoreBinaryExistsResolver? _binaryExistsResolver;
final String? _workspaceRoot;
final String Function()? _resolvedExecutableResolver;
Future<GoCoreLaunch?> locate() async {
for (final root in _candidateRoots()) {
final path = '$root/build/bin/xworkmate-go-core';
if (await _binaryExists(path)) {
return GoCoreLaunch(
executable: path,
source: GoCoreLaunchSource.buildArtifact,
);
}
}
return null;
}
Future<bool> isAvailable() async => await locate() != null;
List<String> _candidateRoots() {
final roots = <String>{};
final explicitRoot = _workspaceRoot?.trim() ?? '';
if (explicitRoot.isNotEmpty) {
roots.add(explicitRoot);
roots.addAll(_ancestorPaths(Directory(explicitRoot)));
}
final currentPath = Directory.current.path.trim();
if (currentPath.isNotEmpty) {
roots.add(currentPath);
roots.addAll(_ancestorPaths(Directory(currentPath)));
}
final resolvedExecutable =
(_resolvedExecutableResolver?.call() ?? Platform.resolvedExecutable)
.trim();
if (resolvedExecutable.isNotEmpty) {
final executableDirectory = File(resolvedExecutable).parent;
roots.add(executableDirectory.path);
roots.addAll(_ancestorPaths(executableDirectory));
}
return roots
.where((path) => path.trim().isNotEmpty)
.toList(growable: false);
}
List<String> _ancestorPaths(Directory start) {
final ancestors = <String>[];
var current = start.absolute;
while (true) {
final parent = current.parent;
if (parent.path == current.path) {
break;
}
ancestors.add(parent.path);
current = parent;
}
return ancestors;
}
Future<bool> _binaryExists(String command) async =>
(_binaryExistsResolver?.call(command)) ?? File(command).exists();
}