From 4aa1c0c8e3a301802bb0d9d9eb9df10fd596d46a Mon Sep 17 00:00:00 2001 From: Sam Chau Date: Mon, 29 Dec 2025 01:35:50 +1030 Subject: [PATCH] feat(git): add isFileUncommitted utility and update cancelOutCreate logic fix(repo): change pull command to standard without rebase fix(changes): ensure UI refresh after discarding and adding changes fix(delay-profile): correct label structure for tags in DelayProfileForm --- src/lib/server/pcd/writer.ts | 14 ++++++++++++-- src/lib/server/utils/git/repo.ts | 4 ++-- src/lib/server/utils/git/status.ts | 17 +++++++++++++++++ src/routes/databases/[id]/changes/+page.svelte | 15 ++++++++++----- .../components/DelayProfileForm.svelte | 4 ++-- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/lib/server/pcd/writer.ts b/src/lib/server/pcd/writer.ts index 1ae0aa4..38ec747 100644 --- a/src/lib/server/pcd/writer.ts +++ b/src/lib/server/pcd/writer.ts @@ -7,6 +7,7 @@ import { getBaseOpsPath, getUserOpsPath } from './ops.ts'; import { databaseInstancesQueries } from '$db/queries/databaseInstances.ts'; import { logger } from '$logger/logger.ts'; import { compile } from './cache.ts'; +import { isFileUncommitted } from '$utils/git/status.ts'; export type OperationLayer = 'base' | 'user'; export type OperationType = 'create' | 'update' | 'delete'; @@ -176,9 +177,11 @@ async function parseOperationMetadata(filepath: string): Promise { if (metadata.operation !== 'delete') { @@ -199,9 +202,16 @@ async function cancelOutCreate( fileMeta.entity === metadata.entity && fileMeta.name === metadata.name ) { + // Only cancel out if the file is uncommitted + const uncommitted = await isFileUncommitted(repoPath, filepath); + if (!uncommitted) { + // File has been committed - don't cancel, proceed with delete operation + continue; + } + // Remove the create file - it cancels out with the delete await Deno.remove(filepath); - await logger.info('Cancelled out create operation with delete', { + await logger.info('Cancelled out uncommitted create operation with delete', { source: 'PCDWriter', meta: { filepath, entity: metadata.entity, name: metadata.name } }); @@ -245,7 +255,7 @@ export async function writeOperation(options: WriteOptions): Promise { } /** - * Pull with rebase + * Pull from remote */ export async function pull(repoPath: string): Promise { - await execGit(['pull', '--rebase'], repoPath); + await execGit(['pull'], repoPath); } /** diff --git a/src/lib/server/utils/git/status.ts b/src/lib/server/utils/git/status.ts index 2005d0a..1fc4876 100644 --- a/src/lib/server/utils/git/status.ts +++ b/src/lib/server/utils/git/status.ts @@ -133,6 +133,23 @@ export async function getBranches(repoPath: string): Promise { return branches; } +/** + * Check if a file is uncommitted (untracked or staged but not yet committed) + */ +export async function isFileUncommitted(repoPath: string, filepath: string): Promise { + // Get relative path from repo root + const relativePath = filepath.startsWith(repoPath + '/') + ? filepath.slice(repoPath.length + 1) + : filepath; + + const output = await execGitSafe(['status', '--porcelain', relativePath], repoPath); + if (!output) return false; + + const status = output.substring(0, 2); + // ?? = untracked, A = added (staged), AM = added and modified + return status.startsWith('??') || status[0] === 'A'; +} + /** * Get commit history */ diff --git a/src/routes/databases/[id]/changes/+page.svelte b/src/routes/databases/[id]/changes/+page.svelte index 2731702..6e610f8 100644 --- a/src/routes/databases/[id]/changes/+page.svelte +++ b/src/routes/databases/[id]/changes/+page.svelte @@ -66,18 +66,20 @@ const response = await fetch('?/discard', { method: 'POST', - body: formData + body: formData, + headers: { 'Accept': 'application/json' } }); const result = await response.json(); if (result.type === 'success' && result.data?.success) { - selected = new Set(); alertStore.add('success', 'Changes discarded'); - await fetchChanges(); } else { alertStore.add('error', result.data?.error || 'Failed to discard changes'); } + + selected = new Set(); + await fetchChanges(); } async function handleAdd() { @@ -89,18 +91,21 @@ const response = await fetch('?/add', { method: 'POST', - body: formData + body: formData, + headers: { 'Accept': 'application/json' } }); const result = await response.json(); if (result.type === 'success' && result.data?.success) { - commitMessage = ''; alertStore.add('success', 'Changes committed and pushed'); } else { alertStore.add('error', result.data?.error || 'Failed to add changes'); } + // Always clear and refresh + commitMessage = ''; + // Always refresh to keep UI in sync with file system selected = new Set(); await fetchChanges(); diff --git a/src/routes/delay-profiles/[databaseId]/components/DelayProfileForm.svelte b/src/routes/delay-profiles/[databaseId]/components/DelayProfileForm.svelte index 62e160a..19aeeda 100644 --- a/src/routes/delay-profiles/[databaseId]/components/DelayProfileForm.svelte +++ b/src/routes/delay-profiles/[databaseId]/components/DelayProfileForm.svelte @@ -161,9 +161,9 @@
-