Bundle go-core helper with macOS app and drop external CLI fallback
This commit is contained in:
parent
f574045b6f
commit
e109e43d99
@ -88,17 +88,18 @@ class ArisLlmChatClient {
|
||||
required Map<String, String> environment,
|
||||
required Map<String, dynamic> arguments,
|
||||
}) async {
|
||||
if (shouldBlockEmbeddedAgentLaunch(
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
throw UnsupportedError(
|
||||
'App Store builds do not allow launching the bundled Go core process.',
|
||||
);
|
||||
}
|
||||
final launch = await _bridgeLocator.locate();
|
||||
if (launch == null) {
|
||||
throw StateError('Go core is unavailable.');
|
||||
}
|
||||
if (shouldBlockGoCoreLaunch(
|
||||
launch,
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
throw UnsupportedError(
|
||||
'App Store builds only allow the bundled Go core helper inside the app bundle.',
|
||||
);
|
||||
}
|
||||
|
||||
final process = await _processStarter(
|
||||
launch.executable,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import '../app/app_store_policy.dart';
|
||||
import 'go_core.dart';
|
||||
|
||||
bool shouldBlockEmbeddedAgentLaunch({
|
||||
required bool isAppleHost,
|
||||
@ -9,3 +10,17 @@ bool shouldBlockEmbeddedAgentLaunch({
|
||||
enabled: enabled,
|
||||
);
|
||||
}
|
||||
|
||||
bool shouldBlockGoCoreLaunch(
|
||||
GoCoreLaunch launch, {
|
||||
required bool isAppleHost,
|
||||
bool? enabled,
|
||||
}) {
|
||||
if (!shouldApplyAppleAppStorePolicy(
|
||||
isAppleHost: isAppleHost,
|
||||
enabled: enabled,
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
return launch.source != GoCoreLaunchSource.bundledHelper;
|
||||
}
|
||||
|
||||
@ -195,15 +195,16 @@ class GoAgentCoreDesktopTransport implements GoAgentCoreClient {
|
||||
}
|
||||
|
||||
Future<Uri?> _startLocalProcess() async {
|
||||
if (shouldBlockEmbeddedAgentLaunch(
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
final launch = await _goCoreLocator.locate();
|
||||
if (launch == null) {
|
||||
return null;
|
||||
}
|
||||
if (shouldBlockGoCoreLaunch(
|
||||
launch,
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
final reservedSocket = await ServerSocket.bind(
|
||||
InternetAddress.loopbackIPv4,
|
||||
0,
|
||||
|
||||
@ -1,13 +1,20 @@
|
||||
import 'dart:io';
|
||||
|
||||
enum GoCoreLaunchSource {
|
||||
bundledHelper,
|
||||
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;
|
||||
}
|
||||
@ -33,39 +40,12 @@ class GoCoreLocator {
|
||||
return bundled;
|
||||
}
|
||||
|
||||
final override =
|
||||
(Platform.environment['XWORKMATE_GO_CORE_BIN'] ??
|
||||
Platform.environment['GO_CORE_BIN'] ??
|
||||
'')
|
||||
.trim();
|
||||
if (override.isNotEmpty && await _binaryExists(override)) {
|
||||
return GoCoreLaunch(executable: override);
|
||||
}
|
||||
|
||||
for (final candidate in <String>['xworkmate-go-core', 'go-core']) {
|
||||
if (await _binaryExists(candidate)) {
|
||||
return GoCoreLaunch(executable: candidate);
|
||||
}
|
||||
}
|
||||
|
||||
final root = (_workspaceRoot ?? Directory.current.path).trim();
|
||||
if (root.isNotEmpty) {
|
||||
for (final path in <String>[
|
||||
'$root/go/bin/xworkmate-go-core',
|
||||
'$root/go/bin/go-core',
|
||||
'$root/build/bin/xworkmate-go-core',
|
||||
]) {
|
||||
if (await File(path).exists()) {
|
||||
return GoCoreLaunch(executable: path);
|
||||
}
|
||||
}
|
||||
|
||||
final packageDirectory = Directory('$root/go/go_core');
|
||||
if (await packageDirectory.exists() && await _binaryExists('go')) {
|
||||
for (final root in _candidateRoots()) {
|
||||
final path = '$root/build/bin/xworkmate-go-core';
|
||||
if (await _binaryExists(path)) {
|
||||
return GoCoreLaunch(
|
||||
executable: 'go',
|
||||
arguments: const <String>['run', '.'],
|
||||
workingDirectory: packageDirectory.path,
|
||||
executable: path,
|
||||
source: GoCoreLaunchSource.buildArtifact,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -94,25 +74,55 @@ class GoCoreLocator {
|
||||
return null;
|
||||
}
|
||||
final bundledPath = '${contentsDirectory.path}/Helpers/xworkmate-go-core';
|
||||
if (await File(bundledPath).exists()) {
|
||||
return GoCoreLaunch(executable: bundledPath);
|
||||
if (await _binaryExists(bundledPath)) {
|
||||
return GoCoreLaunch(
|
||||
executable: bundledPath,
|
||||
source: GoCoreLaunchSource.bundledHelper,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<bool> _binaryExists(String command) async {
|
||||
final resolver = _binaryExistsResolver;
|
||||
if (resolver != null) {
|
||||
return resolver(command);
|
||||
List<String> _candidateRoots() {
|
||||
final roots = <String>{};
|
||||
final explicitRoot = _workspaceRoot?.trim() ?? '';
|
||||
if (explicitRoot.isNotEmpty) {
|
||||
roots.add(explicitRoot);
|
||||
roots.addAll(_ancestorPaths(Directory(explicitRoot)));
|
||||
}
|
||||
if (command.contains(Platform.pathSeparator)) {
|
||||
return File(command).exists();
|
||||
|
||||
final currentPath = Directory.current.path.trim();
|
||||
if (currentPath.isNotEmpty) {
|
||||
roots.add(currentPath);
|
||||
roots.addAll(_ancestorPaths(Directory(currentPath)));
|
||||
}
|
||||
final check = await Process.run(
|
||||
Platform.isWindows ? 'where' : 'which',
|
||||
<String>[command],
|
||||
runInShell: true,
|
||||
);
|
||||
return check.exitCode == 0 && '${check.stdout}'.trim().isNotEmpty;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -291,15 +291,16 @@ class GoGatewayRuntimeDesktopClient implements GatewayRuntimeSessionClient {
|
||||
}
|
||||
|
||||
Future<Uri?> _startLocalProcess() async {
|
||||
if (shouldBlockEmbeddedAgentLaunch(
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
final launch = await _goCoreLocator.locate();
|
||||
if (launch == null) {
|
||||
return null;
|
||||
}
|
||||
if (shouldBlockGoCoreLaunch(
|
||||
launch,
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
final reservedSocket = await ServerSocket.bind(
|
||||
InternetAddress.loopbackIPv4,
|
||||
0,
|
||||
|
||||
@ -132,15 +132,16 @@ class GoMultiAgentMountDesktopClient implements MultiAgentMountResolver {
|
||||
}
|
||||
|
||||
Future<Uri?> _startLocalProcess() async {
|
||||
if (shouldBlockEmbeddedAgentLaunch(
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
final launch = await _goCoreLocator.locate();
|
||||
if (launch == null) {
|
||||
return null;
|
||||
}
|
||||
if (shouldBlockGoCoreLaunch(
|
||||
launch,
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
final reservedSocket = await ServerSocket.bind(
|
||||
InternetAddress.loopbackIPv4,
|
||||
0,
|
||||
|
||||
@ -152,15 +152,16 @@ class GoRuntimeDispatchDesktopClient implements RuntimeDispatchResolver {
|
||||
}
|
||||
|
||||
Future<Uri?> _startLocalProcess() async {
|
||||
if (shouldBlockEmbeddedAgentLaunch(
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
final launch = await _goCoreLocator.locate();
|
||||
if (launch == null) {
|
||||
return null;
|
||||
}
|
||||
if (shouldBlockGoCoreLaunch(
|
||||
launch,
|
||||
isAppleHost: Platform.isIOS || Platform.isMacOS,
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
final reservedSocket = await ServerSocket.bind(
|
||||
InternetAddress.loopbackIPv4,
|
||||
0,
|
||||
|
||||
@ -248,6 +248,7 @@
|
||||
33CC10EB2044A3C60003C045 /* Resources */,
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||
A1B2C3084F0A000100000001 /* Embed Bundled Go Core Helper */,
|
||||
93B26977D4D2EC7AFAB54C8E /* [CP] Embed Pods Frameworks */,
|
||||
A1B2C3074F0A000100000001 /* Generate Missing Framework dSYMs */,
|
||||
);
|
||||
@ -432,6 +433,26 @@
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
A1B2C3084F0A000100000001 /* Embed Bundled Go Core Helper */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Embed Bundled Go Core Helper";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/bash \"${PROJECT_DIR}/../scripts/embed-go-core-helper.sh\" \"${TARGET_BUILD_DIR}/${WRAPPER_NAME}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
A1B2C3074F0A000100000001 /* Generate Missing Framework dSYMs */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
||||
33
scripts/embed-go-core-helper.sh
Executable file
33
scripts/embed-go-core-helper.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
APP_BUNDLE_PATH="${1:-${APP_BUNDLE_PATH:-}}"
|
||||
BRIDGE_BINARY_NAME="${BRIDGE_BINARY_NAME:-xworkmate-go-core}"
|
||||
BRIDGE_BUILD_PATH="${ROOT_DIR}/build/bin/${BRIDGE_BINARY_NAME}"
|
||||
|
||||
if [[ -z "$APP_BUNDLE_PATH" ]]; then
|
||||
echo "Missing app bundle path for embedded go-core helper" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$APP_BUNDLE_PATH" ]]; then
|
||||
echo "App bundle does not exist: $APP_BUNDLE_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
HELPERS_DIR="$APP_BUNDLE_PATH/Contents/Helpers"
|
||||
HELPER_PATH="$HELPERS_DIR/$BRIDGE_BINARY_NAME"
|
||||
|
||||
bash "$ROOT_DIR/scripts/build-go-core.sh"
|
||||
|
||||
mkdir -p "$HELPERS_DIR"
|
||||
ditto "$BRIDGE_BUILD_PATH" "$HELPER_PATH"
|
||||
chmod +x "$HELPER_PATH"
|
||||
|
||||
SIGN_IDENTITY="${EXPANDED_CODE_SIGN_IDENTITY:-${CODE_SIGN_IDENTITY:--}}"
|
||||
if [[ -n "$SIGN_IDENTITY" ]]; then
|
||||
codesign --force --sign "$SIGN_IDENTITY" --timestamp=none "$HELPER_PATH"
|
||||
fi
|
||||
|
||||
echo "Embedded go-core helper: $HELPER_PATH"
|
||||
@ -9,8 +9,6 @@ APP_NAME="${APP_NAME:-XWorkmate}"
|
||||
BUILD_MODE="${BUILD_MODE:-release}"
|
||||
APP_STORE_DEFINE="${APP_STORE_DEFINE:---dart-define=XWORKMATE_APP_STORE=${XWORKMATE_APP_STORE:-true}}"
|
||||
PRODUCTS_DIR_NAME="$(tr '[:lower:]' '[:upper:]' <<< "${BUILD_MODE:0:1}")${BUILD_MODE:1}"
|
||||
BRIDGE_BINARY_NAME="${BRIDGE_BINARY_NAME:-xworkmate-go-core}"
|
||||
BRIDGE_BUILD_PATH="${ROOT_DIR}/build/bin/${BRIDGE_BINARY_NAME}"
|
||||
FLUTTER_BUILD_STATE_DIR="${ROOT_DIR}/.dart_tool/flutter_build"
|
||||
MACOS_BUILD_DIR="${ROOT_DIR}/build/macos"
|
||||
NATIVE_ASSETS_DIR="${ROOT_DIR}/build/native_assets"
|
||||
@ -35,14 +33,8 @@ fi
|
||||
BUILD_APP_PATH="$APP_DIR/build/macos/Build/Products/$PRODUCTS_DIR_NAME/$APP_NAME.app"
|
||||
DIST_APP_PATH="$DIST_DIR/$APP_NAME.app"
|
||||
DIST_DMG_PATH="$DIST_DIR/$APP_NAME-$APP_VERSION.dmg"
|
||||
HELPERS_DIR="$DIST_APP_PATH/Contents/Helpers"
|
||||
HELPER_PATH="$HELPERS_DIR/$BRIDGE_BINARY_NAME"
|
||||
|
||||
mkdir -p "$DIST_DIR"
|
||||
|
||||
echo "Building bundled Go core..."
|
||||
bash "$ROOT_DIR/scripts/build-go-core.sh"
|
||||
|
||||
echo "Building $APP_NAME $APP_VERSION ($APP_BUILD) for macOS..."
|
||||
# Flutter caches native-asset installation state under .dart_tool/flutter_build,
|
||||
# but Xcode consumes the copied frameworks from build/native_assets/macos.
|
||||
@ -74,13 +66,10 @@ bash "$ROOT_DIR/scripts/check-apple-export-compliance.sh" "$BUILD_APP_PATH"
|
||||
|
||||
rm -rf "$DIST_APP_PATH" "$DIST_DMG_PATH"
|
||||
ditto "$BUILD_APP_PATH" "$DIST_APP_PATH"
|
||||
mkdir -p "$HELPERS_DIR"
|
||||
ditto "$BRIDGE_BUILD_PATH" "$HELPER_PATH"
|
||||
chmod +x "$HELPER_PATH"
|
||||
bash "$ROOT_DIR/scripts/embed-go-core-helper.sh" "$DIST_APP_PATH"
|
||||
|
||||
echo "Re-signing bundled helper and app..."
|
||||
SIGN_IDENTITY="${XWORKMATE_SIGN_IDENTITY:--}"
|
||||
codesign --force --sign "$SIGN_IDENTITY" --timestamp=none "$HELPER_PATH"
|
||||
codesign --force --deep --sign "$SIGN_IDENTITY" --preserve-metadata=entitlements,requirements,flags,runtime --timestamp=none "$DIST_APP_PATH"
|
||||
|
||||
echo "Packaging DMG..."
|
||||
|
||||
@ -113,11 +113,17 @@ void main() {
|
||||
}
|
||||
|
||||
GoCoreLocator _fixedLocator() {
|
||||
final appRoot = Directory('${Directory.systemTemp.path}/aris-llm-chat-app');
|
||||
final helpersDir = Directory('${appRoot.path}/XWorkmate.app/Contents/Helpers');
|
||||
helpersDir.createSync(recursive: true);
|
||||
final helper = File('${helpersDir.path}/xworkmate-go-core');
|
||||
if (!helper.existsSync()) {
|
||||
helper.writeAsStringSync('#!/bin/sh\nexit 0\n');
|
||||
Process.runSync('chmod', <String>['+x', helper.path]);
|
||||
}
|
||||
return GoCoreLocator(
|
||||
binaryExistsResolver: (_) async => true,
|
||||
workspaceRoot: Directory.systemTemp.path,
|
||||
resolvedExecutableResolver: () =>
|
||||
'${Directory.systemTemp.path}/XWorkmate.app/Contents/MacOS/XWorkmate',
|
||||
'${appRoot.path}/XWorkmate.app/Contents/MacOS/XWorkmate',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:xworkmate/runtime/embedded_agent_launch_policy.dart';
|
||||
import 'package:xworkmate/runtime/go_core.dart';
|
||||
|
||||
void main() {
|
||||
test('apple app store policy blocks embedded agent launches', () {
|
||||
@ -12,4 +13,28 @@ void main() {
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('apple app store policy allows only bundled go core helpers', () {
|
||||
const bundled = GoCoreLaunch(
|
||||
executable: '/Applications/XWorkmate.app/Contents/Helpers/xworkmate-go-core',
|
||||
source: GoCoreLaunchSource.bundledHelper,
|
||||
);
|
||||
const buildArtifact = GoCoreLaunch(
|
||||
executable: '/tmp/build/bin/xworkmate-go-core',
|
||||
source: GoCoreLaunchSource.buildArtifact,
|
||||
);
|
||||
|
||||
expect(
|
||||
shouldBlockGoCoreLaunch(bundled, isAppleHost: true, enabled: true),
|
||||
isFalse,
|
||||
);
|
||||
expect(
|
||||
shouldBlockGoCoreLaunch(buildArtifact, isAppleHost: true, enabled: true),
|
||||
isTrue,
|
||||
);
|
||||
expect(
|
||||
shouldBlockGoCoreLaunch(buildArtifact, isAppleHost: false, enabled: true),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -37,13 +37,14 @@ void main() {
|
||||
|
||||
expect(launch, isNotNull);
|
||||
expect(launch!.executable, helperFile.path);
|
||||
expect(launch.source, GoCoreLaunchSource.bundledHelper);
|
||||
expect(launch.arguments, isEmpty);
|
||||
expect(launch.workingDirectory, isNull);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'GoCoreLocator falls back to go run in the local bridge package',
|
||||
'GoCoreLocator resolves the local build artifact from the workspace root',
|
||||
() async {
|
||||
final tempDirectory = await Directory.systemTemp.createTemp(
|
||||
'xworkmate-go-core-',
|
||||
@ -53,21 +54,68 @@ void main() {
|
||||
await tempDirectory.delete(recursive: true);
|
||||
}
|
||||
});
|
||||
await Directory(
|
||||
'${tempDirectory.path}/go/go_core',
|
||||
).create(recursive: true);
|
||||
final bridgeFile = File('${tempDirectory.path}/build/bin/xworkmate-go-core');
|
||||
await bridgeFile.parent.create(recursive: true);
|
||||
await bridgeFile.writeAsString('#!/bin/sh\nexit 0\n');
|
||||
await Process.run('chmod', <String>['+x', bridgeFile.path]);
|
||||
|
||||
final locator = GoCoreLocator(
|
||||
workspaceRoot: tempDirectory.path,
|
||||
binaryExistsResolver: (command) async => command == 'go',
|
||||
);
|
||||
|
||||
final launch = await locator.locate();
|
||||
|
||||
expect(launch, isNotNull);
|
||||
expect(launch!.executable, 'go');
|
||||
expect(launch.arguments, const <String>['run', '.']);
|
||||
expect(launch.workingDirectory, '${tempDirectory.path}/go/go_core');
|
||||
expect(launch!.executable, bridgeFile.path);
|
||||
expect(launch.source, GoCoreLaunchSource.buildArtifact);
|
||||
expect(launch.arguments, isEmpty);
|
||||
expect(launch.workingDirectory, isNull);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'GoCoreLocator resolves build-root bridge binaries from the executable ancestry when cwd is outside the repo',
|
||||
() async {
|
||||
final tempDirectory = await Directory.systemTemp.createTemp(
|
||||
'xworkmate-go-core-build-root-',
|
||||
);
|
||||
final outsideDirectory = await Directory.systemTemp.createTemp(
|
||||
'xworkmate-go-core-outside-',
|
||||
);
|
||||
final originalCurrentDirectory = Directory.current;
|
||||
addTearDown(() async {
|
||||
Directory.current = originalCurrentDirectory;
|
||||
if (await tempDirectory.exists()) {
|
||||
await tempDirectory.delete(recursive: true);
|
||||
}
|
||||
if (await outsideDirectory.exists()) {
|
||||
await outsideDirectory.delete(recursive: true);
|
||||
}
|
||||
});
|
||||
|
||||
final bridgeFile = File('${tempDirectory.path}/build/bin/xworkmate-go-core');
|
||||
await bridgeFile.parent.create(recursive: true);
|
||||
await bridgeFile.writeAsString('#!/bin/sh\nexit 0\n');
|
||||
await Process.run('chmod', <String>['+x', bridgeFile.path]);
|
||||
|
||||
final executablePath =
|
||||
'${tempDirectory.path}/build/macos/Build/Products/Debug/XWorkmate.app/Contents/MacOS/XWorkmate';
|
||||
await File(executablePath).parent.create(recursive: true);
|
||||
await File(executablePath).writeAsString('');
|
||||
|
||||
Directory.current = outsideDirectory;
|
||||
|
||||
final locator = GoCoreLocator(
|
||||
resolvedExecutableResolver: () => executablePath,
|
||||
);
|
||||
|
||||
final launch = await locator.locate();
|
||||
|
||||
expect(launch, isNotNull);
|
||||
expect(launch!.executable, bridgeFile.path);
|
||||
expect(launch.source, GoCoreLaunchSource.buildArtifact);
|
||||
expect(launch.arguments, isEmpty);
|
||||
expect(launch.workingDirectory, isNull);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -89,7 +89,6 @@ void main() {
|
||||
await Process.run('chmod', <String>['+x', helper.path]);
|
||||
final locator = GoCoreLocator(
|
||||
workspaceRoot: tempDir.path,
|
||||
binaryExistsResolver: (_) async => false,
|
||||
resolvedExecutableResolver: () =>
|
||||
'${tempDir.path}/XWorkmate.app/Contents/MacOS/XWorkmate',
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user