v1.7.153 zwei Production-Regressionen aus v1.7.151 gefixt
Aus dem live Rename-Log + Library-Screenshot:
(1) .nfo Files landeten in der MKV-Library
moveCompanionFiles() hatte ".nfo" in der Extensions-Liste — sollte
nur fuer Subtitles gemoved werden. .nfo gehoert nicht in die
Library. Aus dem Set entfernt; renameCompanionFiles laesst .nfo
weiterhin mit-umbenennen (im Extract-Dir, harmlos), aber MKV-Move
bringt sie nicht mehr in die Library.
(2) Vollstaendige Scene-Namen wurden auf "Show.SxxExx.mkv" gekuerzt
buildSafeAutoRenameTargetPath hatte ein 247-Zeichen Total-Path-Cap,
das vollstaendige Scene-Releases wie
"Dr.House.S04E02.Der.Stoff.aus.dem.die.Heldin.ist.GERMAN.5.1.DL.AC3.720p.BDRiP.x264-TvR.mkv"
abgelehnt hat → Fallback aktiviert → "Dr.House.S04E02.mkv".
Die ABER renamePathWithExdevFallback wraps eh ueber
toWindowsLongPathIfNeeded (\?\ Prefix), und der Endpfad nach
MKV-Move ist viel kuerzer (Library-Dir-Prefix). Cap war
ueberhaupt nicht noetig und hat aktiv schoene Namen abgesaegt.
Cap entfernt; nur das 255-char NTFS Filename-Limit bleibt.
Test: neuer Test "mkv-move moves SUBTITLES to library but NOT .nfo
metadata files". 592/592 Tests gruen.
Im naechsten Schritt: Fix-Skript fuer den User damit existierende
Library-Files (mit .nfo + zu kurzen Namen) korrigiert werden ohne
Re-Download.
This commit is contained in:
parent
80b4b379f7
commit
6fcad8bc6c
@ -3686,15 +3686,16 @@ export class DownloadManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Move matching subtitle / metadata companions alongside a video that
|
/** Move matching SUBTITLE companions alongside a video collected into the
|
||||||
* was just collected into the library. Mirrors renameCompanionFiles but
|
* library. Note: .nfo / metadata files are intentionally NOT moved — the
|
||||||
* for cross-directory moves. */
|
* library should contain video + subs only. .nfo stays in the extract
|
||||||
|
* dir and is removed by normal cleanup. */
|
||||||
private async moveCompanionFiles(
|
private async moveCompanionFiles(
|
||||||
sourceVideoPath: string,
|
sourceVideoPath: string,
|
||||||
targetVideoPath: string,
|
targetVideoPath: string,
|
||||||
pkg?: PackageEntry
|
pkg?: PackageEntry
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const COMPANION_EXTENSIONS = new Set([".srt", ".ass", ".ssa", ".sub", ".idx", ".vtt", ".smi", ".nfo"]);
|
const COMPANION_EXTENSIONS = new Set([".srt", ".ass", ".ssa", ".sub", ".idx", ".vtt", ".smi"]);
|
||||||
const sourceDir = path.dirname(sourceVideoPath);
|
const sourceDir = path.dirname(sourceVideoPath);
|
||||||
const targetDir = path.dirname(targetVideoPath);
|
const targetDir = path.dirname(targetVideoPath);
|
||||||
const sourceVideoBase = path.basename(sourceVideoPath, path.extname(sourceVideoPath));
|
const sourceVideoBase = path.basename(sourceVideoPath, path.extname(sourceVideoPath));
|
||||||
@ -3776,17 +3777,18 @@ export class DownloadManager extends EventEmitter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows MAX_PATH is 260 chars without the \\?\ long-path prefix.
|
// Note: total-path length is intentionally NOT checked here. We used to
|
||||||
// The actual rename via renamePathWithExdevFallback ALWAYS wraps with
|
// cap it at 247 chars (v1.7.151) on the assumption that paths beyond
|
||||||
// toWindowsLongPathIfNeeded, so paths up to ~32K technically work, but
|
// Windows MAX_PATH (260) would fail or be unusable downstream. That
|
||||||
// many downstream consumers (Explorer, MediaPlayers, scripts) struggle
|
// turned out to be ACTIVELY HARMFUL: renamePathWithExdevFallback wraps
|
||||||
// beyond ~248. Use a conservative 247-char limit so the renamed file
|
// every rename via toWindowsLongPathIfNeeded (\\?\ prefix), and the
|
||||||
// remains usable. Caller will fall back to buildShortPackageFallback
|
// file ends up in the library dir after mkv-move where the parent path
|
||||||
// when this returns null.
|
// is short. Imposing a 247-char cap on the EXTRACT-dir intermediate
|
||||||
const SAFE_TOTAL_PATH_CHARS = 247;
|
// path threw away perfectly-good scene-release names like
|
||||||
if (candidatePath.length > SAFE_TOTAL_PATH_CHARS) {
|
// "Dr.House.S04E02.Der.Stoff.aus.dem.die.Heldin.ist.GERMAN.5.1.DL.AC3.720p.BDRiP.x264-TvR.mkv"
|
||||||
return null;
|
// and replaced them with ugly "Dr.House.S04E02.mkv" via fallback.
|
||||||
}
|
// We rely on the long-path prefix for the rename and on the 255-char
|
||||||
|
// NTFS file-name limit above for the actual constraint.
|
||||||
|
|
||||||
return candidatePath;
|
return candidatePath;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10540,6 +10540,54 @@ describe("download manager", () => {
|
|||||||
expect(fs.existsSync(path.join(sharedDir, "EpisodeFolder", "obfus.mkv"))).toBe(true);
|
expect(fs.existsSync(path.join(sharedDir, "EpisodeFolder", "obfus.mkv"))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("mkv-move moves SUBTITLES to library but NOT .nfo metadata files", async () => {
|
||||||
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-mvcompanion-"));
|
||||||
|
tempDirs.push(root);
|
||||||
|
const extractDir = path.join(root, "extract");
|
||||||
|
const libDir = path.join(root, "library");
|
||||||
|
fs.mkdirSync(extractDir, { recursive: true });
|
||||||
|
fs.mkdirSync(libDir, { recursive: true });
|
||||||
|
const epFolder = path.join(extractDir, "Show.S01E01.GERMAN.x264-GROUP");
|
||||||
|
fs.mkdirSync(epFolder, { recursive: true });
|
||||||
|
fs.writeFileSync(path.join(epFolder, "Show.S01E01.GERMAN.x264-GROUP.mkv"), Buffer.alloc(1024, 0));
|
||||||
|
fs.writeFileSync(path.join(epFolder, "Show.S01E01.GERMAN.x264-GROUP.srt"), "subs");
|
||||||
|
fs.writeFileSync(path.join(epFolder, "Show.S01E01.GERMAN.x264-GROUP.nfo"), "info");
|
||||||
|
|
||||||
|
const manager = new DownloadManager(
|
||||||
|
{
|
||||||
|
...defaultSettings(),
|
||||||
|
token: "rd-token",
|
||||||
|
outputDir: path.join(root, "out"),
|
||||||
|
extractDir,
|
||||||
|
autoExtract: true,
|
||||||
|
collectMkvToLibrary: true,
|
||||||
|
mkvLibraryDir: libDir
|
||||||
|
},
|
||||||
|
emptySession(),
|
||||||
|
createStoragePaths(path.join(root, "state"))
|
||||||
|
);
|
||||||
|
const pkg: any = {
|
||||||
|
id: "movecomp-pkg",
|
||||||
|
name: "Show.S01.GERMAN.x264-GROUP",
|
||||||
|
outputDir: path.join(root, "out", "Show"),
|
||||||
|
extractDir,
|
||||||
|
status: "completed", itemIds: [], cancelled: false, enabled: true, priority: "normal",
|
||||||
|
createdAt: 0, updatedAt: 0, downloadStartedAt: 0, downloadCompletedAt: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
await (manager as any).collectMkvFilesToLibrary("movecomp-pkg", pkg);
|
||||||
|
|
||||||
|
const libFiles = fs.readdirSync(libDir);
|
||||||
|
// Video AND subtitle moved to library.
|
||||||
|
expect(libFiles).toContain("Show.S01E01.GERMAN.x264-GROUP.mkv");
|
||||||
|
expect(libFiles).toContain("Show.S01E01.GERMAN.x264-GROUP.srt");
|
||||||
|
// .nfo MUST NOT end up in the library — that's the user-visible bug
|
||||||
|
// we are fixing. (It gets cleaned up with other residual files in
|
||||||
|
// cleanupNonMkvResidualFiles after the move; we don't care whether it
|
||||||
|
// survives in the extract dir, only that the library stays clean.)
|
||||||
|
expect(libFiles).not.toContain("Show.S01E01.GERMAN.x264-GROUP.nfo");
|
||||||
|
});
|
||||||
|
|
||||||
it("auto-rename also renames matching subtitle / .nfo companion files", async () => {
|
it("auto-rename also renames matching subtitle / .nfo companion files", async () => {
|
||||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-companion-"));
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-companion-"));
|
||||||
tempDirs.push(root);
|
tempDirs.push(root);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user