fix(downloads): restore hardened output scope release gates

Detect stale or foreign files in package-specific extraction directories before starting fresh work while excluding current and atomic ownership markers.

Keep recursive directory inspection confined to the start-conflict boundary and let archive cleanup prune empty package directories directly.

Register German-audio, auto-rename, collection, hybrid, and legacy fixtures through real complete PackageOutputScope records with current method signatures.

Verify plain stops only persist after active work drains, while update-restart parking keeps both its immediate checkpoint and final queued state.
This commit is contained in:
Sucukdeluxe
2026-08-22 18:24:50 +02:00
parent ea904aff79
commit 0d73f7e074
6 changed files with 155 additions and 78 deletions
+15 -15
View File
@@ -3518,7 +3518,7 @@ export class DownloadManager extends EventEmitter {
const extractDirKey = pathKey(pkg.extractDir);
const hasExtractedFiles = hasFilesByExtractDir.has(extractDirKey)
? Boolean(hasFilesByExtractDir.get(extractDirKey))
: this.getPackageOutputScope(pkg).completeFiles().some((filePath) => isPathInsideDir(filePath, pkg.extractDir));
: await this.directoryHasAnyFiles(pkg.extractDir);
if (!hasFilesByExtractDir.has(extractDirKey)) {
hasFilesByExtractDir.set(extractDirKey, hasExtractedFiles);
}
@@ -4333,14 +4333,12 @@ export class DownloadManager extends EventEmitter {
}
}
if (removed > 0) {
logger.info(`Nachträgliches Archive-Cleanup für ${pkg.name}: ${removed} Datei(en) gelöscht`);
if (!await this.directoryHasAnyFiles(pkg.outputDir)) {
const removedDirs = await this.removeEmptyDirectoryTree(pkg.outputDir);
if (removedDirs > 0) {
logger.info(`Nachträgliches Cleanup entfernte leere Download-Ordner für ${pkg.name}: ${removedDirs}`);
}
}
if (removed > 0) {
logger.info(`Nachträgliches Archive-Cleanup für ${pkg.name}: ${removed} Datei(en) gelöscht`);
const removedDirs = await this.removeEmptyDirectoryTree(pkg.outputDir);
if (removedDirs > 0) {
logger.info(`Nachträgliches Cleanup entfernte leere Download-Ordner für ${pkg.name}: ${removedDirs}`);
}
} else {
logger.info(`Nachträgliches Archive-Cleanup für ${pkg.name}: keine Dateien entfernt`);
}
@@ -4374,12 +4372,14 @@ export class DownloadManager extends EventEmitter {
entries = await fs.promises.readdir(current, { withFileTypes: true });
} catch {
continue;
}
for (const entry of entries) {
if (entry.isFile() && !isIgnorableEmptyDirFileName(entry.name)) {
return true;
}
}
for (const entry of entries) {
const isOwnerMarker = entry.name === PACKAGE_OUTPUT_OWNER_MARKER
|| entry.name.startsWith(`.${PACKAGE_OUTPUT_OWNER_MARKER}.`);
if (entry.isFile() && !isOwnerMarker && !isIgnorableEmptyDirFileName(entry.name)) {
return true;
}
if (entry.isDirectory()) {
stack.push(path.join(current, entry.name));
}