add Toolchain, GitClient, native directory picker

Toolchain centralizes binary resolution — replaces five ad-hoc
mechanisms (expandedPath, _resolveGit, _resolve, _resolvePtyc,
_existsOnPath). Resolves via Future.delayed after runApp to avoid
blocking the merged UI/platform thread on macOS.

GitClient wraps all git operations with a typed API. Every subprocess
call goes through _run() using toolchain.git + toolchain.gitEnv.
Replaces free functions in operations.dart.

Native directory picker: NSOpenPanel on macOS (method channel in
AppDelegate), GtkFileChooserDialog on Linux. Falls back to text-input
dialog on web or MissingPluginException. Shows "No git repo found"
dialog when the selected directory is not a git repository.

PqlClient and pane commands updated to use Toolchain. ToolCheck
replaced by Toolchain.missing/allOk. All IPC handlers now catch
GitException to prevent unhandled exceptions on the merged thread.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeroen Schweitzer
2026-04-25 13:18:39 +02:00
co-authored by Claude Opus 4.6
parent 8edcc78bfe
commit 73e80a55a6
22 changed files with 734 additions and 147 deletions
+7 -5
View File
@@ -27,7 +27,7 @@ import 'package:clide/kernel/src/secrets.dart';
import 'package:clide/kernel/src/settings.dart';
import 'package:clide/kernel/src/theme/controller.dart';
import 'package:clide/kernel/src/theme/loader.dart';
import 'package:clide/kernel/src/tool_check.dart';
import 'package:clide/kernel/src/toolchain.dart';
import 'package:clide/kernel/src/tray.dart';
import 'package:clide/kernel/src/window_controls.dart';
import 'package:flutter/widgets.dart';
@@ -61,7 +61,7 @@ class KernelServices {
required this.project,
required this.extensions,
required this.window,
required this.toolCheck,
required this.toolchain,
required this.scheduler,
});
@@ -89,7 +89,7 @@ class KernelServices {
final ProjectManager project;
final ExtensionManager extensions;
final WindowControls window;
final ToolCheck toolCheck;
final Toolchain toolchain;
final SchedulerService scheduler;
static Future<KernelServices> boot({
@@ -103,6 +103,7 @@ class KernelServices {
String? socketPath,
DaemonClient Function(Logger, DaemonBus)? daemonClientFactory,
bool autoStartDaemonClient = true,
Toolchain? toolchain,
}) async {
final log = Logger();
final events = DaemonBus();
@@ -138,13 +139,14 @@ class KernelServices {
final net = NetworkStatus();
final focus = FocusTracker();
final window = WindowControls();
final toolCheck = ToolCheck();
final tc = toolchain ?? Toolchain();
final scheduler = SchedulerService(events);
scheduler.start();
final project = ProjectManager(
log: log,
events: events,
settings: settings,
toolchain: tc,
);
final ipc = daemonClientFactory != null
? daemonClientFactory(log, events)
@@ -207,7 +209,7 @@ class KernelServices {
project: project,
extensions: extensions,
window: window,
toolCheck: toolCheck,
toolchain: tc,
scheduler: scheduler,
);
}