chore: remove all source code comments and internal artifacts
Strip every comment from the source (parsed with the TypeScript compiler so strings, template literals, regex literals and JSX are never touched), and drop internal/working artifacts that do not belong in the public repository (design mockups, internal analysis docs, a stray backup file and an old log). No functional change: build is green, the full test suite passes.
This commit is contained in:
@@ -2,26 +2,6 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { logTimestamp } from "./log-timestamp";
|
||||
|
||||
/**
|
||||
* Session-eigenes Rename-Protokoll auf dem DESKTOP des Nutzers.
|
||||
*
|
||||
* Ziel (User-Anforderung): bei zukuenftigen Renaming-Problemen eine luekenlose,
|
||||
* sofort auffindbare Uebersicht haben — JEDER Umbenenn-/Verschiebevorgang wird
|
||||
* protokolliert UND danach verifiziert (liegt die Datei wirklich unter dem
|
||||
* Zielnamen auf der Platte? ist die Quelle weg?). Nur weil fs.rename "ok" meldet,
|
||||
* heisst das nicht, dass das Ergebnis stimmt (Gross-/Kleinschreibung, Unicode-
|
||||
* Normalisierung, halb-fertiger EXDEV-Copy ohne geloeschte Quelle, ...).
|
||||
*
|
||||
* - Pro Programm-Sitzung eine eigene Datei: <Desktop>/Downloader-Log/rename-session_<ts>.txt
|
||||
* - Der Ordner wird beim Start angelegt UND vor JEDEM Schreibvorgang selbstheilend
|
||||
* neu angelegt (mkdir recursive) — wird er zur Laufzeit geloescht, ist er beim
|
||||
* naechsten Rename sofort wieder da, inkl. neu geschriebenem Session-Header.
|
||||
* - Synchroner Append (wie rename-log.ts), kein gepufferter Flush: Renames sind
|
||||
* selten genug, und so gibt es kein "geloescht-waehrend-Flush"-Zeitfenster.
|
||||
* - Schlaegt das Logging fehl, wird der Fehler verschluckt — Logging darf einen
|
||||
* Download niemals abbrechen.
|
||||
*/
|
||||
|
||||
type DesktopRenameLevel = "INFO" | "WARN" | "ERROR";
|
||||
|
||||
const FOLDER_NAME = "Downloader-Log";
|
||||
@@ -30,8 +10,6 @@ let logDir: string | null = null;
|
||||
let logFilePath: string | null = null;
|
||||
let sessionHeader = "";
|
||||
|
||||
/** Lokaler Zeitstempel fuer den DATEINAMEN (keine Doppelpunkte — unter Windows
|
||||
* in Dateinamen verboten): YYYY-MM-DD_HH-MM-SS in lokaler Zeit. */
|
||||
function fileTimestamp(date: Date = new Date()): string {
|
||||
const pad = (value: number): string => String(value).padStart(2, "0");
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}_`
|
||||
@@ -65,9 +43,6 @@ function formatFields(fields?: Record<string, unknown>): string {
|
||||
return parts.length > 0 ? ` | ${parts.join(" | ")}` : "";
|
||||
}
|
||||
|
||||
/** Stellt sicher, dass Ordner UND Session-Datei existieren (selbstheilend, auch
|
||||
* wenn beides zur Laufzeit geloescht wurde). Gibt false zurueck, wenn das
|
||||
* Logging nicht initialisiert ist oder das Anlegen scheitert. */
|
||||
function ensureWritable(): boolean {
|
||||
if (!logDir || !logFilePath) {
|
||||
return false;
|
||||
@@ -83,9 +58,6 @@ function ensureWritable(): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
/** Initialisiert das Desktop-Rename-Log fuer diese Sitzung. `desktopDir` ist der
|
||||
* Desktop-Pfad (app.getPath("desktop")). Faellt still auf no-op zurueck, wenn der
|
||||
* Pfad fehlt oder nicht beschreibbar ist. */
|
||||
export function initDesktopRenameLog(desktopDir: string | null | undefined): void {
|
||||
try {
|
||||
const base = String(desktopDir || "").trim();
|
||||
@@ -108,9 +80,6 @@ export function initDesktopRenameLog(desktopDir: string | null | undefined): voi
|
||||
}
|
||||
}
|
||||
|
||||
/** Schreibt eine Zeile ins Desktop-Rename-Log. Tut nichts, wenn nicht
|
||||
* initialisiert; verschluckt jeden Schreibfehler (darf nie einen Download
|
||||
* abbrechen). */
|
||||
export function logDesktopRename(level: DesktopRenameLevel, message: string, fields?: Record<string, unknown>): void {
|
||||
if (!ensureWritable() || !logFilePath) {
|
||||
return;
|
||||
@@ -118,7 +87,6 @@ export function logDesktopRename(level: DesktopRenameLevel, message: string, fie
|
||||
try {
|
||||
fs.appendFileSync(logFilePath, `${logTimestamp()} [${level}] ${message}${formatFields(fields)}\n`, "utf8");
|
||||
} catch {
|
||||
// Logging darf einen Download niemals abbrechen.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +106,6 @@ export function shutdownDesktopRenameLog(): void {
|
||||
try {
|
||||
fs.appendFileSync(logFilePath, `=== Rename-Session beendet: ${logTimestamp()} ===\n`, "utf8");
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
logDir = null;
|
||||
@@ -146,34 +113,16 @@ export function shutdownDesktopRenameLog(): void {
|
||||
}
|
||||
|
||||
export interface RenameVerification {
|
||||
/** Gesamtergebnis: Datei liegt unter dem EXAKT erwarteten Namen vor und (sofern kein
|
||||
* In-Place-Rename) die Quelle ist verschwunden. */
|
||||
ok: boolean;
|
||||
/** Empfohlenes Log-Level: ERROR (Rename nicht vollzogen / falscher Name),
|
||||
* WARN (vollzogen, aber Schreibweise nicht pruefbar), INFO (alles ok). */
|
||||
level: "INFO" | "WARN" | "ERROR";
|
||||
/** Zieldatei (egal welche Schreibweise) auf der Platte vorhanden? */
|
||||
targetExists: boolean;
|
||||
/** Tatsaechlicher Name auf der Platte (Gross-/Kleinschreibung wie wirklich
|
||||
* gespeichert), oder null wenn nicht gefunden / Verzeichnis nicht lesbar. */
|
||||
onDiskName: string | null;
|
||||
/** onDiskName === erwarteter Zielname (exakt, case-sensitive)? */
|
||||
nameMatches: boolean;
|
||||
/** Quelldatei verschwunden (Rename wirklich vollzogen, kein halb-fertiger Copy)? */
|
||||
sourceGone: boolean;
|
||||
/** Groesse der Zieldatei in Bytes, oder null. */
|
||||
targetSize: number | null;
|
||||
/** Menschenlesbarer Grund, wenn nicht sauber INFO. */
|
||||
reason: string;
|
||||
}
|
||||
|
||||
/** Repliziert download-manager.toWindowsLongPathIfNeeded (ein Import waere zirkulaer:
|
||||
* download-manager -> desktop-rename-log). Node fs-Aufrufe scheitern unter Windows fuer
|
||||
* absolute Pfade >=248 Zeichen, sofern nicht mit \\?\ / \\?\UNC\ praefixiert — und genau
|
||||
* solche langen Scene-Release-Pfade benennt diese App um. OHNE dieses Prefix wuerden
|
||||
* statSync/readdirSync in der Verifikation auf langen Pfaden faelschlich scheitern
|
||||
* (falsches "Ziel nicht gefunden" UND falsches "Quelle weg" -> falsches OK, das einen
|
||||
* halb-fertigen Verschiebevorgang maskiert). */
|
||||
function toLongPath(filePath: string): string {
|
||||
const absolute = path.resolve(String(filePath || ""));
|
||||
if (process.platform !== "win32") {
|
||||
@@ -191,9 +140,6 @@ function toLongPath(filePath: string): string {
|
||||
return `\\\\?\\${absolute}`;
|
||||
}
|
||||
|
||||
/** Echter On-Disk-Name (korrekte Schreibweise) fuer `requested` aus den
|
||||
* Verzeichnis-Eintraegen, oder null wenn das Verzeichnis nicht lesbar war
|
||||
* (entries===null) bzw. nichts passt. */
|
||||
function resolveOnDiskName(requested: string, entries: string[] | null): string | null {
|
||||
if (entries === null) {
|
||||
return null;
|
||||
@@ -204,8 +150,6 @@ function resolveOnDiskName(requested: string, entries: string[] | null): string
|
||||
|| requested;
|
||||
}
|
||||
|
||||
/** Baut das Verifikations-Ergebnis aus den (sync ODER async) erhobenen Roh-Fakten.
|
||||
* `dirEntries`=null bedeutet "Zielverzeichnis war nicht lesbar". */
|
||||
function buildVerification(
|
||||
sourcePath: string,
|
||||
targetPath: string,
|
||||
@@ -215,8 +159,6 @@ function buildVerification(
|
||||
const dirReadFailed = facts.targetExists && facts.dirEntries === null;
|
||||
const onDiskName = facts.targetExists ? resolveOnDiskName(requested, facts.dirEntries) : null;
|
||||
|
||||
// In-Place-Rename (reine Gross-/Kleinschreibungs-Korrektur auf case-insensitivem FS):
|
||||
// Quelle == Ziel -> "Quelle weg" gilt nicht.
|
||||
const samePath = path.resolve(sourcePath).toLowerCase() === path.resolve(targetPath).toLowerCase();
|
||||
const sourceGone = samePath ? true : !facts.sourceExists;
|
||||
const nameMatches = facts.targetExists && !dirReadFailed && onDiskName === requested;
|
||||
@@ -235,7 +177,6 @@ function buildVerification(
|
||||
level = "ERROR";
|
||||
}
|
||||
if (level === "INFO" && dirReadFailed) {
|
||||
// Datei da + Quelle weg, aber Schreibweise ungeprueft — KEIN stilles OK.
|
||||
problems.push("Zielverzeichnis nicht lesbar — Schreibweise nicht verifiziert");
|
||||
level = "WARN";
|
||||
}
|
||||
@@ -252,10 +193,6 @@ function buildVerification(
|
||||
};
|
||||
}
|
||||
|
||||
/** Verifiziert NACH einem Rename SYNCHRON, ob das Ergebnis wirklich stimmt — der Kern
|
||||
* der User-Anforderung ("nur weil er renaming sagt heisst es nicht das es klappt").
|
||||
* Fuer die synchronen Rename-Sites (startup-Dedup, Suffix-Fix, Deobfuskation). Rein
|
||||
* lesend, wirft nie. fs-Aufrufe ueber toLongPath (lange Windows-Pfade!). */
|
||||
export function verifyRename(sourcePath: string, targetPath: string): RenameVerification {
|
||||
const longTarget = toLongPath(targetPath);
|
||||
let targetExists = false;
|
||||
@@ -285,9 +222,6 @@ export function verifyRename(sourcePath: string, targetPath: string): RenameVeri
|
||||
return buildVerification(sourcePath, targetPath, { targetExists, targetSize, dirEntries, sourceExists });
|
||||
}
|
||||
|
||||
/** Asynchrone Verifikation — fuer den Media-Rename-Hot-Path (renamePathWithExdevFallback),
|
||||
* damit KEIN synchrones statSync/readdirSync den Electron-Main-Loop in Saison-Pack-
|
||||
* Rename-Schleifen blockiert (Projekt-Regel: kein sync I/O in Hot Paths). Wirft nie. */
|
||||
export async function verifyRenameAsync(sourcePath: string, targetPath: string): Promise<RenameVerification> {
|
||||
const longTarget = toLongPath(targetPath);
|
||||
let targetExists = false;
|
||||
|
||||
Reference in New Issue
Block a user