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:
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user