installer-rp: delete partial artifacts on failure; bump to 0.3.6
Resume previously skipped any track/cover whose file merely existed, so a partially written NN.ogg or cover_NN.png from a failed download/convert could be mistaken for a finished file on the next attempt. Now the failure path removes the expected output before bailing, so only fully completed artifacts are skipped on resume. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "minecraft-music-quiz-installer",
|
"name": "minecraft-music-quiz-installer",
|
||||||
"version": "0.3.5",
|
"version": "0.3.6",
|
||||||
"description": "마인크래프트 음악퀴즈 간편설치기 + 관리 사이트",
|
"description": "마인크래프트 음악퀴즈 간편설치기 + 관리 사이트",
|
||||||
"main": "dist/installer/main.js",
|
"main": "dist/installer/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -365,6 +365,9 @@ ipcMain.handle('rp:install:start', async (): Promise<{ resourcepackPath: string
|
|||||||
async function tryDownloadTrack(i: number, emitErrorProgress: boolean): Promise<boolean> {
|
async function tryDownloadTrack(i: number, emitErrorProgress: boolean): Promise<boolean> {
|
||||||
const entry = musicList[i]
|
const entry = musicList[i]
|
||||||
const idx = i + 1
|
const idx = i + 1
|
||||||
|
// 최종 산출물 경로. 실패 시 부분 생성된 파일을 지워, 다음 재시도(이어받기)에서
|
||||||
|
// 완성본으로 오인해 건너뛰는 일을 막는다.
|
||||||
|
const expectedOut = path.join(musicDir, String(idx).padStart(2, '0') + '.ogg')
|
||||||
sendLog(t('log.musicTrackStart', { idx }))
|
sendLog(t('log.musicTrackStart', { idx }))
|
||||||
sendProgress({ phase: 'item', kind: 'music', index: idx, total: musicTotal, percent: 0, status: 'running' })
|
sendProgress({ phase: 'item', kind: 'music', index: idx, total: musicTotal, percent: 0, status: 'running' })
|
||||||
let child: ChildProcess | null = null
|
let child: ChildProcess | null = null
|
||||||
@@ -394,6 +397,8 @@ ipcMain.handle('rp:install:start', async (): Promise<{ resourcepackPath: string
|
|||||||
return true
|
return true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (child) state.activeChildren.delete(child)
|
if (child) state.activeChildren.delete(child)
|
||||||
|
// 부분 생성된 .ogg 를 제거(이어받기 시 완성본 오인 방지).
|
||||||
|
await fsp.rm(expectedOut, { force: true }).catch(() => {})
|
||||||
if (state.cancelRequested) {
|
if (state.cancelRequested) {
|
||||||
sendProgress({ phase: 'item', kind: 'music', index: idx, total: musicTotal, percent: 0, status: 'error', message: t('progress.cancelled') })
|
sendProgress({ phase: 'item', kind: 'music', index: idx, total: musicTotal, percent: 0, status: 'error', message: t('progress.cancelled') })
|
||||||
return false
|
return false
|
||||||
@@ -483,15 +488,19 @@ ipcMain.handle('rp:install:start', async (): Promise<{ resourcepackPath: string
|
|||||||
try {
|
try {
|
||||||
buf = await downloadImage(entry.url)
|
buf = await downloadImage(entry.url)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
// 부분 생성됐을 수 있는 커버 파일 제거(이어받기 시 완성본 오인 방지).
|
||||||
|
await fsp.rm(coverPath, { force: true }).catch(() => {})
|
||||||
sendProgress({ phase: 'item', kind: 'image', index: idx, total: imageTotal, percent: 0, status: 'error', message: (err as Error).message })
|
sendProgress({ phase: 'item', kind: 'image', index: idx, total: imageTotal, percent: 0, status: 'error', message: (err as Error).message })
|
||||||
throw new Error(t('errors.imageDownloadFailed', { idx, message: (err as Error).message }))
|
throw new Error(t('errors.imageDownloadFailed', { idx, message: (err as Error).message }))
|
||||||
}
|
}
|
||||||
throwIfCancelled()
|
throwIfCancelled()
|
||||||
sendProgress({ phase: 'item', kind: 'image', index: idx, total: imageTotal, percent: 60, status: 'running' })
|
sendProgress({ phase: 'item', kind: 'image', index: idx, total: imageTotal, percent: 60, status: 'running' })
|
||||||
const outPath = path.join(paintingDir, coverFileName(idx))
|
const outPath = coverPath
|
||||||
try {
|
try {
|
||||||
await normalizeToCover(buf, outPath)
|
await normalizeToCover(buf, outPath)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
// 변환 중 부분 생성된 PNG 제거(이어받기 시 완성본 오인 방지).
|
||||||
|
await fsp.rm(coverPath, { force: true }).catch(() => {})
|
||||||
sendProgress({ phase: 'item', kind: 'image', index: idx, total: imageTotal, percent: 0, status: 'error', message: (err as Error).message })
|
sendProgress({ phase: 'item', kind: 'image', index: idx, total: imageTotal, percent: 0, status: 'error', message: (err as Error).message })
|
||||||
throw new Error(t('errors.imageNormalizeFailed', { idx, message: (err as Error).message }))
|
throw new Error(t('errors.imageNormalizeFailed', { idx, message: (err as Error).message }))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user