mirror of
https://github.com/Dictionarry-Hub/profilarr.git
synced 2026-01-22 10:51:02 +01:00
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:
@@ -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 };
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -161,9 +161,9 @@
|
||||
|
||||
<!-- Tags -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-neutral-700 dark:text-neutral-300">
|
||||
<div class="block text-sm font-medium text-neutral-700 dark:text-neutral-300">
|
||||
Tags <span class="text-red-500">*</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="mt-1 text-xs text-neutral-500 dark:text-neutral-400">
|
||||
Delay profiles apply to items with matching tags
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user