137 lines
4.9 KiB
PowerShell
137 lines
4.9 KiB
PowerShell
|
|
# =============================================================================
|
|||
|
|
# Bookworm .claude 同步 - 阶段 1: 本机打包 + HTTP 服务
|
|||
|
|
# 在源机器 (leesu) 上运行
|
|||
|
|
# =============================================================================
|
|||
|
|
[CmdletBinding()]
|
|||
|
|
param(
|
|||
|
|
[string]$SourceUser = $env:USERNAME,
|
|||
|
|
[int]$Port = 8765,
|
|||
|
|
[switch]$NoServe # 加这个开关只打包不起服务
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
$ErrorActionPreference = 'Stop'
|
|||
|
|
|
|||
|
|
$src = "C:\Users\$SourceUser\.claude"
|
|||
|
|
$staging = "$env:TEMP\claude-sync-staging"
|
|||
|
|
$zip = "$env:TEMP\claude-sync.zip"
|
|||
|
|
|
|||
|
|
if (-not (Test-Path $src)) {
|
|||
|
|
Write-Host "❌ 源目录不存在: $src" -ForegroundColor Red
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Write-Host "==================== 阶段 1: 打包 ====================" -ForegroundColor Cyan
|
|||
|
|
Write-Host "源: $src"
|
|||
|
|
Write-Host "目标 zip: $zip"
|
|||
|
|
Write-Host ""
|
|||
|
|
|
|||
|
|
# ---------- 1) 清理旧暂存 ----------
|
|||
|
|
Write-Host "[1/5] 清理旧暂存..." -ForegroundColor Yellow
|
|||
|
|
Remove-Item $staging, $zip -Recurse -Force -ErrorAction SilentlyContinue
|
|||
|
|
New-Item $staging -ItemType Directory -Force | Out-Null
|
|||
|
|
|
|||
|
|
# ---------- 2) 构建排除列表 ----------
|
|||
|
|
Write-Host "[2/5] 构建排除列表..." -ForegroundColor Yellow
|
|||
|
|
|
|||
|
|
# 必排除目录 (顶层)
|
|||
|
|
$excludeTopDirs = @(
|
|||
|
|
"$src\.git",
|
|||
|
|
"$src\node_modules",
|
|||
|
|
"$src\.skill-cache"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 排除每个 mcp-server 下的 .venv / __pycache__ / node_modules (保留源码)
|
|||
|
|
$mcpExcludes = @()
|
|||
|
|
if (Test-Path "$src\mcp-servers") {
|
|||
|
|
Get-ChildItem "$src\mcp-servers" -Directory | ForEach-Object {
|
|||
|
|
$mcpExcludes += "$($_.FullName)\.venv"
|
|||
|
|
$mcpExcludes += "$($_.FullName)\__pycache__"
|
|||
|
|
$mcpExcludes += "$($_.FullName)\node_modules"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 排除每个 skill 下的 node_modules / dist / .git (保留源码)
|
|||
|
|
$skillExcludes = @()
|
|||
|
|
if (Test-Path "$src\skills") {
|
|||
|
|
Get-ChildItem "$src\skills" -Directory | ForEach-Object {
|
|||
|
|
$skillExcludes += "$($_.FullName)\node_modules"
|
|||
|
|
$skillExcludes += "$($_.FullName)\dist"
|
|||
|
|
$skillExcludes += "$($_.FullName)\.git"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 排除文件类型
|
|||
|
|
$excludeFiles = @(
|
|||
|
|
'*.dpapi.json', # DPAPI 机器绑定,无法跨机器解密
|
|||
|
|
'*.bak.*', # 临时备份文件
|
|||
|
|
'Thumbs.db','desktop.ini' # OS 残留
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
$xdArgs = $excludeTopDirs + $mcpExcludes + $skillExcludes
|
|||
|
|
|
|||
|
|
# ---------- 3) robocopy 复制 ----------
|
|||
|
|
Write-Host "[3/5] 复制中(约 1-3 分钟)..." -ForegroundColor Yellow
|
|||
|
|
$rcArgs = @($src, $staging, '/E', '/XD') + $xdArgs + @('/XF') + $excludeFiles + @('/NFL','/NDL','/NJH','/NJS','/NC','/NS','/NP','/R:1','/W:1')
|
|||
|
|
$rcExit = (Start-Process robocopy -ArgumentList $rcArgs -NoNewWindow -Wait -PassThru).ExitCode
|
|||
|
|
# robocopy exit code < 8 都是成功
|
|||
|
|
if ($rcExit -ge 8) {
|
|||
|
|
Write-Host "❌ robocopy 失败 (exit=$rcExit)" -ForegroundColor Red
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 排除 hooks 测试 / 归档 / 废弃
|
|||
|
|
Remove-Item "$staging\hooks\__tests__","$staging\hooks\archive","$staging\hooks\deprecated" -Recurse -Force -ErrorAction SilentlyContinue
|
|||
|
|
|
|||
|
|
# 统计
|
|||
|
|
$stat = Get-ChildItem $staging -Recurse -File -ErrorAction SilentlyContinue | Measure-Object Length -Sum
|
|||
|
|
Write-Host " 暂存: $([Math]::Round($stat.Sum / 1MB, 1)) MB / $($stat.Count) 文件"
|
|||
|
|
|
|||
|
|
# ---------- 4) 压缩 ----------
|
|||
|
|
Write-Host "[4/5] 压缩中(文件多时 2-5 分钟)..." -ForegroundColor Yellow
|
|||
|
|
Compress-Archive -Path "$staging\*" -DestinationPath $zip -Force -CompressionLevel Optimal
|
|||
|
|
|
|||
|
|
$zipSize = [Math]::Round((Get-Item $zip).Length / 1MB, 1)
|
|||
|
|
Write-Host " ✅ $zip ($zipSize MB)" -ForegroundColor Green
|
|||
|
|
|
|||
|
|
# ---------- 5) 起 HTTP 服务 ----------
|
|||
|
|
if ($NoServe) {
|
|||
|
|
Write-Host "[5/5] 跳过 HTTP 服务(-NoServe 已指定)" -ForegroundColor Yellow
|
|||
|
|
Write-Host ""
|
|||
|
|
Write-Host "✅ 打包完成。手动传输 $zip 到目标机器即可。" -ForegroundColor Green
|
|||
|
|
exit 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Write-Host "[5/5] 启动 HTTP 服务..." -ForegroundColor Yellow
|
|||
|
|
|
|||
|
|
# 获取本机 LAN IP
|
|||
|
|
$lanIP = (Get-NetIPAddress -AddressFamily IPv4 |
|
|||
|
|
Where-Object {
|
|||
|
|
$_.IPAddress -notlike '169.254.*' -and
|
|||
|
|
$_.IPAddress -ne '127.0.0.1' -and
|
|||
|
|
$_.IPAddress -notlike '198.18.*' -and
|
|||
|
|
$_.IPAddress -notlike '172.*'
|
|||
|
|
} |
|
|||
|
|
Select-Object -First 1).IPAddress
|
|||
|
|
|
|||
|
|
Write-Host ""
|
|||
|
|
Write-Host "================ 服务就绪 ================" -ForegroundColor Green
|
|||
|
|
Write-Host " 目标机器请运行 2-pull-and-rebuild.ps1,"
|
|||
|
|
Write-Host " 或手动下载: " -NoNewline
|
|||
|
|
Write-Host "http://${lanIP}:${Port}/claude-sync.zip" -ForegroundColor Cyan
|
|||
|
|
Write-Host ""
|
|||
|
|
Write-Host " 传输完成后回到此窗口按 Ctrl+C 停止服务" -ForegroundColor Yellow
|
|||
|
|
Write-Host "==========================================" -ForegroundColor Green
|
|||
|
|
Write-Host ""
|
|||
|
|
|
|||
|
|
# 切到 TEMP 目录起服务
|
|||
|
|
Push-Location $env:TEMP
|
|||
|
|
try {
|
|||
|
|
python -m http.server $Port
|
|||
|
|
} finally {
|
|||
|
|
Pop-Location
|
|||
|
|
Write-Host ""
|
|||
|
|
Write-Host "🧹 清理暂存..." -ForegroundColor Yellow
|
|||
|
|
Remove-Item $staging -Recurse -Force -ErrorAction SilentlyContinue
|
|||
|
|
Write-Host "✅ 暂存已清。zip 保留在: $zip" -ForegroundColor Green
|
|||
|
|
}
|