Fix updater SHA512 mismatch by patching latest.yml filenames and adding integrity retry
Some checks are pending
Build and Release / build (push) Waiting to run
Some checks are pending
Build and Release / build (push) Waiting to run
- Patch latest.yml during release to use actual filenames (spaces) instead of electron-builder's dashed names - Add download size validation before SHA512 check to catch incomplete downloads - Retry download on integrity mismatch (up to 3 passes) with API refresh - Re-resolve digest from latest.yml on each retry pass Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8b153bdabe
commit
8f186ad894
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "real-debrid-downloader",
|
"name": "real-debrid-downloader",
|
||||||
"version": "1.4.60",
|
"version": "1.4.61",
|
||||||
"description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)",
|
"description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)",
|
||||||
"main": "build/main/main/main.js",
|
"main": "build/main/main/main.js",
|
||||||
"author": "Sucukdeluxe",
|
"author": "Sucukdeluxe",
|
||||||
|
|||||||
@ -148,6 +148,18 @@ function updatePackageVersion(rootDir, version) {
|
|||||||
fs.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}\n`, "utf8");
|
fs.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}\n`, "utf8");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function patchLatestYml(releaseDir, version) {
|
||||||
|
const ymlPath = path.join(releaseDir, "latest.yml");
|
||||||
|
let content = fs.readFileSync(ymlPath, "utf8");
|
||||||
|
const setupName = `Real-Debrid-Downloader Setup ${version}.exe`;
|
||||||
|
const dashedName = `Real-Debrid-Downloader-Setup-${version}.exe`;
|
||||||
|
if (content.includes(dashedName)) {
|
||||||
|
content = content.split(dashedName).join(setupName);
|
||||||
|
fs.writeFileSync(ymlPath, content, "utf8");
|
||||||
|
process.stdout.write(`Patched latest.yml: replaced "${dashedName}" with "${setupName}"\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function ensureAssetsExist(rootDir, version) {
|
function ensureAssetsExist(rootDir, version) {
|
||||||
const releaseDir = path.join(rootDir, "release");
|
const releaseDir = path.join(rootDir, "release");
|
||||||
const files = [
|
const files = [
|
||||||
@ -162,6 +174,7 @@ function ensureAssetsExist(rootDir, version) {
|
|||||||
throw new Error(`Missing release artifact: ${fullPath}`);
|
throw new Error(`Missing release artifact: ${fullPath}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
patchLatestYml(releaseDir, version);
|
||||||
return { releaseDir, files };
|
return { releaseDir, files };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -689,7 +689,7 @@ export async function checkGitHubUpdate(repo: string): Promise<UpdateCheckResult
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadFile(url: string, targetPath: string, onProgress?: UpdateProgressCallback): Promise<void> {
|
async function downloadFile(url: string, targetPath: string, onProgress?: UpdateProgressCallback): Promise<{ expectedBytes: number | null }> {
|
||||||
const shutdownSignal = activeUpdateAbortController?.signal;
|
const shutdownSignal = activeUpdateAbortController?.signal;
|
||||||
if (shutdownSignal?.aborted) {
|
if (shutdownSignal?.aborted) {
|
||||||
throw new Error("aborted:update_shutdown");
|
throw new Error("aborted:update_shutdown");
|
||||||
@ -808,6 +808,15 @@ async function downloadFile(url: string, targetPath: string, onProgress?: Update
|
|||||||
}
|
}
|
||||||
emitDownloadProgress(true);
|
emitDownloadProgress(true);
|
||||||
logger.info(`Update-Download abgeschlossen: ${targetPath}`);
|
logger.info(`Update-Download abgeschlossen: ${targetPath}`);
|
||||||
|
|
||||||
|
if (totalBytes) {
|
||||||
|
const actualSize = (await fs.promises.stat(targetPath)).size;
|
||||||
|
if (actualSize !== totalBytes) {
|
||||||
|
throw new Error(`Update Download unvollständig (${actualSize} / ${totalBytes} Bytes)`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { expectedBytes: totalBytes };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sleep(ms: number, signal?: AbortSignal): Promise<void> {
|
async function sleep(ms: number, signal?: AbortSignal): Promise<void> {
|
||||||
@ -992,8 +1001,8 @@ export async function installLatestUpdate(
|
|||||||
let verified = false;
|
let verified = false;
|
||||||
let lastVerifyError: unknown = null;
|
let lastVerifyError: unknown = null;
|
||||||
let integrityError: unknown = null;
|
let integrityError: unknown = null;
|
||||||
for (let pass = 0; pass < 2 && !verified; pass += 1) {
|
for (let pass = 0; pass < 3 && !verified; pass += 1) {
|
||||||
logger.info(`Update-Download Kandidaten (${pass + 1}/2): ${candidates.join(" | ")}`);
|
logger.info(`Update-Download Kandidaten (${pass + 1}/3): ${candidates.join(" | ")}`);
|
||||||
lastVerifyError = null;
|
lastVerifyError = null;
|
||||||
for (let index = 0; index < candidates.length; index += 1) {
|
for (let index = 0; index < candidates.length; index += 1) {
|
||||||
const candidate = candidates[index];
|
const candidate = candidates[index];
|
||||||
@ -1034,8 +1043,10 @@ export async function installLatestUpdate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const status = readHttpStatusFromError(lastVerifyError);
|
const status = readHttpStatusFromError(lastVerifyError);
|
||||||
|
const wasIntegrityError = integrityError !== null;
|
||||||
let shouldRetryAfterRefresh = false;
|
let shouldRetryAfterRefresh = false;
|
||||||
if (pass === 0 && status === 404) {
|
|
||||||
|
if (pass < 2 && (status === 404 || wasIntegrityError)) {
|
||||||
const refreshed = await resolveSetupAssetFromApi(safeRepo, effectiveCheck.latestTag);
|
const refreshed = await resolveSetupAssetFromApi(safeRepo, effectiveCheck.latestTag);
|
||||||
if (refreshed) {
|
if (refreshed) {
|
||||||
effectiveCheck = {
|
effectiveCheck = {
|
||||||
@ -1045,15 +1056,14 @@ export async function installLatestUpdate(
|
|||||||
setupAssetDigest: refreshed.setupAssetDigest || effectiveCheck.setupAssetDigest
|
setupAssetDigest: refreshed.setupAssetDigest || effectiveCheck.setupAssetDigest
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (!effectiveCheck.setupAssetDigest && effectiveCheck.setupAssetUrl) {
|
|
||||||
const digestFromYml = await resolveSetupDigestFromLatestYml(safeRepo, effectiveCheck.latestTag, effectiveCheck.setupAssetName || "");
|
const digestFromYml = await resolveSetupDigestFromLatestYml(safeRepo, effectiveCheck.latestTag, effectiveCheck.setupAssetName || "");
|
||||||
if (digestFromYml) {
|
if (digestFromYml) {
|
||||||
effectiveCheck = {
|
effectiveCheck = {
|
||||||
...effectiveCheck,
|
...effectiveCheck,
|
||||||
setupAssetDigest: digestFromYml
|
setupAssetDigest: digestFromYml
|
||||||
};
|
};
|
||||||
logger.info("Update-Integritätsdigest aus latest.yml übernommen");
|
logger.info("Update-Integritätsdigest aus latest.yml übernommen");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const refreshedCandidates = buildDownloadCandidates(safeRepo, effectiveCheck);
|
const refreshedCandidates = buildDownloadCandidates(safeRepo, effectiveCheck);
|
||||||
@ -1061,9 +1071,13 @@ export async function installLatestUpdate(
|
|||||||
&& (refreshedCandidates.length !== candidates.length
|
&& (refreshedCandidates.length !== candidates.length
|
||||||
|| refreshedCandidates.some((value, idx) => value !== candidates[idx]));
|
|| refreshedCandidates.some((value, idx) => value !== candidates[idx]));
|
||||||
if (changed) {
|
if (changed) {
|
||||||
logger.warn("Update-404 erkannt, Kandidatenliste aus API neu geladen");
|
logger.warn(`Update-Fehler erkannt (${wasIntegrityError ? "integrity" : "404"}), Kandidatenliste aus API neu geladen`);
|
||||||
candidates = refreshedCandidates;
|
candidates = refreshedCandidates;
|
||||||
shouldRetryAfterRefresh = true;
|
}
|
||||||
|
shouldRetryAfterRefresh = true;
|
||||||
|
if (wasIntegrityError) {
|
||||||
|
integrityError = null;
|
||||||
|
logger.warn("SHA512-Mismatch erkannt, erneuter Download-Versuch");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!shouldRetryAfterRefresh) {
|
if (!shouldRetryAfterRefresh) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user