Show upgrade disk checks by directory

This commit is contained in:
FengLee
2026-05-10 13:28:39 +08:00
parent ee9516c733
commit 0962b4f3fc
3 changed files with 20 additions and 20 deletions

View File

@@ -464,13 +464,12 @@ function validatePreExtractDiskSpace(packageBytes) {
requiredBytes: packageBytes + MAX_EXTRACTED_BYTES + MIN_FREE_BYTES,
});
assertDiskSpace(stateCheck);
logStep('磁盘空间检查', `${stateCheck.label} ${stateCheck.path} 可用 ${formatBytes(stateCheck.availableBytes)},需要 ${formatBytes(stateCheck.requiredBytes)}`);
logDiskCheck(stateCheck);
return [stateCheck];
}
function validateUpgradeDiskSpace(stats, packageBytes) {
const checksByPath = new Map();
for (const check of [
const checks = [
buildDiskCheck({
label: '升级状态目录',
targetPath: stateRoot,
@@ -481,16 +480,10 @@ function validateUpgradeDiskSpace(stats, packageBytes) {
targetPath: projectRoot,
requiredBytes: stats.totalBytes + (mode === 'cold' ? BUILD_FREE_BYTES : MIN_FREE_BYTES),
}),
]) {
const existing = checksByPath.get(check.path);
if (!existing || check.requiredBytes > existing.requiredBytes) {
checksByPath.set(check.path, check);
}
}
const checks = [...checksByPath.values()];
];
for (const check of checks) {
assertDiskSpace(check);
logStep('磁盘空间检查', `${check.label} ${check.path} 可用 ${formatBytes(check.availableBytes)},需要 ${formatBytes(check.requiredBytes)}`);
logDiskCheck(check);
}
return checks;
}
@@ -499,7 +492,8 @@ function buildDiskCheck({ label, targetPath, requiredBytes }) {
const usage = readDiskUsage(targetPath);
return {
label,
path: usage.path,
path: path.resolve(targetPath),
mountPath: usage.mountPath,
totalBytes: usage.totalBytes,
availableBytes: usage.availableBytes,
requiredBytes,
@@ -526,7 +520,7 @@ function readDiskUsage(targetPath) {
throw new Error(`读取磁盘空间失败:${targetPath}`);
}
return {
path: row.slice(5).join(' ') || targetPath,
mountPath: row.slice(5).join(' ') || targetPath,
totalBytes,
availableBytes,
usedPercent: Number.isFinite(usedPercent) ? usedPercent : null,
@@ -539,6 +533,11 @@ function assertDiskSpace(check) {
throw new Error(`升级前磁盘空间不足:${check.label} ${check.path} 可用 ${formatBytes(check.availableBytes)},需要至少 ${formatBytes(check.requiredBytes)}`);
}
function logDiskCheck(check) {
const mountDetail = check.mountPath && check.mountPath !== check.path ? `(挂载点 ${check.mountPath}` : '';
logStep('磁盘空间检查', `${check.label} ${check.path}${mountDetail} 可用 ${formatBytes(check.availableBytes)},需要 ${formatBytes(check.requiredBytes)}`);
}
function validateFiles(files, updateMode) {
for (const file of files) {
assertSafeRelativePath(file);

View File

@@ -52,6 +52,7 @@ type UpgradeJobState = {
type DiskCheck = {
label: string;
path: string;
mountPath?: string;
totalBytes: number;
availableBytes: number;
requiredBytes?: number;
@@ -114,15 +115,10 @@ function getRuntimeStatus(): RuntimeStatus {
}
function getRuntimeDisks(projectRoot: string, stateDir: string): DiskCheck[] {
const checks = [
return [
readDiskUsage('项目目录', projectRoot),
readDiskUsage('升级状态目录', stateDir),
].filter((check): check is DiskCheck => Boolean(check));
const byPath = new Map<string, DiskCheck>();
for (const check of checks) {
if (!byPath.has(check.path)) byPath.set(check.path, check);
}
return [...byPath.values()];
}
function readDiskUsage(label: string, targetPath: string): DiskCheck | null {
@@ -139,7 +135,8 @@ function readDiskUsage(label: string, targetPath: string): DiskCheck | null {
if (!Number.isFinite(totalBytes) || !Number.isFinite(availableBytes)) return null;
return {
label,
path: row.slice(5).join(' ') || targetPath,
path: path.resolve(targetPath),
mountPath: row.slice(5).join(' ') || targetPath,
totalBytes,
availableBytes,
usedPercent: Number.isFinite(usedPercent) ? usedPercent : null,

View File

@@ -93,6 +93,7 @@ type RuntimeStatus = {
type DiskCheck = {
label: string;
path: string;
mountPath?: string;
totalBytes: number;
availableBytes: number;
requiredBytes?: number;
@@ -649,6 +650,9 @@ function DiskCheckList({ checks, showRequired = false }: { checks: DiskCheck[];
</span>
</div>
<div className="mt-1 truncate font-mono text-xs text-muted-foreground" title={check.path}>{check.path}</div>
{check.mountPath && check.mountPath !== check.path && (
<div className="mt-1 truncate text-xs text-muted-foreground" title={check.mountPath}> {check.mountPath}</div>
)}
<div className="mt-2 grid gap-2 text-xs text-muted-foreground sm:grid-cols-2">
<span> {formatBytes(check.availableBytes)} / {formatBytes(check.totalBytes)}</span>
{showRequired && typeof check.requiredBytes === 'number' && <span> {formatBytes(check.requiredBytes)}</span>}