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
This commit is contained in:
Sam Chau
2025-12-29 01:35:50 +10:30
parent 7db49af4a2
commit 4aa1c0c8e3
5 changed files with 43 additions and 11 deletions

View File

@@ -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<OperationMetada
/**
* Find and remove a matching create operation for a delete
* Returns true if a create was found and removed (no delete needed)
* Only cancels out if the create file is uncommitted (untracked or staged)
*/
async function cancelOutCreate(
targetDir: string,
repoPath: string,
metadata: OperationMetadata
): Promise<boolean> {
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<WriteResult
await ensureDir(targetDir);
// Optimization: if this is a delete and there's an uncommitted create, just remove the create
if (metadata && await cancelOutCreate(targetDir, metadata)) {
if (metadata && await cancelOutCreate(targetDir, instance.local_path, metadata)) {
// Recompile the cache after removing the create file
await compile(instance.local_path, instance.id);
return { success: true };

View File

@@ -115,10 +115,10 @@ export async function fetch(repoPath: string): Promise<void> {
}
/**
* Pull with rebase
* Pull from remote
*/
export async function pull(repoPath: string): Promise<void> {
await execGit(['pull', '--rebase'], repoPath);
await execGit(['pull'], repoPath);
}
/**

View File

@@ -133,6 +133,23 @@ export async function getBranches(repoPath: string): Promise<string[]> {
return branches;
}
/**
* Check if a file is uncommitted (untracked or staged but not yet committed)
*/
export async function isFileUncommitted(repoPath: string, filepath: string): Promise<boolean> {
// 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
*/