Skip to content

Commit

Permalink
feat(patcher): add step to check disk space before processing
Browse files Browse the repository at this point in the history
  • Loading branch information
brownsugar committed Mar 5, 2023
1 parent e819e5c commit 2739dae
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 29 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -20,6 +20,7 @@
"@electron/remote": "^2.0.9",
"@quasar/extras": "^1.15.11",
"buffer-reader": "^0.1.0",
"check-disk-space": "^3.3.1",
"compare-versions": "^6.0.0-rc.1",
"easydl": "^1.0.3",
"electron-log": "^5.0.0-beta.16",
Expand Down
103 changes: 78 additions & 25 deletions src-electron/lib/kart-patcher.ts
Expand Up @@ -6,6 +6,7 @@ import { createGunzip } from 'zlib'
import { move } from 'fs-extra'
import { utimes } from 'utimes'
import EasyDl from 'easydl'
import checkDiskSpace from 'check-disk-space'
import { resolveUrl, fetch } from '../utils'
import { PatchFile, LocalFile } from './kart-files'

Expand All @@ -17,6 +18,7 @@ type stepStartT = {
name:
| 'processPatchInfo'
| 'checkLocal'
| 'checkDisk'
| 'download'
| 'extract'
| 'apply'
Expand All @@ -29,6 +31,7 @@ type stepUpdate = {
fileIndex: number
file: string
type?: 'file-start'
size?: number
} | {
stepIndex: number
fileIndex: number
Expand Down Expand Up @@ -81,7 +84,10 @@ class KartPatcher extends EventEmitter {
tempPath: string

patchFiles: PatchFile[] = []
downloadQueue: LocalFile[] = []
downloadQueue: {
localFile: LocalFile
patchFile: PatchFile
}[] = []

patchFileIndexMap = new Map<string, number>()

Expand All @@ -100,6 +106,7 @@ class KartPatcher extends EventEmitter {
const steps = [
this.processPatchInfo,
this.checkLocal,
this.checkDisk,
this.download,
this.extract,
this.apply,
Expand Down Expand Up @@ -190,7 +197,41 @@ class KartPatcher extends EventEmitter {
}

this.patchFileIndexMap.set(patchFile.path, i)
this.downloadQueue.push(localFile)
this.downloadQueue.push({
localFile,
patchFile
})
}

this.emit('step-end', {
stepIndex
})
}

async checkDisk (stepIndex: number) {
this.emit('step-start', {
stepIndex,
name: 'checkDisk',
indeterminate: true
})

const estimatedSize = this.downloadQueue.reduce((sum, { localFile, patchFile }) => {
if (localFile.target === 'full')
sum += patchFile.sizeGzipped + patchFile.size
else if (localFile.target === 'delta1')
sum += patchFile.delta1Size
else if (localFile.target === 'delta2')
sum += patchFile.delta2Size
return sum
}, 0)
const diskSpace = await checkDiskSpace(this.localPath)
if (diskSpace.free < estimatedSize) {
throw new Error('INSUFFICIENT_DISK_SPACE', {
cause: {
free: diskSpace.free,
estimated: estimatedSize
}
})
}

this.emit('step-end', {
Expand All @@ -213,21 +254,28 @@ class KartPatcher extends EventEmitter {
})

for (let i = 0; i < fileCount; i++) {
const file = this.downloadQueue[i]
const { localFile, patchFile } = this.downloadQueue[i]

this.emit('step-update', {
stepIndex,
fileIndex: i,
file: file.basename,
type: 'file-start'
file: localFile.basename,
type: 'file-start',
size: localFile.target === 'full'
? patchFile.sizeGzipped
: (
localFile.target === 'delta1'
? patchFile.delta1Size
: patchFile.delta2Size
)
})

const localPath = file.getDownloadPath()
const localPath = localFile.getDownloadPath()
await this.createDirectory(localPath)

const downloader =
new EasyDl(
resolveUrl(this.remoteUrl, file.getRawFilePath()),
resolveUrl(this.remoteUrl, localFile.getRawFilePath()),
localPath,
{
connections: this.options.connections,
Expand Down Expand Up @@ -295,19 +343,19 @@ class KartPatcher extends EventEmitter {
})

for (let i = 0; i < fileCount; i++) {
const file = this.downloadQueue[i]
const { localFile } = this.downloadQueue[i]

this.emit('step-update', {
stepIndex,
fileIndex: i,
file: file.basename
file: localFile.basename
})

if (file.target === 'full') {
const downloaded = file.getDownloadPath()
if (localFile.target === 'full') {
const downloaded = localFile.getDownloadPath()
await this.ungzip(downloaded)
await rm(downloaded)
file.extracted = true
localFile.extracted = true
}
}

Expand All @@ -326,20 +374,25 @@ class KartPatcher extends EventEmitter {
})

for (let i = 0; i < fileCount; i++) {
const file = this.downloadQueue[i]
const { localFile } = this.downloadQueue[i]

this.emit('step-update', {
stepIndex,
fileIndex: i,
file: file.basename
file: localFile.basename
})

await move(file.getDownloadPath(), file.path, {
await move(localFile.getDownloadPath(), localFile.path, {
overwrite: true
})
await file.loadMeta()
await localFile.loadMeta()
}

await rm(this.tempPath, {
recursive: true,
force: true
})

this.emit('step-end', {
stepIndex
})
Expand All @@ -355,35 +408,35 @@ class KartPatcher extends EventEmitter {
})

for (let i = 0; i < fileCount; i++) {
const file = this.downloadQueue[i]
const { localFile } = this.downloadQueue[i]

this.emit('step-update', {
stepIndex,
fileIndex: i,
file: file.basename
file: localFile.basename
})

const patchIndex = this.patchFileIndexMap.get(file.filePath)
const patchIndex = this.patchFileIndexMap.get(localFile.filePath)
if (patchIndex === undefined)
continue

const patchFile = this.patchFiles[patchIndex]
if (!existsSync(file.path)) {
if (!existsSync(localFile.path)) {
throw new Error('FILE_NOT_EXIST', {
cause: file.filePath
cause: localFile.filePath
})
}
if (file.target !== 'full')
if (localFile.target !== 'full')
continue

// Check file CRC
if (file.crc !== patchFile.crc) {
if (localFile.crc !== patchFile.crc) {
throw new Error('FILE_CRC_MISMATCH', {
cause: file.filePath
cause: localFile.filePath
})
}
// Restore file modification time
await utimes(file.path, {
await utimes(localFile.path, {
mtime: this.filetimeToUnix(patchFile.dwHighDateTime, patchFile.dwLowDateTime)
})
}
Expand Down
9 changes: 5 additions & 4 deletions src/components/kart-patcher.vue
Expand Up @@ -148,6 +148,7 @@ const notify = useNotify()
type stepT =
| 'processPatchInfo'
| 'checkLocal'
| 'checkDisk'
| 'download'
| 'extract'
| 'apply'
Expand Down Expand Up @@ -287,12 +288,12 @@ on('step-update', (data) => {
stepsProgress.value[data.stepIndex] = (data.fileIndex + 1) / filesTotal.value * 100
}
if (data.type === 'file-meta')
file.value.size = data.meta.size
else if (data.type === 'file-start') {
if (data.type === 'file-meta') {
// file.value.size = data.meta.size
} else if (data.type === 'file-start') {
file.value.name = data.file
file.value.size = data.size ?? 0
file.value.progress = 0
file.value.size = 0
file.value.receivedBytes = 0
} else if (data.type === 'file-download') {
file.value.progress = data.progress?.percentage ?? 0
Expand Down
1 change: 1 addition & 0 deletions src/i18n/en-US/index.ts
Expand Up @@ -110,6 +110,7 @@ export default {
step: {
processPatchInfo: 'Processing patch info',
checkLocal: 'Checking local files',
checkDisk: 'Checking disk space',
download: 'Downloading files',
extract: 'Extracting files',
apply: 'Applying files',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/zh-TW/index.ts
Expand Up @@ -110,6 +110,7 @@ export default {
step: {
processPatchInfo: '獲取更新資訊中',
checkLocal: '檢查本機檔案中',
checkDisk: '檢查硬碟空間中',
download: '下載檔案中',
extract: '解壓縮檔案中',
apply: '套用檔案中',
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Expand Up @@ -1504,6 +1504,11 @@ chardet@^0.7.0:
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==

check-disk-space@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/check-disk-space/-/check-disk-space-3.3.1.tgz#10c4c8706fdd16d3e5c3572a16aa95efd0b4d40b"
integrity sha512-iOrT8yCZjSnyNZ43476FE2rnssvgw5hnuwOM0hm8Nj1qa0v4ieUUEbCyxxsEliaoDUb/75yCOL71zkDiDBLbMQ==

"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
Expand Down

0 comments on commit 2739dae

Please sign in to comment.