Fix extraction completion and password prioritization
This commit is contained in:
parent
6e00bbab53
commit
babcd8edb7
@ -6396,6 +6396,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
const hybridResolvedItems = new Map<string, DownloadItem[]>();
|
const hybridResolvedItems = new Map<string, DownloadItem[]>();
|
||||||
const hybridStartTimes = new Map<string, number>();
|
const hybridStartTimes = new Map<string, number>();
|
||||||
let hybridLastEmitAt = 0;
|
let hybridLastEmitAt = 0;
|
||||||
|
let hybridLastProgressCurrent: number | null = null;
|
||||||
|
|
||||||
// Mark items based on whether their archive is actually ready for extraction.
|
// Mark items based on whether their archive is actually ready for extraction.
|
||||||
// Only items whose archive is in readyArchives get "Ausstehend"; others keep
|
// Only items whose archive is in readyArchives get "Ausstehend"; others keep
|
||||||
@ -6443,9 +6444,15 @@ export class DownloadManager extends EventEmitter {
|
|||||||
if (progress.phase === "done") {
|
if (progress.phase === "done") {
|
||||||
hybridResolvedItems.clear();
|
hybridResolvedItems.clear();
|
||||||
hybridStartTimes.clear();
|
hybridStartTimes.clear();
|
||||||
|
hybridLastProgressCurrent = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const currentCount = Math.max(0, Number(progress.current ?? 0));
|
||||||
|
const archiveFinished = progress.archiveDone === true
|
||||||
|
|| (hybridLastProgressCurrent !== null && currentCount > hybridLastProgressCurrent);
|
||||||
|
hybridLastProgressCurrent = currentCount;
|
||||||
|
|
||||||
if (progress.archiveName) {
|
if (progress.archiveName) {
|
||||||
// Resolve items for this archive if not yet tracked
|
// Resolve items for this archive if not yet tracked
|
||||||
if (!hybridResolvedItems.has(progress.archiveName)) {
|
if (!hybridResolvedItems.has(progress.archiveName)) {
|
||||||
@ -6470,11 +6477,14 @@ export class DownloadManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
const archItems = hybridResolvedItems.get(progress.archiveName) || [];
|
const archItems = hybridResolvedItems.get(progress.archiveName) || [];
|
||||||
|
|
||||||
// If archive is at 100%, mark its items as done and remove from active
|
// Only mark as finished on explicit archive-done signal (or real current increment),
|
||||||
if (Number(progress.archivePercent ?? 0) >= 100) {
|
// never on raw 100% archivePercent, because password retries can report 100% mid-run.
|
||||||
|
if (archiveFinished) {
|
||||||
const doneAt = nowMs();
|
const doneAt = nowMs();
|
||||||
const startedAt = hybridStartTimes.get(progress.archiveName) || doneAt;
|
const startedAt = hybridStartTimes.get(progress.archiveName) || doneAt;
|
||||||
const doneLabel = formatExtractDone(doneAt - startedAt);
|
const doneLabel = progress.archiveSuccess === false
|
||||||
|
? "Entpacken - Error"
|
||||||
|
: formatExtractDone(doneAt - startedAt);
|
||||||
for (const entry of archItems) {
|
for (const entry of archItems) {
|
||||||
if (!isExtractedLabel(entry.fullStatus)) {
|
if (!isExtractedLabel(entry.fullStatus)) {
|
||||||
entry.fullStatus = doneLabel;
|
entry.fullStatus = doneLabel;
|
||||||
@ -6484,7 +6494,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
hybridResolvedItems.delete(progress.archiveName);
|
hybridResolvedItems.delete(progress.archiveName);
|
||||||
hybridStartTimes.delete(progress.archiveName);
|
hybridStartTimes.delete(progress.archiveName);
|
||||||
// Show transitional label while next archive initializes
|
// Show transitional label while next archive initializes
|
||||||
const done = progress.current + 1;
|
const done = currentCount;
|
||||||
if (done < progress.total) {
|
if (done < progress.total) {
|
||||||
pkg.postProcessLabel = `Entpacken (${done}/${progress.total}) - Naechstes Archiv...`;
|
pkg.postProcessLabel = `Entpacken (${done}/${progress.total}) - Naechstes Archiv...`;
|
||||||
this.emitState();
|
this.emitState();
|
||||||
@ -6516,7 +6526,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update package-level label with overall extraction progress
|
// Update package-level label with overall extraction progress
|
||||||
const activeArchive = Number(progress.archivePercent ?? 0) > 0 ? 1 : 0;
|
const activeArchive = !archiveFinished && Number(progress.archivePercent ?? 0) > 0 ? 1 : 0;
|
||||||
const currentDisplay = Math.max(0, Math.min(progress.total, progress.current + activeArchive));
|
const currentDisplay = Math.max(0, Math.min(progress.total, progress.current + activeArchive));
|
||||||
if (progress.passwordFound) {
|
if (progress.passwordFound) {
|
||||||
pkg.postProcessLabel = `Passwort gefunden · ${progress.archiveName || ""}`;
|
pkg.postProcessLabel = `Passwort gefunden · ${progress.archiveName || ""}`;
|
||||||
@ -6777,6 +6787,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
// Track archives for parallel extraction progress
|
// Track archives for parallel extraction progress
|
||||||
const fullResolvedItems = new Map<string, DownloadItem[]>();
|
const fullResolvedItems = new Map<string, DownloadItem[]>();
|
||||||
const fullStartTimes = new Map<string, number>();
|
const fullStartTimes = new Map<string, number>();
|
||||||
|
let fullLastProgressCurrent: number | null = null;
|
||||||
|
|
||||||
const result = await extractPackageArchives({
|
const result = await extractPackageArchives({
|
||||||
packageDir: pkg.outputDir,
|
packageDir: pkg.outputDir,
|
||||||
@ -6802,10 +6813,16 @@ export class DownloadManager extends EventEmitter {
|
|||||||
if (progress.phase === "done") {
|
if (progress.phase === "done") {
|
||||||
fullResolvedItems.clear();
|
fullResolvedItems.clear();
|
||||||
fullStartTimes.clear();
|
fullStartTimes.clear();
|
||||||
|
fullLastProgressCurrent = null;
|
||||||
emitExtractStatus("Entpacken 100%", true);
|
emitExtractStatus("Entpacken 100%", true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const currentCount = Math.max(0, Number(progress.current ?? 0));
|
||||||
|
const archiveFinished = progress.archiveDone === true
|
||||||
|
|| (fullLastProgressCurrent !== null && currentCount > fullLastProgressCurrent);
|
||||||
|
fullLastProgressCurrent = currentCount;
|
||||||
|
|
||||||
if (progress.archiveName) {
|
if (progress.archiveName) {
|
||||||
// Resolve items for this archive if not yet tracked
|
// Resolve items for this archive if not yet tracked
|
||||||
if (!fullResolvedItems.has(progress.archiveName)) {
|
if (!fullResolvedItems.has(progress.archiveName)) {
|
||||||
@ -6829,11 +6846,14 @@ export class DownloadManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
const archiveItems = fullResolvedItems.get(progress.archiveName) || [];
|
const archiveItems = fullResolvedItems.get(progress.archiveName) || [];
|
||||||
|
|
||||||
// If archive is at 100%, mark its items as done and remove from active
|
// Only finalize on explicit archive completion (or real current increment),
|
||||||
if (Number(progress.archivePercent ?? 0) >= 100) {
|
// not on plain 100% archivePercent.
|
||||||
|
if (archiveFinished) {
|
||||||
const doneAt = nowMs();
|
const doneAt = nowMs();
|
||||||
const startedAt = fullStartTimes.get(progress.archiveName) || doneAt;
|
const startedAt = fullStartTimes.get(progress.archiveName) || doneAt;
|
||||||
const doneLabel = formatExtractDone(doneAt - startedAt);
|
const doneLabel = progress.archiveSuccess === false
|
||||||
|
? "Entpacken - Error"
|
||||||
|
: formatExtractDone(doneAt - startedAt);
|
||||||
for (const entry of archiveItems) {
|
for (const entry of archiveItems) {
|
||||||
if (!isExtractedLabel(entry.fullStatus)) {
|
if (!isExtractedLabel(entry.fullStatus)) {
|
||||||
entry.fullStatus = doneLabel;
|
entry.fullStatus = doneLabel;
|
||||||
@ -6843,7 +6863,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
fullResolvedItems.delete(progress.archiveName);
|
fullResolvedItems.delete(progress.archiveName);
|
||||||
fullStartTimes.delete(progress.archiveName);
|
fullStartTimes.delete(progress.archiveName);
|
||||||
// Show transitional label while next archive initializes
|
// Show transitional label while next archive initializes
|
||||||
const done = progress.current + 1;
|
const done = currentCount;
|
||||||
if (done < progress.total) {
|
if (done < progress.total) {
|
||||||
emitExtractStatus(`Entpacken (${done}/${progress.total}) - Naechstes Archiv...`, true);
|
emitExtractStatus(`Entpacken (${done}/${progress.total}) - Naechstes Archiv...`, true);
|
||||||
}
|
}
|
||||||
@ -6878,7 +6898,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
const elapsed = progress.elapsedMs && progress.elapsedMs >= 1000
|
const elapsed = progress.elapsedMs && progress.elapsedMs >= 1000
|
||||||
? ` · ${Math.floor(progress.elapsedMs / 1000)}s`
|
? ` · ${Math.floor(progress.elapsedMs / 1000)}s`
|
||||||
: "";
|
: "";
|
||||||
const activeArchive = Number(progress.archivePercent ?? 0) > 0 ? 1 : 0;
|
const activeArchive = !archiveFinished && Number(progress.archivePercent ?? 0) > 0 ? 1 : 0;
|
||||||
const currentDisplay = Math.max(0, Math.min(progress.total, progress.current + activeArchive));
|
const currentDisplay = Math.max(0, Math.min(progress.total, progress.current + activeArchive));
|
||||||
let overallLabel: string;
|
let overallLabel: string;
|
||||||
if (progress.passwordFound) {
|
if (progress.passwordFound) {
|
||||||
|
|||||||
@ -123,6 +123,8 @@ export interface ExtractProgressUpdate {
|
|||||||
passwordAttempt?: number;
|
passwordAttempt?: number;
|
||||||
passwordTotal?: number;
|
passwordTotal?: number;
|
||||||
passwordFound?: boolean;
|
passwordFound?: boolean;
|
||||||
|
archiveDone?: boolean;
|
||||||
|
archiveSuccess?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_EXTRACT_OUTPUT_BUFFER = 48 * 1024;
|
const MAX_EXTRACT_OUTPUT_BUFFER = 48 * 1024;
|
||||||
@ -378,6 +380,19 @@ function parseProgressPercent(chunk: string): number | null {
|
|||||||
return latest;
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function nextArchivePercent(previous: number, incoming: number): number {
|
||||||
|
const prev = Math.max(0, Math.min(100, Math.floor(Number(previous) || 0)));
|
||||||
|
const next = Math.max(0, Math.min(100, Math.floor(Number(incoming) || 0)));
|
||||||
|
if (next >= prev) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
// Wrong-password retries can emit a fresh 0..100 run for the same archive.
|
||||||
|
if (prev >= 95 && next <= 5) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
async function shouldPreferExternalZip(archivePath: string): Promise<boolean> {
|
async function shouldPreferExternalZip(archivePath: string): Promise<boolean> {
|
||||||
if (extractorBackendMode() !== "legacy") {
|
if (extractorBackendMode() !== "legacy") {
|
||||||
return true;
|
return true;
|
||||||
@ -529,9 +544,12 @@ function prioritizePassword(passwords: string[], successful: string): string[] {
|
|||||||
return passwords;
|
return passwords;
|
||||||
}
|
}
|
||||||
const index = passwords.findIndex((candidate) => candidate === target);
|
const index = passwords.findIndex((candidate) => candidate === target);
|
||||||
if (index <= 0) {
|
if (index === 0) {
|
||||||
return passwords;
|
return passwords;
|
||||||
}
|
}
|
||||||
|
if (index < 0) {
|
||||||
|
return [target, ...passwords.filter((candidate) => candidate !== target)];
|
||||||
|
}
|
||||||
const next = [...passwords];
|
const next = [...passwords];
|
||||||
const [value] = next.splice(index, 1);
|
const [value] = next.splice(index, 1);
|
||||||
next.unshift(value);
|
next.unshift(value);
|
||||||
@ -961,9 +979,12 @@ function parseJvmLine(
|
|||||||
|
|
||||||
if (trimmed.startsWith("RD_PROGRESS ")) {
|
if (trimmed.startsWith("RD_PROGRESS ")) {
|
||||||
const parsed = parseProgressPercent(trimmed);
|
const parsed = parseProgressPercent(trimmed);
|
||||||
if (parsed !== null && parsed > state.bestPercent) {
|
if (parsed !== null) {
|
||||||
state.bestPercent = parsed;
|
const next = nextArchivePercent(state.bestPercent, parsed);
|
||||||
onArchiveProgress?.(parsed);
|
if (next !== state.bestPercent) {
|
||||||
|
state.bestPercent = next;
|
||||||
|
onArchiveProgress?.(next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1742,6 +1763,10 @@ async function runExternalExtractInner(
|
|||||||
onArchiveProgress?.(0);
|
onArchiveProgress?.(0);
|
||||||
}
|
}
|
||||||
passwordAttempt += 1;
|
passwordAttempt += 1;
|
||||||
|
if (passwordAttempt > 1 && bestPercent > 0) {
|
||||||
|
bestPercent = 0;
|
||||||
|
onArchiveProgress?.(0);
|
||||||
|
}
|
||||||
const quotedPw = password === "" ? '""' : `"${password}"`;
|
const quotedPw = password === "" ? '""' : `"${password}"`;
|
||||||
logger.info(`Legacy-Passwort-Versuch ${passwordAttempt}/${passwords.length} für ${path.basename(archivePath)}: ${quotedPw}`);
|
logger.info(`Legacy-Passwort-Versuch ${passwordAttempt}/${passwords.length} für ${path.basename(archivePath)}: ${quotedPw}`);
|
||||||
if (passwords.length > 1) {
|
if (passwords.length > 1) {
|
||||||
@ -1750,11 +1775,14 @@ async function runExternalExtractInner(
|
|||||||
let args = buildExternalExtractArgs(command, archivePath, targetDir, conflictMode, password, usePerformanceFlags, hybridMode);
|
let args = buildExternalExtractArgs(command, archivePath, targetDir, conflictMode, password, usePerformanceFlags, hybridMode);
|
||||||
let result = await runExtractCommand(command, args, (chunk) => {
|
let result = await runExtractCommand(command, args, (chunk) => {
|
||||||
const parsed = parseProgressPercent(chunk);
|
const parsed = parseProgressPercent(chunk);
|
||||||
if (parsed === null || parsed <= bestPercent) {
|
if (parsed === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bestPercent = parsed;
|
const next = nextArchivePercent(bestPercent, parsed);
|
||||||
onArchiveProgress?.(bestPercent);
|
if (next !== bestPercent) {
|
||||||
|
bestPercent = next;
|
||||||
|
onArchiveProgress?.(bestPercent);
|
||||||
|
}
|
||||||
}, signal, timeoutMs);
|
}, signal, timeoutMs);
|
||||||
|
|
||||||
if (!result.ok && usePerformanceFlags && isUnsupportedExtractorSwitchError(result.errorText)) {
|
if (!result.ok && usePerformanceFlags && isUnsupportedExtractorSwitchError(result.errorText)) {
|
||||||
@ -1764,11 +1792,14 @@ async function runExternalExtractInner(
|
|||||||
args = buildExternalExtractArgs(command, archivePath, targetDir, conflictMode, password, false, hybridMode);
|
args = buildExternalExtractArgs(command, archivePath, targetDir, conflictMode, password, false, hybridMode);
|
||||||
result = await runExtractCommand(command, args, (chunk) => {
|
result = await runExtractCommand(command, args, (chunk) => {
|
||||||
const parsed = parseProgressPercent(chunk);
|
const parsed = parseProgressPercent(chunk);
|
||||||
if (parsed === null || parsed <= bestPercent) {
|
if (parsed === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bestPercent = parsed;
|
const next = nextArchivePercent(bestPercent, parsed);
|
||||||
onArchiveProgress?.(bestPercent);
|
if (next !== bestPercent) {
|
||||||
|
bestPercent = next;
|
||||||
|
onArchiveProgress?.(bestPercent);
|
||||||
|
}
|
||||||
}, signal, timeoutMs);
|
}, signal, timeoutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2258,6 +2289,7 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
let extracted = candidates.length - pendingCandidates.length;
|
let extracted = candidates.length - pendingCandidates.length;
|
||||||
let failed = 0;
|
let failed = 0;
|
||||||
let lastError = "";
|
let lastError = "";
|
||||||
|
let learnedPassword = "";
|
||||||
const extractedArchives = new Set<string>();
|
const extractedArchives = new Set<string>();
|
||||||
for (const archivePath of candidates) {
|
for (const archivePath of candidates) {
|
||||||
if (resumeCompleted.has(archiveNameKey(path.basename(archivePath)))) {
|
if (resumeCompleted.has(archiveNameKey(path.basename(archivePath)))) {
|
||||||
@ -2271,7 +2303,8 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
phase: "extracting" | "done",
|
phase: "extracting" | "done",
|
||||||
archivePercent?: number,
|
archivePercent?: number,
|
||||||
elapsedMs?: number,
|
elapsedMs?: number,
|
||||||
pwInfo?: { passwordAttempt?: number; passwordTotal?: number; passwordFound?: boolean }
|
pwInfo?: { passwordAttempt?: number; passwordTotal?: number; passwordFound?: boolean },
|
||||||
|
archiveInfo?: { archiveDone?: boolean; archiveSuccess?: boolean }
|
||||||
): void => {
|
): void => {
|
||||||
if (!options.onProgress) {
|
if (!options.onProgress) {
|
||||||
return;
|
return;
|
||||||
@ -2292,6 +2325,7 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
archivePercent,
|
archivePercent,
|
||||||
elapsedMs,
|
elapsedMs,
|
||||||
phase,
|
phase,
|
||||||
|
...(archiveInfo || {}),
|
||||||
...(pwInfo || {})
|
...(pwInfo || {})
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -2306,7 +2340,7 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
// rather than leaving them as "Entpacken - Ausstehend" until all extraction finishes.
|
// rather than leaving them as "Entpacken - Ausstehend" until all extraction finishes.
|
||||||
for (const archivePath of candidates) {
|
for (const archivePath of candidates) {
|
||||||
if (resumeCompleted.has(archiveNameKey(path.basename(archivePath)))) {
|
if (resumeCompleted.has(archiveNameKey(path.basename(archivePath)))) {
|
||||||
emitProgress(extracted, path.basename(archivePath), "extracting", 100, 0);
|
emitProgress(extracted, path.basename(archivePath), "extracting", 100, 0, undefined, { archiveDone: true, archiveSuccess: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2329,11 +2363,14 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
||||||
}, 1100);
|
}, 1100);
|
||||||
const hybrid = Boolean(options.hybridMode);
|
const hybrid = Boolean(options.hybridMode);
|
||||||
// Insert archive-filename-derived passwords after "" but before custom passwords
|
// Before the first successful extraction, filename-derived candidates are useful.
|
||||||
|
// After a known password is learned, try that first to avoid per-archive delays.
|
||||||
const filenamePasswords = archiveFilenamePasswords(archiveName);
|
const filenamePasswords = archiveFilenamePasswords(archiveName);
|
||||||
const archivePasswordCandidates = filenamePasswords.length > 0
|
const nonEmptyBasePasswords = passwordCandidates.filter((p) => p !== "");
|
||||||
? Array.from(new Set(["", ...filenamePasswords, ...passwordCandidates.filter((p) => p !== "")]))
|
const orderedNonEmpty = learnedPassword
|
||||||
: passwordCandidates;
|
? [learnedPassword, ...nonEmptyBasePasswords.filter((p) => p !== learnedPassword), ...filenamePasswords]
|
||||||
|
: [...filenamePasswords, ...nonEmptyBasePasswords];
|
||||||
|
const archivePasswordCandidates = Array.from(new Set(["", ...orderedNonEmpty]));
|
||||||
|
|
||||||
// Validate generic .001 splits via file signature before attempting extraction
|
// Validate generic .001 splits via file signature before attempting extraction
|
||||||
const isGenericSplit = /\.\d{3}$/i.test(archiveName) && !/\.(zip|7z)\.\d{3}$/i.test(archiveName);
|
const isGenericSplit = /\.\d{3}$/i.test(archiveName) && !/\.(zip|7z)\.\d{3}$/i.test(archiveName);
|
||||||
@ -2368,9 +2405,12 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
if (preferExternal) {
|
if (preferExternal) {
|
||||||
try {
|
try {
|
||||||
const usedPassword = await runExternalExtract(archivePath, options.targetDir, options.conflictMode, archivePasswordCandidates, (value) => {
|
const usedPassword = await runExternalExtract(archivePath, options.targetDir, options.conflictMode, archivePasswordCandidates, (value) => {
|
||||||
archivePercent = Math.max(archivePercent, value);
|
archivePercent = nextArchivePercent(archivePercent, value);
|
||||||
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
||||||
}, options.signal, hybrid, onPwAttempt);
|
}, options.signal, hybrid, onPwAttempt);
|
||||||
|
if (usedPassword) {
|
||||||
|
learnedPassword = usedPassword;
|
||||||
|
}
|
||||||
passwordCandidates = prioritizePassword(passwordCandidates, usedPassword);
|
passwordCandidates = prioritizePassword(passwordCandidates, usedPassword);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (isNoExtractorError(String(error))) {
|
if (isNoExtractorError(String(error))) {
|
||||||
@ -2389,9 +2429,12 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const usedPassword = await runExternalExtract(archivePath, options.targetDir, options.conflictMode, archivePasswordCandidates, (value) => {
|
const usedPassword = await runExternalExtract(archivePath, options.targetDir, options.conflictMode, archivePasswordCandidates, (value) => {
|
||||||
archivePercent = Math.max(archivePercent, value);
|
archivePercent = nextArchivePercent(archivePercent, value);
|
||||||
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
||||||
}, options.signal, hybrid, onPwAttempt);
|
}, options.signal, hybrid, onPwAttempt);
|
||||||
|
if (usedPassword) {
|
||||||
|
learnedPassword = usedPassword;
|
||||||
|
}
|
||||||
passwordCandidates = prioritizePassword(passwordCandidates, usedPassword);
|
passwordCandidates = prioritizePassword(passwordCandidates, usedPassword);
|
||||||
} catch (externalError) {
|
} catch (externalError) {
|
||||||
if (isNoExtractorError(String(externalError)) || isUnsupportedArchiveFormatError(String(externalError))) {
|
if (isNoExtractorError(String(externalError)) || isUnsupportedArchiveFormatError(String(externalError))) {
|
||||||
@ -2403,9 +2446,12 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const usedPassword = await runExternalExtract(archivePath, options.targetDir, options.conflictMode, archivePasswordCandidates, (value) => {
|
const usedPassword = await runExternalExtract(archivePath, options.targetDir, options.conflictMode, archivePasswordCandidates, (value) => {
|
||||||
archivePercent = Math.max(archivePercent, value);
|
archivePercent = nextArchivePercent(archivePercent, value);
|
||||||
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
||||||
}, options.signal, hybrid, onPwAttempt);
|
}, options.signal, hybrid, onPwAttempt);
|
||||||
|
if (usedPassword) {
|
||||||
|
learnedPassword = usedPassword;
|
||||||
|
}
|
||||||
passwordCandidates = prioritizePassword(passwordCandidates, usedPassword);
|
passwordCandidates = prioritizePassword(passwordCandidates, usedPassword);
|
||||||
}
|
}
|
||||||
extracted += 1;
|
extracted += 1;
|
||||||
@ -2415,9 +2461,9 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
logger.info(`Entpacken erfolgreich: ${path.basename(archivePath)}`);
|
logger.info(`Entpacken erfolgreich: ${path.basename(archivePath)}`);
|
||||||
archivePercent = 100;
|
archivePercent = 100;
|
||||||
if (hasManyPasswords) {
|
if (hasManyPasswords) {
|
||||||
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt, { passwordFound: true });
|
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt, { passwordFound: true }, { archiveDone: true, archiveSuccess: true });
|
||||||
} else {
|
} else {
|
||||||
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt, undefined, { archiveDone: true, archiveSuccess: true });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorText = String(error);
|
const errorText = String(error);
|
||||||
@ -2428,7 +2474,7 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
lastError = errorText;
|
lastError = errorText;
|
||||||
const errorCategory = classifyExtractionError(errorText);
|
const errorCategory = classifyExtractionError(errorText);
|
||||||
logger.error(`Entpack-Fehler ${path.basename(archivePath)} [${errorCategory}]: ${errorText}`);
|
logger.error(`Entpack-Fehler ${path.basename(archivePath)} [${errorCategory}]: ${errorText}`);
|
||||||
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt);
|
emitProgress(extracted + failed, archiveName, "extracting", archivePercent, Date.now() - archiveStartedAt, undefined, { archiveDone: true, archiveSuccess: false });
|
||||||
if (isNoExtractorError(errorText)) {
|
if (isNoExtractorError(errorText)) {
|
||||||
noExtractorEncountered = true;
|
noExtractorEncountered = true;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user