Merge pull request #276 from pikasTech/fix/vscode-vsix-gc-retention
gc: VS Code VSIX 缓存 retention
This commit is contained in:
@@ -86,13 +86,14 @@ bun scripts/cli.ts gc plan --target-use-percent 69 \
|
||||
--include-stale-tmp \
|
||||
--include-vscode-stale-servers \
|
||||
--include-vscode-stale-extensions \
|
||||
--include-vscode-cached-vsix \
|
||||
--include-baidu-staging \
|
||||
--include-vpn-diagnostic-logs
|
||||
```
|
||||
|
||||
`--target-use-percent` 按 `df` 显示口径估算 shortfall。工具缓存、`/tmp` 非 allowlist 直接子项、VS Code 历史 server/extension 版本、Baidu staging 旧 PGDATA tarball、UniDesk `.state` 历史诊断/部署产物、VPN 诊断 ring pcap 均默认不启用;必须显式 include 后才进入候选,且执行时仍受路径断言保护。stale `/tmp` 扫描按 `--limit` 有界枚举候选,避免为了估算全量临时目录而长时间无输出。`.state` retention 只通过 `--include-state-artifacts --state-artifact-keep-days N` 选择 `.state/e2e`、`.state/validation`、`.state/jobs`、`.state/codex-queue/output-archive` 下超过保留期的普通文件,以及 `.state/deploy/exports`、`.state/deploy/resolve` 下超过保留期的直接子目录;默认保留期 14 天。VPN 诊断日志只选择 `/root/vpn-server/logs/hy2-udp-ring-*.pcap` 和 `hy2-monitor-ring-*.pcap` 中超过 `--vpn-diagnostic-log-keep-hours` 的普通文件,执行前检查 active fd;不删除 evidence JSONL。默认 GC 不触碰 `.state/recovery`、`.state/codex-queue/codex-home`、`.state/deploy/work`、`.state/baidu-netdisk`、PGDATA、Docker volumes/images、Codex sessions/auth state、active worktree、runtime image/snapshot state、Baidu staging 根目录或 VPN 日志根目录。
|
||||
`--target-use-percent` 按 `df` 显示口径估算 shortfall。工具缓存、`/tmp` 非 allowlist 直接子项、VS Code 历史 server/extension 版本、VS Code CachedExtensionVSIXs 下载缓存、Baidu staging 旧 PGDATA tarball、UniDesk `.state` 历史诊断/部署产物、VPN 诊断 ring pcap 均默认不启用;必须显式 include 后才进入候选,且执行时仍受路径断言保护。stale `/tmp` 扫描按 `--limit` 有界枚举候选,避免为了估算全量临时目录而长时间无输出。`.state` retention 只通过 `--include-state-artifacts --state-artifact-keep-days N` 选择 `.state/e2e`、`.state/validation`、`.state/jobs`、`.state/codex-queue/output-archive` 下超过保留期的普通文件,以及 `.state/deploy/exports`、`.state/deploy/resolve` 下超过保留期的直接子目录;默认保留期 14 天。VS Code cached VSIX 只选择 `/root/.vscode-server/data/CachedExtensionVSIXs` 下超过 `--vscode-cached-vsix-keep-days` 的顶层普通缓存文件,执行前检查 active fd;不删除已安装 extensions、server 或 user data。VPN 诊断日志只选择 `/root/vpn-server/logs/hy2-udp-ring-*.pcap` 和 `hy2-monitor-ring-*.pcap` 中超过 `--vpn-diagnostic-log-keep-hours` 的普通文件,执行前检查 active fd;不删除 evidence JSONL。默认 GC 不触碰 `.state/recovery`、`.state/codex-queue/codex-home`、`.state/deploy/work`、`.state/baidu-netdisk`、PGDATA、Docker volumes/images、Codex sessions/auth state、active worktree、runtime image/snapshot state、Baidu staging 根目录、VPN 日志根目录或 VS Code user data。
|
||||
|
||||
`gc policy install` 的每日 timer 会自动执行 24 小时 VPN 诊断 pcap retention 和 14 天 UniDesk `.state` artifact retention,用于限制长期诊断/部署产物增长;手动 `gc plan/run` 仍必须显式 `--include-vpn-diagnostic-logs` 或 `--include-state-artifacts` 才会列出或删除这些对象。
|
||||
`gc policy install` 的每日 timer 会自动执行 24 小时 VPN 诊断 pcap retention、14 天 UniDesk `.state` artifact retention 和 7 天 VS Code CachedExtensionVSIXs retention,用于限制长期诊断/部署产物、tcpdump ring 文件与 VS Code 下载缓存增长;手动 `gc plan/run` 仍必须显式 `--include-vpn-diagnostic-logs` / `--include-state-artifacts` / `--include-vscode-cached-vsix` 才会列出或删除这些对象。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ UniDesk 的磁盘治理入口是 `bun scripts/cli.ts gc ...`。该入口用于
|
||||
|
||||
- `gc plan`:只读生成主 server 清理候选、估算收益、风险等级、保护对象和数据库诊断摘要。
|
||||
- `gc run --confirm`:只执行当前 plan 可见候选页,默认不执行分页隐藏候选;用 `--limit`、`--result-limit`、`--full|--raw` 控制披露和执行范围。
|
||||
- `gc policy plan|install`:渲染或安装低风险长期策略,例如 journald cap、每日 allowlisted 文件/tmp 清理 timer、24 小时 VPN 诊断 pcap retention 和 14 天 `.state` artifact retention。
|
||||
- `gc policy plan|install`:渲染或安装低风险长期策略,例如 journald cap、每日 allowlisted 文件/tmp 清理 timer、24 小时 VPN 诊断 pcap retention、14 天 `.state` artifact retention 和 VS Code CachedExtensionVSIXs 下载缓存 retention。
|
||||
- `gc db-trace plan|run --confirm --before-date YYYY-MM-DD --vacuum-full`:显式 trace 遥测留存入口;涉及数据库重写时按维护窗口处理。
|
||||
- `gc remote <providerId> plan|run --confirm|status --job-id <id>`:通过 UniDesk SSH 透传在 provider host 上执行受控 GC。远端长任务必须使用异步 job 和 `status` 短查询,不应让单次 SSH 等待完整 registry GC 或其他长清理。
|
||||
|
||||
@@ -29,6 +29,8 @@ UniDesk 的磁盘治理入口是 `bun scripts/cli.ts gc ...`。该入口用于
|
||||
|
||||
`gc run --confirm --include-state-artifacts` 执行前必须重新校验路径、保留期、对象类型和 symlink 状态。文件候选必须仍是 allowlist 根下的普通文件;deploy 目录候选必须仍是 `.state/deploy/exports` 或 `.state/deploy/resolve` 的直接子目录。该入口不得递归扩大成通用 `.state` 清空器,也不得选择 `.state` 根目录、allowlist 之外的目录、symlink、active worktree、runtime image 或 snapshot 状态。
|
||||
|
||||
主 server VS Code 下载缓存默认不清理。`/root/.vscode-server/data/CachedExtensionVSIXs` 只用于 VS Code extension VSIX 下载缓存,可通过显式 `--include-vscode-cached-vsix` 进入候选;执行时只允许删除该目录下符合 extension-version 命名的顶层普通文件,并按 `--vscode-cached-vsix-keep-days` 保留近期缓存。执行前必须重新校验路径、文件名、非 symlink/regular file,并用 active-file 检查确认没有进程仍打开该文件。该入口不得触碰 `/root/.vscode-server/extensions`、`/root/.vscode-server/cli/servers`、VS Code user data 或任意 session/auth state。
|
||||
|
||||
## Protected Data
|
||||
|
||||
默认 GC 不得删除或 prune 以下对象:
|
||||
@@ -44,6 +46,7 @@ UniDesk 的磁盘治理入口是 `bun scripts/cli.ts gc ...`。该入口用于
|
||||
| active worktree、runtime image、runtime snapshot state | 当前执行面和运行面 provenance,不通过 `.state` artifact retention 删除 |
|
||||
| Codex sessions/auth | `~/.codex/sessions`、`~/.codex/auth.json` 等凭证和会话状态 |
|
||||
| VPN diagnostic evidence logs | `/root/vpn-server/logs/hy2-server-evidence.jsonl` 等 active evidence 流用于网络排障,不随 pcap retention 删除 |
|
||||
| VS Code installed extensions/server/user data | 已安装扩展、server 版本和用户配置不是下载缓存,只能由专门 stale-version 规则或 VS Code 自身管理 |
|
||||
| D601 registry storage | artifact registry retention 需使用专门入口 |
|
||||
| `/var/lib/rancher/k3s` 与 `/var/lib/rancher/k3s/storage` | k3s 控制面、containerd 状态和 local-path PVC 数据 |
|
||||
| `/var/lib/kubelet`、`/var/lib/containerd` | kubelet/runtime 状态和可能被 workload 复用的 image cache |
|
||||
@@ -52,7 +55,7 @@ UniDesk 的磁盘治理入口是 `bun scripts/cli.ts gc ...`。该入口用于
|
||||
|
||||
如果需要触碰上表对象,必须先补高层 UniDesk CLI 子命令、dry-run 计划、保护对象、验证命令和失败分类;不能把原生 `kubectl`、`docker prune`、`crictl rmi` 或手写 registry shell 作为长期流程。
|
||||
|
||||
`gc policy install` 的每日 timer 会启用 14 天 `.state` artifact retention,用来限制历史诊断和部署产物长期增长;手动 `gc plan/run` 仍默认不清 `.state`,必须显式 `--include-state-artifacts` 才会列出或执行这些候选。policy timer 仍保护上表对象,并把输出限制在 `.state/gc/last-run.json` 和 `.state/gc/last-run.stderr`。
|
||||
`gc policy install` 的每日 timer 会启用 14 天 `.state` artifact retention 和 7 天 VS Code CachedExtensionVSIXs retention,用来限制历史诊断/部署产物与 VS Code 下载缓存长期增长;手动 `gc plan/run` 仍默认不清 `.state` 或 VSIX 缓存,必须显式 `--include-state-artifacts` / `--include-vscode-cached-vsix` 才会列出或执行这些候选。policy timer 仍保护上表对象,并把输出限制在 `.state/gc/last-run.json` 和 `.state/gc/last-run.stderr`。
|
||||
|
||||
## Remote G14 Policy
|
||||
|
||||
@@ -255,6 +258,7 @@ bun scripts/cli.ts hwlab g14 control-plane cleanup-released-pvs --lane all --lim
|
||||
| CI tag growth cap | 每个 service 对 commit tag 增长设置上限并进入 GC plan | 防止 registry 每周持续膨胀 |
|
||||
| Tekton/Pipeline retention | 完成态 PipelineRun/TaskRun/Job 按留存期清理 | 释放少量空间,降低 API 噪声 |
|
||||
| Log/journal cap | journald 上限、文件日志轮转、Docker json log truncate | 稳定防止日志膨胀,收益通常为数百 MiB 到数 GiB |
|
||||
| VS Code CachedExtensionVSIXs retention | 只清理可重建 extension VSIX 下载缓存,不触碰已安装扩展/server/user data | 防止远程 VS Code 扩展升级缓存长期堆积,收益通常为数百 MiB |
|
||||
| Core dump limits | 限制 dump 大小或按 allowlist 删除实际分配块 | 防止 crash dump 污染观测;sparse dump 不应被高估 |
|
||||
| Containerd image audit | 定期只读报告 runtime image cache 构成 | 为维护窗口 prune 提供证据,不默认删除 |
|
||||
| Worktree TTL audit | 报告 `.worktree` owner、branch、dirty 和 node_modules/cache 占用 | 为安全清理并行任务 scratch 提供证据 |
|
||||
|
||||
+79
-4
@@ -18,6 +18,7 @@ type GcItemKind =
|
||||
| "tool-cache-delete"
|
||||
| "vscode-server-delete"
|
||||
| "vscode-extension-delete"
|
||||
| "vscode-cached-vsix-delete"
|
||||
| "baidu-staging-file-delete"
|
||||
| "state-artifact-file-delete"
|
||||
| "state-artifact-dir-delete"
|
||||
@@ -44,6 +45,8 @@ interface GcOptions {
|
||||
vscodeKeepServers: number;
|
||||
vscodeStaleExtensions: boolean;
|
||||
vscodeKeepExtensionVersions: number;
|
||||
vscodeCachedVsix: boolean;
|
||||
vscodeCachedVsixKeepDays: number;
|
||||
baiduStaging: boolean;
|
||||
baiduStagingKeepDays: number;
|
||||
stateArtifacts: boolean;
|
||||
@@ -185,6 +188,8 @@ const DEFAULT_OPTIONS: GcOptions = {
|
||||
vscodeKeepServers: 2,
|
||||
vscodeStaleExtensions: false,
|
||||
vscodeKeepExtensionVersions: 1,
|
||||
vscodeCachedVsix: false,
|
||||
vscodeCachedVsixKeepDays: 7,
|
||||
baiduStaging: false,
|
||||
baiduStagingKeepDays: 10,
|
||||
stateArtifacts: false,
|
||||
@@ -305,6 +310,7 @@ const TOOL_CACHE_ALLOWLIST = [
|
||||
|
||||
const VSCODE_SERVER_ROOT = "/root/.vscode-server/cli/servers";
|
||||
const VSCODE_EXTENSION_ROOT = "/root/.vscode-server/extensions";
|
||||
const VSCODE_CACHED_VSIX_ROOT = "/root/.vscode-server/data/CachedExtensionVSIXs";
|
||||
const BAIDU_STAGING_RELATIVE_ROOT = [".state", "baidu-netdisk", "staging"];
|
||||
const STATE_ARTIFACT_FILE_ROOTS = [
|
||||
{ id: "e2e", relativeRoot: [".state", "e2e"] },
|
||||
@@ -473,6 +479,20 @@ export function gcPlan(config: UniDeskConfig, options: GcOptions = DEFAULT_OPTIO
|
||||
});
|
||||
}
|
||||
}
|
||||
if (options.vscodeCachedVsix) {
|
||||
candidates.push(...collectVscodeCachedVsixCandidates(options, observedAt));
|
||||
} else {
|
||||
const cachedVsixSize = safePathSize(VSCODE_CACHED_VSIX_ROOT);
|
||||
if (cachedVsixSize > 0) {
|
||||
protectedItems.push({
|
||||
kind: "vscode-cached-vsix-cache",
|
||||
risk: "blocked",
|
||||
ref: VSCODE_CACHED_VSIX_ROOT,
|
||||
sizeBytes: cachedVsixSize,
|
||||
reason: "VS Code CachedExtensionVSIXs download cache is not removed by default; rerun with --include-vscode-cached-vsix to remove stale cached VSIX files only.",
|
||||
});
|
||||
}
|
||||
}
|
||||
if (options.baiduStaging) {
|
||||
candidates.push(...collectBaiduStagingCandidates(options, observedAt));
|
||||
}
|
||||
@@ -523,7 +543,7 @@ export function gcPlan(config: UniDeskConfig, options: GcOptions = DEFAULT_OPTIO
|
||||
notes: [
|
||||
"gc run only executes listed one-time cleanup actions after --confirm.",
|
||||
options.full ? "Full candidate output requested." : `Default output is capped to ${options.limit} candidates; use --full or --limit N for broader disclosure.`,
|
||||
"Tool caches, stale /tmp direct children, stale VS Code server versions and stale VS Code extension versions are opt-in and require explicit include flags.",
|
||||
"Tool caches, stale /tmp direct children, stale VS Code server versions, stale VS Code extension versions and stale VS Code cached VSIX downloads are opt-in and require explicit include flags.",
|
||||
"Baidu Netdisk staging cleanup is opt-in and only selects old PGDATA backup tarballs under server-data/unidesk-pg-data.",
|
||||
"State artifact retention is opt-in for manual plan/run; --include-state-artifacts selects only stale files under .state/e2e, .state/validation, .state/jobs and .state/codex-queue/output-archive plus stale direct directories under .state/deploy/exports and .state/deploy/resolve.",
|
||||
"VPN diagnostic pcap cleanup is opt-in and only selects stale hy2 ring pcap files; active pcap files and evidence JSONL are protected.",
|
||||
@@ -634,6 +654,12 @@ function parseGcOptions(args: string[]): GcOptions {
|
||||
const value = parseNonNegativeNumber(arg, args[++index]);
|
||||
if (!Number.isInteger(value) || value <= 0) throw new Error("--vscode-keep-extension-versions must be a positive integer");
|
||||
options.vscodeKeepExtensionVersions = Math.min(value, 20);
|
||||
} else if (arg === "--include-vscode-cached-vsix") {
|
||||
options.vscodeCachedVsix = true;
|
||||
} else if (arg === "--no-vscode-cached-vsix") {
|
||||
options.vscodeCachedVsix = false;
|
||||
} else if (arg === "--vscode-cached-vsix-keep-days") {
|
||||
options.vscodeCachedVsixKeepDays = parsePositiveIntegerOption(arg, args[++index], 365);
|
||||
} else if (arg === "--target-use-percent") {
|
||||
options.targetUsePercent = parseUsePercentOption(arg, args[++index]);
|
||||
} else if (arg === "--include-baidu-staging") {
|
||||
@@ -794,6 +820,8 @@ function publicOptions(options: GcOptions): Record<string, unknown> {
|
||||
vscodeKeepServers: options.vscodeKeepServers,
|
||||
vscodeStaleExtensions: options.vscodeStaleExtensions,
|
||||
vscodeKeepExtensionVersions: options.vscodeKeepExtensionVersions,
|
||||
vscodeCachedVsix: options.vscodeCachedVsix,
|
||||
vscodeCachedVsixKeepDays: options.vscodeCachedVsixKeepDays,
|
||||
baiduStaging: options.baiduStaging,
|
||||
baiduStagingKeepDays: options.baiduStagingKeepDays,
|
||||
stateArtifacts: options.stateArtifacts,
|
||||
@@ -1108,6 +1136,35 @@ function vscodeExtensionIdFromDirectory(name: string): string | null {
|
||||
return match?.[1] ?? null;
|
||||
}
|
||||
|
||||
function collectVscodeCachedVsixCandidates(options: GcOptions, observedAt: string): GcCandidate[] {
|
||||
if (!existsSync(VSCODE_CACHED_VSIX_ROOT)) return [];
|
||||
const cutoffMs = new Date(observedAt).getTime() - options.vscodeCachedVsixKeepDays * 24 * 60 * 60 * 1000;
|
||||
const result: GcCandidate[] = [];
|
||||
for (const entry of readdirSync(VSCODE_CACHED_VSIX_ROOT, { withFileTypes: true })) {
|
||||
if (!entry.isFile()) continue;
|
||||
if (vscodeExtensionIdFromDirectory(entry.name) === null) continue;
|
||||
const path = join(VSCODE_CACHED_VSIX_ROOT, entry.name);
|
||||
let stat;
|
||||
try {
|
||||
stat = lstatSync(path);
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
if (!stat.isFile() || stat.isSymbolicLink() || stat.mtimeMs >= cutoffMs || stat.size <= 0) continue;
|
||||
result.push({
|
||||
id: `vscode-cached-vsix:${entry.name}`,
|
||||
kind: "vscode-cached-vsix-delete",
|
||||
risk: "medium",
|
||||
description: `Delete stale VS Code CachedExtensionVSIXs download older than ${options.vscodeCachedVsixKeepDays} days`,
|
||||
path,
|
||||
sizeBytes: stat.size,
|
||||
estimatedReclaimBytes: stat.size,
|
||||
action: { op: "unlink", allowlist: "vscode-cached-vsix", keepDays: options.vscodeCachedVsixKeepDays, activeCheck: "fuser-before-delete" },
|
||||
});
|
||||
}
|
||||
return result.sort((left, right) => right.estimatedReclaimBytes - left.estimatedReclaimBytes);
|
||||
}
|
||||
|
||||
function collectBaiduStagingCandidates(options: GcOptions, observedAt: string): GcCandidate[] {
|
||||
const root = rootPath(...BAIDU_STAGING_RELATIVE_ROOT);
|
||||
const pgdataRoot = join(root, "server-data", "unidesk-pg-data");
|
||||
@@ -1486,8 +1543,8 @@ function gcPolicyPlan(options: GcPolicyOptions): unknown {
|
||||
policy: {
|
||||
safeScope: [
|
||||
"systemd journal is capped at 512MiB",
|
||||
"daily timer runs file-log, Docker json logs, 24h BuildKit cache, allowlisted /tmp gc, 24h VPN diagnostic pcap retention and 14-day UniDesk .state artifact retention",
|
||||
"timer does not touch PostgreSQL PGDATA, Docker images, Docker volumes, tool caches, VS Code servers/extensions or Baidu Netdisk staging",
|
||||
"daily timer runs file-log, Docker json logs, 24h BuildKit cache, allowlisted /tmp gc, 24h VPN diagnostic pcap retention, 14-day UniDesk .state artifact retention and 7d VS Code CachedExtensionVSIXs retention",
|
||||
"timer does not touch PostgreSQL PGDATA, Docker images, Docker volumes, tool caches, installed VS Code servers/extensions, VS Code user data or Baidu Netdisk staging",
|
||||
"timer output is redirected under .state/gc and capped by gc --result-limit",
|
||||
],
|
||||
manualDbRetention: "gc db-trace remains explicit maintenance and is not scheduled automatically.",
|
||||
@@ -1538,7 +1595,7 @@ function gcPolicyInstall(options: GcPolicyOptions): unknown {
|
||||
function gcPolicyFiles(): Record<string, { path: string; content: string }> {
|
||||
const gcStateDir = rootPath(".state", "gc");
|
||||
const bunPath = bunExecutablePath();
|
||||
const gcScript = `cd ${shellQuote(repoRoot)} && mkdir -p ${shellQuote(gcStateDir)} && ${shellQuote(bunPath)} scripts/cli.ts gc run --confirm --no-db-summary --no-journal --build-cache-until 24h --include-vpn-diagnostic-logs --vpn-diagnostic-log-keep-hours 24 --include-state-artifacts --state-artifact-keep-days 14 --limit 5000 --result-limit 25 > ${shellQuote(join(gcStateDir, "last-run.json"))} 2> ${shellQuote(join(gcStateDir, "last-run.stderr"))}`;
|
||||
const gcScript = `cd ${shellQuote(repoRoot)} && mkdir -p ${shellQuote(gcStateDir)} && ${shellQuote(bunPath)} scripts/cli.ts gc run --confirm --no-db-summary --no-journal --build-cache-until 24h --include-vpn-diagnostic-logs --vpn-diagnostic-log-keep-hours 24 --include-state-artifacts --state-artifact-keep-days 14 --include-vscode-cached-vsix --vscode-cached-vsix-keep-days 7 --limit 5000 --result-limit 25 > ${shellQuote(join(gcStateDir, "last-run.json"))} 2> ${shellQuote(join(gcStateDir, "last-run.stderr"))}`;
|
||||
return {
|
||||
journald: {
|
||||
path: "/etc/systemd/journald.conf.d/unidesk-gc.conf",
|
||||
@@ -1678,6 +1735,13 @@ function executeCandidate(candidate: GcCandidate, options: GcOptions): { reclaim
|
||||
rmSync(candidate.path, { recursive: true, force: true });
|
||||
return { reclaimedBytes: before };
|
||||
}
|
||||
if (candidate.kind === "vscode-cached-vsix-delete" && candidate.path !== undefined) {
|
||||
assertVscodeCachedVsixCandidatePath(candidate.path);
|
||||
assertPathNotOpen(candidate.path);
|
||||
const before = safeFileSize(candidate.path);
|
||||
unlinkSync(candidate.path);
|
||||
return { reclaimedBytes: before };
|
||||
}
|
||||
if (candidate.kind === "baidu-staging-file-delete" && candidate.path !== undefined) {
|
||||
assertBaiduStagingCandidatePath(candidate.path);
|
||||
const before = safeFileSize(candidate.path);
|
||||
@@ -1791,6 +1855,17 @@ function assertVscodeExtensionCandidatePath(path: string): void {
|
||||
if (vscodeExtensionIdFromDirectory(basename(resolved)) === null) throw new Error(`refusing to remove unexpected VS Code extension directory: ${path}`);
|
||||
}
|
||||
|
||||
function assertVscodeCachedVsixCandidatePath(path: string): void {
|
||||
const resolved = resolve(path);
|
||||
const root = resolve(VSCODE_CACHED_VSIX_ROOT);
|
||||
if (!resolved.startsWith(`${root}/`)) throw new Error(`refusing to remove VS Code cached VSIX outside cache root: ${path}`);
|
||||
const relativePath = resolved.slice(root.length + 1);
|
||||
if (relativePath.includes("/")) throw new Error(`refusing to remove nested VS Code cached VSIX path: ${path}`);
|
||||
if (vscodeExtensionIdFromDirectory(basename(resolved)) === null) throw new Error(`refusing to remove unexpected VS Code cached VSIX name: ${path}`);
|
||||
const stat = lstatSync(resolved);
|
||||
if (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`refusing to remove non-regular VS Code cached VSIX: ${path}`);
|
||||
}
|
||||
|
||||
function assertBaiduStagingCandidatePath(path: string): void {
|
||||
const resolved = resolve(path);
|
||||
const root = resolve(rootPath(...BAIDU_STAGING_RELATIVE_ROOT, "server-data", "unidesk-pg-data"));
|
||||
|
||||
Reference in New Issue
Block a user