diff --git a/macos/Tests/LitheTests/DiagnosticsWorkflowTests.swift b/macos/Tests/LitheTests/DiagnosticsWorkflowTests.swift index 8e0673b31..5147744b7 100644 --- a/macos/Tests/LitheTests/DiagnosticsWorkflowTests.swift +++ b/macos/Tests/LitheTests/DiagnosticsWorkflowTests.swift @@ -10,6 +10,11 @@ private struct WorkflowLogDirectory: LogDirectoryProviding { let defaultLogDirectory: URL } +/// AppKit shrinks titled windows to the visible screen, and CI displays are smaller than the mockup. +private final class ScreenUnconstrainedWindow: NSWindow { + override func constrainFrameRect(_ frameRect: NSRect, to screen: NSScreen?) -> NSRect { frameRect } +} + /// Real filesystem adapter with task-owned staging, never the user's cache. private struct WorkflowDiskStorage: FileStorage { let root: URL @@ -245,7 +250,7 @@ struct DiagnosticsWorkflowTests { .environmentObject(settings).environment(\.colorScheme, scheme) .environment(\.locale, Locale(identifier: language)) .task { mounted.open() }) - let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 1340, height: 786), styleMask: [.titled, .resizable], backing: .buffered, defer: false) + let window = ScreenUnconstrainedWindow(contentRect: NSRect(x: 0, y: 0, width: 1340, height: 786), styleMask: [.titled, .resizable], backing: .buffered, defer: false) window.isReleasedWhenClosed = false window.appearance = NSAppearance(named: scheme == .dark ? .darkAqua : .aqua) window.contentView = host; window.makeKeyAndOrderFront(nil) diff --git a/rust/lithe-core/src/diagnostics/request_trace.rs b/rust/lithe-core/src/diagnostics/request_trace.rs index d47402658..cde70fb79 100644 --- a/rust/lithe-core/src/diagnostics/request_trace.rs +++ b/rust/lithe-core/src/diagnostics/request_trace.rs @@ -319,12 +319,18 @@ mod tests { #[test] fn fields_keep_valid_tokens_and_omit_invalid_ones() { + // Windows paths are only absolute with a drive prefix. + let root = if cfg!(windows) { + r"C:\project" + } else { + "/tmp/project" + }; let ((), events) = capture::run(false, || { let trace = Request::begin(&request(json!({ "id": "request-1", "command": "git.write", "origin": {"source": "user", "trigger": "vcs.fetch", "operation": "action-7"}, - "payload": {"operation": "fetch", "root": "/tmp/project", "path": "/ignored"} + "payload": {"operation": "fetch", "root": root, "path": "/ignored"} }))); assert_eq!(current().op.as_deref(), Some("action-7")); assert_eq!(current().source, Source::User); diff --git a/rust/lithe-core/src/git/mod.rs b/rust/lithe-core/src/git/mod.rs index 0ed43b601..d57aa5e0c 100644 --- a/rust/lithe-core/src/git/mod.rs +++ b/rust/lithe-core/src/git/mod.rs @@ -16,9 +16,9 @@ pub(crate) mod configuration; pub(crate) mod console; pub(crate) mod execution_events; pub(crate) mod execution_policy; -pub(crate) mod file_context; mod fetch; mod fetch_execution; +pub(crate) mod file_context; #[allow(dead_code)] pub(crate) mod graph; mod history; diff --git a/rust/lithe-core/src/runtime/dispatcher.rs b/rust/lithe-core/src/runtime/dispatcher.rs index 61b365f6d..008d10e48 100644 --- a/rust/lithe-core/src/runtime/dispatcher.rs +++ b/rust/lithe-core/src/runtime/dispatcher.rs @@ -2693,19 +2693,37 @@ fn execute_parsed(parsed: CoreRequest) -> CoreResponse { } CoreCommand::GitWorkspaceStatusMerge => { match serde_json::from_value::(parsed.payload) - .map_err(|error| CoreError::new(ErrorCode::InvalidRequest, "Invalid workspace Git status request").with_details(error.to_string())) + .map_err(|error| { + CoreError::new( + ErrorCode::InvalidRequest, + "Invalid workspace Git status request", + ) + .with_details(error.to_string()) + }) .and_then(git::workspace_status::plan) { - Ok(data) => CoreResponse::success(id, serde_json::to_value(data).expect("Git workspace status plan should encode")), + Ok(data) => CoreResponse::success( + id, + serde_json::to_value(data).expect("Git workspace status plan should encode"), + ), Err(error) => CoreResponse::failure(id, error), } } CoreCommand::GitResolveFileContext => { match serde_json::from_value::(parsed.payload) - .map_err(|error| CoreError::new(ErrorCode::InvalidRequest, "Invalid Git file context request").with_details(error.to_string())) + .map_err(|error| { + CoreError::new( + ErrorCode::InvalidRequest, + "Invalid Git file context request", + ) + .with_details(error.to_string()) + }) .and_then(git::file_context::resolve) { - Ok(data) => CoreResponse::success(id, serde_json::to_value(data).expect("Git file context should encode")), + Ok(data) => CoreResponse::success( + id, + serde_json::to_value(data).expect("Git file context should encode"), + ), Err(error) => CoreResponse::failure(id, error), } } diff --git a/rust/lithe-core/src/tests/core_request_traces.rs b/rust/lithe-core/src/tests/core_request_traces.rs index 815c4b763..bbec0afb4 100644 --- a/rust/lithe-core/src/tests/core_request_traces.rs +++ b/rust/lithe-core/src/tests/core_request_traces.rs @@ -82,7 +82,9 @@ fn user_git_command_records_redacted_argv_under_the_action_operation() { assert_eq!(request.op.as_deref(), Some("action-1")); assert_eq!(request.fields["method"], "git.command"); assert_eq!(request.fields["trigger"], "vcs.commit"); - assert_eq!(request.fields["path"], ""); + // A temporary directory under the home directory scrubs to `\...` on Windows runners. + let path = request.fields["path"].as_str().unwrap(); + assert!(path == "" || path.starts_with(""), "{path}"); let serialized = serde_json::to_string(&events).unwrap(); assert!(!serialized.contains("secret"), "{serialized}"); diff --git a/windows/tauri/src/features/git/utils/lossy-rollback-channel.test.ts b/windows/tauri/src/features/git/utils/lossy-rollback-channel.test.ts index 353891f47..6ef324aac 100644 --- a/windows/tauri/src/features/git/utils/lossy-rollback-channel.test.ts +++ b/windows/tauri/src/features/git/utils/lossy-rollback-channel.test.ts @@ -49,6 +49,7 @@ mock.module("@/platform/tauri-core", () => ({ ...core, invoke: async (command: s mutate?.(); return diff; } + if (command === "git.resolveFileContext") return { root: current.root, path: "file.txt", ownership: "git" }; throw new Error(`Unexpected command: ${command}`); } })); const { getWorkingTreePathDiff, isWorktreeWritePatchCurrent } = await import("@/features/git/api/git-diff-api");