Compare commits
No commits in common. "d54a9d603b7de9bec588ccd79abbc5855dcda71a" and "dfab5e0cb42cd77a6e774ca19d31177a99ae0bc4" have entirely different histories.
d54a9d603b
...
dfab5e0cb4
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "real-debrid-downloader",
|
"name": "real-debrid-downloader",
|
||||||
"version": "1.7.156",
|
"version": "1.7.155",
|
||||||
"description": "Desktop downloader",
|
"description": "Desktop downloader",
|
||||||
"main": "build/main/main/main.js",
|
"main": "build/main/main/main.js",
|
||||||
"author": "Sucukdeluxe",
|
"author": "Sucukdeluxe",
|
||||||
|
|||||||
@ -4654,21 +4654,6 @@ export class DownloadManager extends EventEmitter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CLEANUP-DIR: NUR dieser Ordner darf nach dem Move destruktiv aufgeraeumt
|
|
||||||
// werden (Restdateien loeschen + leere Ordner entfernen).
|
|
||||||
// - autoExtract=true -> extractDir (entpackter Inhalt, fertig verarbeitet)
|
|
||||||
// - autoExtract=false -> outputDir (kein Extract, das ist der finale Inhalt)
|
|
||||||
//
|
|
||||||
// WICHTIG: Bei autoExtract=true wird der outputDir NICHT hier aufgeraeumt!
|
|
||||||
// Dort liegen die RAR-Archive, die von der separaten Archive-Cleanup-Pipeline
|
|
||||||
// (mit Extraktions-Guards) verwaltet werden. Ein blindes Loeschen aller
|
|
||||||
// Nicht-Video-Dateien im outputDir wuerde noch nicht entpackte Archive-Sets
|
|
||||||
// anderer Staffeln/Items zerstoeren (Regression v1.7.154, gefixt v1.7.156).
|
|
||||||
const cleanupDirCandidate = this.settings.autoExtract ? pkg.extractDir : pkg.outputDir;
|
|
||||||
const cleanupDir = (cleanupDirCandidate && sourceDirs.some(
|
|
||||||
(d) => path.resolve(d).toLowerCase() === path.resolve(cleanupDirCandidate).toLowerCase()
|
|
||||||
)) ? cleanupDirCandidate : null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fs.promises.mkdir(targetDir, { recursive: true });
|
await fs.promises.mkdir(targetDir, { recursive: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -4845,16 +4830,19 @@ export class DownloadManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sourceArtifactsChanged || sourceCleanupRelevant) && cleanupDir && await this.existsAsync(cleanupDir)) {
|
if (sourceArtifactsChanged || sourceCleanupRelevant) {
|
||||||
// NUR cleanupDir aufraeumen — niemals den outputDir bei autoExtract=true,
|
// Cleanup pro Source-Dir — beide können Restdateien hinterlassen haben
|
||||||
// sonst werden noch nicht entpackte Archive-Sets geloescht (s.o.).
|
// (Mega-Direct .mkv weg aus outputDir, oder extracted .mkv weg aus extractDir).
|
||||||
const removedResidual = await this.cleanupNonMkvResidualFiles(cleanupDir, targetDir);
|
for (const dir of sourceDirs) {
|
||||||
|
if (!await this.existsAsync(dir)) continue;
|
||||||
|
const removedResidual = await this.cleanupNonMkvResidualFiles(dir, targetDir);
|
||||||
if (removedResidual > 0) {
|
if (removedResidual > 0) {
|
||||||
logger.info(`MKV-Sammelordner entfernte Restdateien: pkg=${pkg.name}, dir=${cleanupDir}, entfernt=${removedResidual}`);
|
logger.info(`MKV-Sammelordner entfernte Restdateien: pkg=${pkg.name}, dir=${dir}, entfernt=${removedResidual}`);
|
||||||
}
|
}
|
||||||
const removedDirs = await this.removeEmptyDirectoryTree(cleanupDir);
|
const removedDirs = await this.removeEmptyDirectoryTree(dir);
|
||||||
if (removedDirs > 0) {
|
if (removedDirs > 0) {
|
||||||
logger.info(`MKV-Sammelordner entfernte leere Ordner: pkg=${pkg.name}, dir=${cleanupDir}, entfernt=${removedDirs}`);
|
logger.info(`MKV-Sammelordner entfernte leere Ordner: pkg=${pkg.name}, dir=${dir}, entfernt=${removedDirs}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9441,92 +9441,6 @@ describe("download manager", () => {
|
|||||||
void manager;
|
void manager;
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
|
||||||
it("does NOT delete pending RAR archive sets in outputDir when collecting MKVs from extractDir", async () => {
|
|
||||||
// Regression v1.7.156: bei einem Multi-Archive-Set-Paket (z.B. S01 + S02 RARs
|
|
||||||
// im selben outputDir) wurde nach dem Extrahieren von S01 die MKV-Collection
|
|
||||||
// getriggert. Diese loeschte als "Restdateien" ALLE Nicht-Video-Files im
|
|
||||||
// outputDir — also auch die noch nicht entpackten S02-RAR-Parts. Folge:
|
|
||||||
// S02 ging verloren ("missing_file" beim spaeteren Extract).
|
|
||||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-dm-"));
|
|
||||||
tempDirs.push(root);
|
|
||||||
|
|
||||||
const packageName = "Ugly.Americans.MultiSeason-Pack";
|
|
||||||
const outputDir = path.join(root, "downloads", packageName);
|
|
||||||
const extractDir = path.join(root, "extract", packageName);
|
|
||||||
fs.mkdirSync(outputDir, { recursive: true });
|
|
||||||
fs.mkdirSync(extractDir, { recursive: true });
|
|
||||||
|
|
||||||
// outputDir: S02-RAR-Set noch NICHT entpackt (pending). Muss erhalten bleiben.
|
|
||||||
const s02Parts = [
|
|
||||||
"Ugly.Americans.S02.COMPLETE.German.part1.rar",
|
|
||||||
"Ugly.Americans.S02.COMPLETE.German.part2.rar",
|
|
||||||
"Ugly.Americans.S02.COMPLETE.German.part3.rar"
|
|
||||||
];
|
|
||||||
for (const part of s02Parts) {
|
|
||||||
fs.writeFileSync(path.join(outputDir, part), Buffer.alloc(1024, 7));
|
|
||||||
}
|
|
||||||
// Auch eine harmlose Nicht-Video-Restdatei im outputDir (z.B. .nfo).
|
|
||||||
fs.writeFileSync(path.join(outputDir, "info.nfo"), Buffer.from("nfo"));
|
|
||||||
|
|
||||||
// extractDir: S01 wurde bereits entpackt → MKVs liegen hier.
|
|
||||||
const s01Mkvs = [
|
|
||||||
"Ugly.Americans.S01E01.German.mkv",
|
|
||||||
"Ugly.Americans.S01E02.German.mkv"
|
|
||||||
];
|
|
||||||
for (const mkv of s01Mkvs) {
|
|
||||||
fs.writeFileSync(path.join(extractDir, mkv), Buffer.alloc(4096, 9));
|
|
||||||
}
|
|
||||||
|
|
||||||
const session = emptySession();
|
|
||||||
const packageId = `${packageName}-pkg`;
|
|
||||||
const createdAt = Date.now() - 20_000;
|
|
||||||
session.packageOrder = [packageId];
|
|
||||||
session.packages[packageId] = {
|
|
||||||
id: packageId,
|
|
||||||
name: packageName,
|
|
||||||
outputDir,
|
|
||||||
extractDir,
|
|
||||||
status: "downloading",
|
|
||||||
itemIds: [],
|
|
||||||
cancelled: false,
|
|
||||||
enabled: true,
|
|
||||||
createdAt,
|
|
||||||
updatedAt: createdAt
|
|
||||||
};
|
|
||||||
|
|
||||||
const mkvLibraryDir = path.join(root, "mkv-library");
|
|
||||||
|
|
||||||
const manager = new DownloadManager(
|
|
||||||
{
|
|
||||||
...defaultSettings(),
|
|
||||||
outputDir: path.join(root, "downloads"),
|
|
||||||
extractDir: path.join(root, "extract"),
|
|
||||||
autoExtract: true,
|
|
||||||
autoRename4sf4sj: false,
|
|
||||||
collectMkvToLibrary: true,
|
|
||||||
mkvLibraryDir,
|
|
||||||
enableIntegrityCheck: false,
|
|
||||||
cleanupMode: "delete"
|
|
||||||
},
|
|
||||||
session,
|
|
||||||
createStoragePaths(path.join(root, "state"))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Direkt aufrufen (umgeht die volle Download/Extract-Pipeline).
|
|
||||||
await (manager as any).collectMkvFilesToLibrary(packageId, session.packages[packageId]);
|
|
||||||
|
|
||||||
// S01-MKVs sind in der Library angekommen.
|
|
||||||
for (const mkv of s01Mkvs) {
|
|
||||||
expect(fs.existsSync(path.join(mkvLibraryDir, mkv))).toBe(true);
|
|
||||||
}
|
|
||||||
// KRITISCH: S02-RAR-Parts im outputDir wurden NICHT geloescht.
|
|
||||||
for (const part of s02Parts) {
|
|
||||||
expect(fs.existsSync(path.join(outputDir, part))).toBe(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void manager;
|
|
||||||
}, 20000);
|
|
||||||
|
|
||||||
it("does NOT move bonus files from Extras subdirectory to flat library", async () => {
|
it("does NOT move bonus files from Extras subdirectory to flat library", async () => {
|
||||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-dm-"));
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-dm-"));
|
||||||
tempDirs.push(root);
|
tempDirs.push(root);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user