Release v1.4.7 with ENOENT extraction recovery and lag optimizations
Build and Release / build (push) Has been cancelled

This commit is contained in:
Sucukdeluxe
2026-02-27 19:12:40 +01:00
parent dbf1c34282
commit 3b9c4a4e88
9 changed files with 358 additions and 90 deletions
+14 -57
View File
@@ -42,9 +42,18 @@ type ExtractResumeState = {
};
function findArchiveCandidates(packageDir: string): string[] {
const files = fs.readdirSync(packageDir, { withFileTypes: true })
.filter((entry) => entry.isFile())
.map((entry) => path.join(packageDir, entry.name));
if (!packageDir || !fs.existsSync(packageDir)) {
return [];
}
let files: string[] = [];
try {
files = fs.readdirSync(packageDir, { withFileTypes: true })
.filter((entry) => entry.isFile())
.map((entry) => path.join(packageDir, entry.name));
} catch {
return [];
}
const preferred = files.filter((file) => /\.part0*1\.rar$/i.test(file));
const zip = files.filter((file) => /\.zip$/i.test(file));
@@ -408,56 +417,6 @@ function escapeRegex(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function captureDirFingerprint(rootDir: string): Map<string, string> {
const fingerprint = new Map<string, string>();
if (!fs.existsSync(rootDir)) {
return fingerprint;
}
const stack = [rootDir];
while (stack.length > 0) {
const current = stack.pop() as string;
let entries: fs.Dirent[] = [];
try {
entries = fs.readdirSync(current, { withFileTypes: true });
} catch {
continue;
}
for (const entry of entries) {
const full = path.join(current, entry.name);
if (entry.isDirectory()) {
stack.push(full);
continue;
}
if (!entry.isFile()) {
continue;
}
try {
const stat = fs.statSync(full);
const relative = path.relative(rootDir, full).toLowerCase();
fingerprint.set(relative, `${stat.size}:${stat.mtimeMs}`);
} catch {
// ignore
}
}
}
return fingerprint;
}
function hasDirChanges(before: Map<string, string>, after: Map<string, string>): boolean {
if (after.size > before.size) {
return true;
}
for (const [relative, meta] of after.entries()) {
if (before.get(relative) !== meta) {
return true;
}
}
return false;
}
export function collectArchiveCleanupTargets(sourceArchivePath: string): string[] {
const targets = new Set<string>([sourceArchivePath]);
const dir = path.dirname(sourceArchivePath);
@@ -619,7 +578,6 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
const conflictMode = effectiveConflictMode(options.conflictMode);
const passwordCandidates = archivePasswords(options.passwordList || "");
const beforeFingerprint = captureDirFingerprint(options.targetDir);
const resumeCompleted = readExtractResumeState(options.packageDir);
const resumeCompletedAtStart = resumeCompleted.size;
const candidateNames = new Set(candidates.map((archivePath) => path.basename(archivePath)));
@@ -751,10 +709,9 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
}
if (extracted > 0) {
const afterFingerprint = captureDirFingerprint(options.targetDir);
const changedOutput = hasDirChanges(beforeFingerprint, afterFingerprint);
const hasOutputAfter = hasAnyFilesRecursive(options.targetDir);
const hadResumeProgress = resumeCompletedAtStart > 0;
if (!changedOutput && conflictMode !== "skip" && !hadResumeProgress) {
if (!hasOutputAfter && conflictMode !== "skip" && !hadResumeProgress) {
lastError = "Keine entpackten Dateien erkannt";
failed += extracted;
extracted = 0;