From 245151dda23309290151344a69845715f557bbb6 Mon Sep 17 00:00:00 2001 From: xintaofei Date: Wed, 1 Apr 2026 11:16:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8F=90=E4=BA=A4=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=9A=84=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E4=B8=80=E4=BA=9B=E6=83=85=E5=86=B5=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/commands/folders.rs | 47 +++++++++++++++++++------ src/app/commit/page.tsx | 3 +- src/components/layout/commit-dialog.tsx | 17 ++++----- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src-tauri/src/commands/folders.rs b/src-tauri/src/commands/folders.rs index f2fafad..33a04d9 100644 --- a/src-tauri/src/commands/folders.rs +++ b/src-tauri/src/commands/folders.rs @@ -1566,19 +1566,44 @@ pub(crate) async fn git_commit_core( message: &str, files: &[String], ) -> Result { - // Stage selected files - let mut add_args = vec!["add".to_string(), "--".to_string()]; - add_args.extend(files.iter().map(|file| to_git_literal_pathspec(file))); + // Find files already staged for deletion — git add would fail on these + // because they no longer exist in either the working tree or the index. + let staged_deletions: std::collections::HashSet = + crate::process::tokio_command("git") + .args(["diff", "--cached", "--name-only", "--diff-filter=D", "-z"]) + .current_dir(path) + .output() + .await + .ok() + .map(|o| { + String::from_utf8_lossy(&o.stdout) + .split('\0') + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect() + }) + .unwrap_or_default(); - let add_output = crate::process::tokio_command("git") - .args(&add_args) - .current_dir(path) - .output() - .await - .map_err(AppCommandError::io)?; + // Stage only files that aren't already staged deletions + let files_to_add: Vec<_> = files + .iter() + .filter(|f| !staged_deletions.contains(f.as_str())) + .collect(); - if !add_output.status.success() { - return Err(git_command_error("add", &add_output.stderr)); + if !files_to_add.is_empty() { + let mut add_args = vec!["add".to_string(), "--".to_string()]; + add_args.extend(files_to_add.iter().map(|file| to_git_literal_pathspec(file))); + + let add_output = crate::process::tokio_command("git") + .args(&add_args) + .current_dir(path) + .output() + .await + .map_err(AppCommandError::io)?; + + if !add_output.status.success() { + return Err(git_command_error("add", &add_output.stderr)); + } } // Resolve commit author from matching account (e.g. GitHub username) diff --git a/src/app/commit/page.tsx b/src/app/commit/page.tsx index 36bc4eb..4340f6f 100644 --- a/src/app/commit/page.tsx +++ b/src/app/commit/page.tsx @@ -12,6 +12,7 @@ import { CommitWorkspace } from "@/components/layout/commit-dialog" import { AppTitleBar } from "@/components/layout/app-title-bar" import { AppToaster } from "@/components/ui/app-toaster" import { getFolder } from "@/lib/api" +import { toErrorMessage } from "@/lib/app-error" import type { FolderDetail } from "@/lib/types" const TOAST_DURATION_MS = 6000 @@ -67,7 +68,7 @@ function CommitPageInner() { setState({ loadedId: normalizedFolderId, folder: null, - error: String(err), + error: toErrorMessage(err), }) } }) diff --git a/src/components/layout/commit-dialog.tsx b/src/components/layout/commit-dialog.tsx index fa49078..fc2e18b 100644 --- a/src/components/layout/commit-dialog.tsx +++ b/src/components/layout/commit-dialog.tsx @@ -47,6 +47,7 @@ import { cn } from "@/lib/utils" import { toast } from "sonner" import { DiffViewer } from "@/components/diff/diff-viewer" import { languageFromPath } from "@/lib/language-detect" +import { toErrorMessage } from "@/lib/app-error" interface CommitWorkspaceProps { folderPath: string @@ -342,7 +343,7 @@ export function CommitWorkspace({ await loadDiff(firstFile, result) } } catch (err) { - setError(String(err)) + setError(toErrorMessage(err)) setEntries([]) setExpandedTrackedDirs(new Set()) setExpandedUntrackedDirs(new Set()) @@ -432,7 +433,7 @@ export function CommitWorkspace({ }) onCommitted?.() } catch (err) { - setError(String(err)) + setError(toErrorMessage(err)) } finally { setCommitting(false) } @@ -448,7 +449,7 @@ export function CommitWorkspace({ toast.success(t("toasts.addedToVcs"), { description: file }) void loadStatus() } catch (err) { - toast.error(t("toasts.addToVcsFailed"), { description: String(err) }) + toast.error(t("toasts.addToVcsFailed"), { description: toErrorMessage(err) }) } }, [folderPath, loadStatus, t] @@ -482,7 +483,7 @@ export function CommitWorkspace({ void loadStatus() } catch (err) { toast.error(t("toasts.deleteFailed"), { - description: String(err), + description: toErrorMessage(err), }) } })() @@ -519,7 +520,7 @@ export function CommitWorkspace({ void loadStatus() } catch (err) { toast.error(t("toasts.rollbackFailed"), { - description: String(err), + description: toErrorMessage(err), }) } })() @@ -558,7 +559,7 @@ export function CommitWorkspace({ void loadStatus() } catch (err) { toast.error(t("toasts.rollbackFailed"), { - description: String(err), + description: toErrorMessage(err), }) } })() @@ -597,7 +598,7 @@ export function CommitWorkspace({ void loadStatus() } catch (err) { toast.error(t("toasts.deleteFailed"), { - description: String(err), + description: toErrorMessage(err), }) } })() @@ -616,7 +617,7 @@ export function CommitWorkspace({ toast.success(t("toasts.addedToVcs"), { description: label }) void loadStatus() } catch (err) { - toast.error(t("toasts.addToVcsFailed"), { description: String(err) }) + toast.error(t("toasts.addToVcsFailed"), { description: toErrorMessage(err) }) } }, [folderPath, loadStatus, t]