fix(v5): Neu komprimieren ersetzt die alte Fassung — erst wenn die neue fertig ist
Ampel / ampel (push) Successful in 1m31s
Ampel / ampel (push) Successful in 1m31s
Bei Serien stand die alte S01E03.mkv der Umbenennung im Weg (existiert schon), bei Filmen ueberschrieb HandBrake stumm. Jetzt traegt der Wiederholungs-Auftrag die alten fertigen Dateien (ersetzt) und loescht sie NACH dem Encode; scheitert der zweite Lauf, bleibt die erste Fassung. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
6555562a4c
commit
2c74dc6958
@@ -252,6 +252,20 @@ export async function komprimierenUndAblegen(
|
||||
if (datei.rolle === 'folge') folgenSekunden.push(datei.dauerS)
|
||||
}
|
||||
|
||||
// ── Wiederholen: die alte Fassung weicht der neuen — JETZT erst, da alle
|
||||
// neuen Dateien da sind. Vorher hätte ein gescheiterter Lauf die
|
||||
// erste Fassung gekostet; danach stünde sie bei Serien der
|
||||
// Umbenennung im Weg („existiert schon"). ────────────────────────
|
||||
for (const alt of auftrag.ersetzt ?? []) {
|
||||
if (fertigeDateien.includes(alt) || !existsSync(alt)) continue
|
||||
try {
|
||||
unlinkSync(alt)
|
||||
hinweise.push(`Alte Fassung ersetzt: ${basename(alt)}`)
|
||||
} catch (fehler) {
|
||||
hinweise.push(`Alte Fassung nicht gelöscht (${basename(alt)}): ${String(fehler)}`)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Serien-Staffelablage (§ 4.2) ────────────────────────────────────
|
||||
// Von Hand gesetzte Folgen („ab Folge 3") schlagen die Laufzeit-
|
||||
// Zuordnung; TMDb darf dann nur noch warnen. Ohne Vorgabe wird
|
||||
|
||||
@@ -45,6 +45,11 @@ export interface KompressionsAuftrag {
|
||||
* Fassung ersetzt die alte, statt einen zweiten Ordner anzulegen.
|
||||
* '' = Zielordner wird frisch bestimmt. */
|
||||
zielOrdner: string
|
||||
/** Beim Wiederholen: die fertigen Dateien des ERSTEN Durchlaufs. Sie
|
||||
* werden gelöscht, sobald die neuen fertig sind — vorher nicht, damit
|
||||
* ein gescheiterter zweiter Lauf die erste Fassung nicht kostet. Bei
|
||||
* Serien stünden sie sonst der Umbenennung im Weg („existiert schon"). */
|
||||
ersetzt?: string[]
|
||||
}
|
||||
|
||||
export function auftragZuJson(auftrag: KompressionsAuftrag): string {
|
||||
@@ -94,6 +99,7 @@ export function auftragAusJson(text: string): KompressionsAuftrag | null {
|
||||
begonnen: typeof a.begonnen === 'string' ? a.begonnen : '',
|
||||
preset: typeof a.preset === 'string' ? a.preset : '',
|
||||
zielOrdner: typeof a.zielOrdner === 'string' ? a.zielOrdner : '',
|
||||
ersetzt: Array.isArray(a.ersetzt) ? a.ersetzt.map(String) : [],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -734,12 +734,15 @@ function vorgangNeuKomprimieren(vorgangId: string, preset: string): void {
|
||||
if (vorhandene.length < auftrag.dateien.length) {
|
||||
hinweis(`„${v.titel}": ${auftrag.dateien.length - vorhandene.length} Roh-Datei(en) fehlen — der Rest wird komprimiert.`)
|
||||
}
|
||||
const alteFassung = v.phase === 'fertig' && v.zielOrdner.length > 0 && existsSync(v.zielOrdner)
|
||||
const neu = {
|
||||
...auftrag,
|
||||
dateien: vorhandene,
|
||||
preset,
|
||||
// Die neue Fassung ersetzt die alte im selben Ordner.
|
||||
zielOrdner: v.phase === 'fertig' && v.zielOrdner.length > 0 && existsSync(v.zielOrdner) ? v.zielOrdner : '',
|
||||
// Die neue Fassung ersetzt die alte im selben Ordner — die alten
|
||||
// Dateien fallen erst, wenn die neuen fertig sind (ablegen.ts).
|
||||
zielOrdner: alteFassung ? v.zielOrdner : '',
|
||||
ersetzt: alteFassung ? dateienAusJson(v.fertigeDateien) : [],
|
||||
}
|
||||
db?.vorgangAktualisieren(vorgangId, { phase: 'wartet', fehler: '', auftrag: auftragZuJson(neu) })
|
||||
const platz = warteschlange.einreihen(neu, v.titel)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// gewollt UND HandBrake da, sonst VERSCHIEBEN; ein Kompressions-Fehler
|
||||
// lässt den verlustfreien Rip STEHEN und sagt wo er liegt; Sprachen je
|
||||
// Datei erreichen HandBrake; Folgen von Hand schlagen die Laufzeit-Raterei.
|
||||
import { existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
@@ -299,3 +299,51 @@ describe('komprimierenUndAblegen', () => {
|
||||
expect(prozente).toContain(87)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Wiederholen ersetzt die alte Fassung', () => {
|
||||
it('Serie: die alten S01E03/E04 fallen erst nach dem Encode, dann greift die Umbenennung', async () => {
|
||||
const { ablage, roh, dateien } = aufbau(['title_t00.mkv', 'title_t01.mkv'], ['folge', 'folge'])
|
||||
const ziel = join(ablage, 'Serien', 'Spartacus', 'Season 01')
|
||||
mkdirSync(ziel, { recursive: true })
|
||||
const alt3 = join(ziel, 'Spartacus S01E03.mkv')
|
||||
const alt4 = join(ziel, 'Spartacus S01E04.mkv')
|
||||
writeFileSync(alt3, 'alt')
|
||||
writeFileSync(alt4, 'alt')
|
||||
const ergebnis = await komprimierenUndAblegen(
|
||||
auftrag({
|
||||
rohOrdner: roh,
|
||||
dateien,
|
||||
zuordnung: zuordnung('tv', 'Spartacus', 2010),
|
||||
staffel: 1,
|
||||
ersteFolge: 3,
|
||||
zielOrdner: ziel,
|
||||
ersetzt: [alt3, alt4],
|
||||
}),
|
||||
umgebung(ablage),
|
||||
() => {},
|
||||
KEIN_ABBRUCH,
|
||||
)
|
||||
expect(ergebnis.status).toBe('fertig')
|
||||
expect(readdirSync(ziel).filter((n) => n.endsWith('.mkv')).sort()).toEqual(['Spartacus S01E03.mkv', 'Spartacus S01E04.mkv'])
|
||||
expect(readFileSync(alt3, 'utf8')).toBe('encoded')
|
||||
expect(ergebnis.hinweise.join(' ')).toContain('Alte Fassung ersetzt')
|
||||
expect(ergebnis.hinweise.join(' ')).not.toContain('existiert schon')
|
||||
})
|
||||
|
||||
it('scheitert der zweite Lauf, bleibt die alte Fassung stehen', async () => {
|
||||
hb.ergebnis = 'error'
|
||||
const { ablage, roh, dateien } = aufbau(['title_t00.mkv'])
|
||||
const ziel = join(ablage, 'Filme', 'Akira (1988)')
|
||||
mkdirSync(ziel, { recursive: true })
|
||||
const alt = join(ziel, 'title_t00.mkv')
|
||||
writeFileSync(alt, 'alt')
|
||||
const ergebnis = await komprimierenUndAblegen(
|
||||
auftrag({ rohOrdner: roh, dateien, zuordnung: zuordnung('movie', 'Akira', 1988), zielOrdner: ziel, ersetzt: [alt] }),
|
||||
umgebung(ablage),
|
||||
() => {},
|
||||
KEIN_ABBRUCH,
|
||||
)
|
||||
expect(ergebnis.status).toBe('fehler')
|
||||
expect(readFileSync(alt, 'utf8')).toBe('alt')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -99,6 +99,7 @@ describe('Auftrag als JSON — und wieder zurück', () => {
|
||||
begonnen: '2026-08-30T12:00:00.000Z',
|
||||
preset: '',
|
||||
zielOrdner: '',
|
||||
ersetzt: [],
|
||||
}
|
||||
it('kommt unverändert zurück', () => {
|
||||
expect(auftragAusJson(auftragZuJson(a))).toEqual(a)
|
||||
|
||||
Reference in New Issue
Block a user