优化代码冲突解决
This commit is contained in:
@@ -81,6 +81,7 @@ import {
|
||||
openCommitWindow,
|
||||
setFolderParentBranch,
|
||||
gitListConflicts,
|
||||
gitHasMergeHead,
|
||||
} from "@/lib/tauri"
|
||||
import { RemoteManageDialog } from "@/components/layout/remote-manage-dialog"
|
||||
import { ConflictDialog } from "@/components/layout/conflict-dialog"
|
||||
@@ -292,6 +293,9 @@ export function BranchDropdown({
|
||||
})
|
||||
}
|
||||
|
||||
// Uses operation "merge" intentionally: MERGE_HEAD exists so merge state is
|
||||
// already active. MergeWorkspace won't call gitStartPullMerge (only for "pull"),
|
||||
// and ConflictDialog abort correctly runs git merge --abort.
|
||||
async function showMergeConflictDialog() {
|
||||
try {
|
||||
const remaining = await gitListConflicts(folderPath)
|
||||
@@ -310,6 +314,16 @@ export function BranchDropdown({
|
||||
}
|
||||
|
||||
async function handlePush() {
|
||||
// Pre-check: if MERGE_HEAD exists, show conflict dialog immediately
|
||||
try {
|
||||
if (await gitHasMergeHead(folderPath)) {
|
||||
await showMergeConflictDialog()
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
// Pre-check failed, continue with normal push flow
|
||||
}
|
||||
|
||||
const taskId = `git-${++taskSeq.current}-${Date.now()}`
|
||||
const label = t("tasks.pushCode")
|
||||
setLoading(true)
|
||||
|
||||
@@ -44,6 +44,7 @@ export function ConflictDialog({
|
||||
const [resolvedFiles, setResolvedFiles] = useState<Set<string>>(new Set())
|
||||
const [aborting, setAborting] = useState(false)
|
||||
const [completing, setCompleting] = useState(false)
|
||||
const [done, setDone] = useState(false)
|
||||
|
||||
const open = conflictInfo !== null
|
||||
const operation = conflictInfo?.operation ?? "merge"
|
||||
@@ -53,6 +54,7 @@ export function ConflictDialog({
|
||||
if (conflictInfo) {
|
||||
setConflictedFiles(conflictInfo.conflicted_files)
|
||||
setResolvedFiles(new Set())
|
||||
setDone(false)
|
||||
}
|
||||
}, [conflictInfo])
|
||||
|
||||
@@ -76,6 +78,7 @@ export function ConflictDialog({
|
||||
|
||||
let unlistenResolved: UnlistenFn | null = null
|
||||
let unlistenCompleted: UnlistenFn | null = null
|
||||
let unlistenAborted: UnlistenFn | null = null
|
||||
|
||||
listen<{ folder_id: number; file: string }>(
|
||||
"folder://merge-conflict-resolved",
|
||||
@@ -91,6 +94,7 @@ export function ConflictDialog({
|
||||
|
||||
listen<{ folder_id: number }>("folder://merge-completed", (event) => {
|
||||
if (event.payload.folder_id !== folderId) return
|
||||
setDone(true)
|
||||
onResolved()
|
||||
onClose()
|
||||
})
|
||||
@@ -99,12 +103,26 @@ export function ConflictDialog({
|
||||
})
|
||||
.catch(() => {})
|
||||
|
||||
// Merge was aborted (user clicked abort in merge window, or window closed)
|
||||
// Reset resolved state since abort reverts all changes
|
||||
listen<{ folder_id: number }>("folder://merge-aborted", (event) => {
|
||||
if (event.payload.folder_id !== folderId) return
|
||||
setDone(true)
|
||||
setResolvedFiles(new Set())
|
||||
onClose()
|
||||
})
|
||||
.then((fn) => {
|
||||
unlistenAborted = fn
|
||||
})
|
||||
.catch(() => {})
|
||||
|
||||
return () => {
|
||||
disposeTauriListener(
|
||||
unlistenResolved,
|
||||
"ConflictDialog.mergeConflictResolved"
|
||||
)
|
||||
disposeTauriListener(unlistenCompleted, "ConflictDialog.mergeCompleted")
|
||||
disposeTauriListener(unlistenAborted, "ConflictDialog.mergeAborted")
|
||||
}
|
||||
}, [open, folderId, onResolved, onClose])
|
||||
|
||||
@@ -122,7 +140,7 @@ export function ConflictDialog({
|
||||
|
||||
async function handleOpenMergeTool() {
|
||||
try {
|
||||
await openMergeWindow(folderId, operation)
|
||||
await openMergeWindow(folderId, operation, conflictInfo?.upstream_commit)
|
||||
} catch (err) {
|
||||
toast.error(String(err))
|
||||
}
|
||||
@@ -149,6 +167,7 @@ export function ConflictDialog({
|
||||
}
|
||||
|
||||
async function handleComplete() {
|
||||
if (done) return
|
||||
setCompleting(true)
|
||||
try {
|
||||
await gitContinueOperation(folderPath, operation)
|
||||
@@ -227,7 +246,7 @@ export function ConflictDialog({
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={handleComplete}
|
||||
disabled={completing || aborting}
|
||||
disabled={completing || aborting || done}
|
||||
>
|
||||
{completing && (
|
||||
<Loader2 className="mr-1.5 h-3.5 w-3.5 animate-spin" />
|
||||
|
||||
@@ -29,6 +29,7 @@ interface MergeWorkspaceProps {
|
||||
folderId: number
|
||||
folderPath: string
|
||||
operation: string
|
||||
upstreamCommit?: string
|
||||
onCompleted: () => void
|
||||
onAborted: () => void
|
||||
}
|
||||
@@ -37,6 +38,7 @@ export function MergeWorkspace({
|
||||
folderId,
|
||||
folderPath,
|
||||
operation,
|
||||
upstreamCommit,
|
||||
onCompleted,
|
||||
onAborted,
|
||||
}: MergeWorkspaceProps) {
|
||||
@@ -51,6 +53,7 @@ export function MergeWorkspace({
|
||||
const [completing, setCompleting] = useState(false)
|
||||
const currentContentRef = useRef<string>("")
|
||||
const [hasUnresolvedConflicts, setHasUnresolvedConflicts] = useState(true)
|
||||
const [preparing, setPreparing] = useState(false)
|
||||
|
||||
// Load conflict files on mount
|
||||
useEffect(() => {
|
||||
@@ -62,7 +65,12 @@ export function MergeWorkspace({
|
||||
// For pull operations, the merge was aborted during detection to keep
|
||||
// working tree clean. Re-start the merge to create conflict state.
|
||||
if (operation === "pull") {
|
||||
await gitStartPullMerge(folderPath)
|
||||
setPreparing(true)
|
||||
try {
|
||||
await gitStartPullMerge(folderPath, upstreamCommit)
|
||||
} finally {
|
||||
setPreparing(false)
|
||||
}
|
||||
}
|
||||
const conflictFiles = await gitListConflicts(folderPath)
|
||||
setFiles(conflictFiles)
|
||||
@@ -137,7 +145,7 @@ export function MergeWorkspace({
|
||||
try {
|
||||
await gitAbortOperation(folderPath, operation)
|
||||
toast.success(t("abortSuccess"))
|
||||
await emit("folder://merge-completed", { folder_id: folderId })
|
||||
await emit("folder://merge-aborted", { folder_id: folderId })
|
||||
onAborted()
|
||||
} catch (err) {
|
||||
toast.error(toErrorMessage(err))
|
||||
@@ -221,7 +229,12 @@ export function MergeWorkspace({
|
||||
|
||||
{/* Main area: three-pane merge editor */}
|
||||
<ResizablePanel defaultSize={82}>
|
||||
{loadingVersions ? (
|
||||
{preparing ? (
|
||||
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
{t("preparingMerge")}
|
||||
</div>
|
||||
) : loadingVersions ? (
|
||||
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
{t("loadingFile")}
|
||||
|
||||
Reference in New Issue
Block a user