diff --git a/api/src/unraid-api/unraid-file-modifier/file-modification.ts b/api/src/unraid-api/unraid-file-modifier/file-modification.ts index c03fff685..14ad0b45e 100644 --- a/api/src/unraid-api/unraid-file-modifier/file-modification.ts +++ b/api/src/unraid-api/unraid-file-modifier/file-modification.ts @@ -68,7 +68,7 @@ export abstract class FileModification { } } - private async applyPatch(patchContents: string): Promise { + private async applyPatch(patchContents: string): Promise { if (!patchContents.trim()) { throw new Error('Patch contents are empty'); } @@ -82,22 +82,28 @@ export abstract class FileModification { throw new Error(`Failed to apply patch to ${this.filePath}`); } await writeFile(this.filePath, results); + return results; } - async apply(): Promise { + /** + * Apply the patch for the target file + * @returns + */ + async apply(): Promise { try { - const savedPatch = await this.loadPatchedFilePatch(this.filePath); - if (savedPatch) { - // Rollback the saved patch before applying the new patch - await this.rollback(); - } + // First attempt to rollback an existing patch saved on disk (if the file has already been modified by us, unclean shutdown) + await this.rollback(true).catch((err) => { + this.logger.debug( + `Failed to rollback patch for ${this.id}: ${err}, may not have been applied yet` + ); + }); // First attempt to apply the patch that was generated const staticPatch = await this.getPregeneratedPatch(); if (staticPatch) { try { await this.applyPatch(staticPatch); await this.savePatch(staticPatch); - return; + return staticPatch; } catch (error) { this.logger.error( `Failed to apply static patch to ${this.filePath}, continuing with dynamic patch` @@ -107,25 +113,35 @@ export abstract class FileModification { const patchContents = await this.generatePatch(); await this.applyPatch(patchContents); await this.savePatch(patchContents); + return patchContents; } catch (err) { this.logger.error(`Failed to apply patch to ${this.filePath}: ${err}`); + throw err; } } - async rollback(): Promise { - let patch: string; + /** + * Rollback the patch for the target file + * @param useSavedPatchOnly - If true, only use the saved patch file if it exists, otherwise use the file or generate a new patch + */ + async rollback(useSavedPatchOnly: boolean = false): Promise { + let patch: string | null = null; // Try to load saved patch first const savedPatch = await this.loadPatchedFilePatch(this.filePath); if (savedPatch) { this.logger.debug(`Using saved patch file for ${this.id}`); patch = savedPatch; - } else { + } else if (!useSavedPatchOnly) { this.logger.debug(`No saved patch found for ${this.id}, generating new patch`); const patchContents = await this.generatePatch(); patch = patchContents; } + if (!patch) { + throw new Error(`No patch found to rollback for ${this.id}`); + } + const currentContent = await readFile(this.filePath, 'utf8'); const parsedPatch = parsePatch(patch)[0]; diff --git a/api/src/unraid-api/unraid-file-modifier/modifications/__fixtures__/test-patch-file.txt b/api/src/unraid-api/unraid-file-modifier/modifications/__fixtures__/test-patch-file.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/api/src/unraid-api/unraid-file-modifier/modifications/__fixtures__/test.patch b/api/src/unraid-api/unraid-file-modifier/modifications/__fixtures__/test.patch deleted file mode 100644 index bc727f476..000000000 --- a/api/src/unraid-api/unraid-file-modifier/modifications/__fixtures__/test.patch +++ /dev/null @@ -1,9 +0,0 @@ -Index: text-patch-file.txt -=================================================================== ---- text-patch-file.txt -+++ text-patch-file.txt -@@ -1,1 +1,1 @@ --original -\ No newline at end of file -+modified -\ No newline at end of file diff --git a/api/src/unraid-api/unraid-file-modifier/modifications/__fixtures__/text-patch-file.txt b/api/src/unraid-api/unraid-file-modifier/modifications/__fixtures__/text-patch-file.txt new file mode 100644 index 000000000..94f3610c0 --- /dev/null +++ b/api/src/unraid-api/unraid-file-modifier/modifications/__fixtures__/text-patch-file.txt @@ -0,0 +1 @@ +original \ No newline at end of file diff --git a/api/src/unraid-api/unraid-file-modifier/unraid-file-modifier.spec.ts b/api/src/unraid-api/unraid-file-modifier/unraid-file-modifier.spec.ts index 3981b32df..3b3684601 100644 --- a/api/src/unraid-api/unraid-file-modifier/unraid-file-modifier.spec.ts +++ b/api/src/unraid-api/unraid-file-modifier/unraid-file-modifier.spec.ts @@ -132,12 +132,6 @@ describe.sequential('FileModificationService', () => { afterEach(async () => { await service.rollbackAll(); - // Clean up the fixture file - try { - await fs.unlink(FIXTURE_PATH); - } catch (error) { - console.error('Failed to clean up fixture file', error); - } vi.clearAllMocks(); }); });