Redesign Zed Gist sync workflow
This commit is contained in:
+140
@@ -0,0 +1,140 @@
|
||||
[CmdletBinding()]
|
||||
param()
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$bundleUrl = "https://git.okk.cool/purp1e/zed-sync/raw/branch/master/zed-settings-sync.json"
|
||||
$utf8 = New-Object System.Text.UTF8Encoding($false)
|
||||
|
||||
function Require-Command([string]$Name, [string]$InstallHint) {
|
||||
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
|
||||
throw "$Name is required. Install it first: $InstallHint"
|
||||
}
|
||||
}
|
||||
|
||||
function Test-AllowedPath([string]$Path) {
|
||||
$fixed = @(
|
||||
"settings.json",
|
||||
"keymap.json",
|
||||
"tasks.json",
|
||||
"debug.json",
|
||||
"scripts/toggle-file-scan-exclusions.mjs",
|
||||
"scripts/file-exclusions.json",
|
||||
"scripts/zed-settings-sync.mjs"
|
||||
)
|
||||
$segments = $Path.Split("/")
|
||||
if (
|
||||
$Path.StartsWith("/") -or
|
||||
$Path.Contains("\") -or
|
||||
$segments -contains "" -or
|
||||
$segments -contains "." -or
|
||||
$segments -contains ".."
|
||||
) {
|
||||
return $false
|
||||
}
|
||||
return $fixed -contains $Path -or $Path.StartsWith("snippets/") -or $Path.StartsWith("themes/")
|
||||
}
|
||||
|
||||
function Write-Atomic([string]$Path, [string]$Contents) {
|
||||
$directory = Split-Path $Path -Parent
|
||||
New-Item -ItemType Directory -Force -Path $directory | Out-Null
|
||||
$temporary = Join-Path $directory ".$([IO.Path]::GetFileName($Path)).$PID.tmp"
|
||||
try {
|
||||
[IO.File]::WriteAllText($temporary, $Contents, $utf8)
|
||||
Move-Item -LiteralPath $temporary -Destination $Path -Force
|
||||
} finally {
|
||||
Remove-Item -LiteralPath $temporary -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
Require-Command "node" "winget install OpenJS.NodeJS.LTS"
|
||||
if ($env:ZED_SETTINGS_BUNDLE_PATH) {
|
||||
$bundleSource = [IO.File]::ReadAllText($env:ZED_SETTINGS_BUNDLE_PATH, [Text.Encoding]::UTF8)
|
||||
} else {
|
||||
Write-Host "Downloading the public Zed configuration bundle..."
|
||||
$bundleSource = (Invoke-WebRequest -UseBasicParsing -Uri $bundleUrl).Content
|
||||
}
|
||||
try {
|
||||
$bundle = $bundleSource | ConvertFrom-Json
|
||||
} catch {
|
||||
throw "The downloaded bundle contains invalid JSON: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
$properties = @($bundle.PSObject.Properties)
|
||||
foreach ($required in @("settings.json", "keymap.json", "tasks.json")) {
|
||||
if (-not ($properties.Name -contains $required)) { throw "The bundle is missing $required." }
|
||||
}
|
||||
foreach ($property in $properties) {
|
||||
if (-not (Test-AllowedPath $property.Name) -or $property.Value -isnot [string]) {
|
||||
throw "Invalid bundle file: $($property.Name)"
|
||||
}
|
||||
}
|
||||
|
||||
$target = Join-Path $env:APPDATA "Zed"
|
||||
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
$backup = Join-Path $target "backups\bootstrap-$timestamp"
|
||||
New-Item -ItemType Directory -Force -Path $target, $backup, (Join-Path $target "scripts") | Out-Null
|
||||
|
||||
foreach ($property in $properties) {
|
||||
$existing = Join-Path $target ($property.Name.Replace("/", "\"))
|
||||
if (Test-Path -LiteralPath $existing) {
|
||||
$backupPath = Join-Path $backup ($property.Name.Replace("/", "\"))
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path $backupPath -Parent) | Out-Null
|
||||
Copy-Item -LiteralPath $existing -Destination $backupPath -Force
|
||||
}
|
||||
}
|
||||
|
||||
$toggleScript = (Join-Path $target "scripts\toggle-file-scan-exclusions.mjs").Replace("\", "/")
|
||||
$syncScript = (Join-Path $target "scripts\zed-settings-sync.mjs").Replace("\", "/")
|
||||
foreach ($property in $properties) {
|
||||
$destination = Join-Path $target ($property.Name.Replace("/", "\"))
|
||||
$contents = [string]$property.Value
|
||||
if ($property.Name -eq "tasks.json") {
|
||||
$contents = $contents.Replace("__TOGGLE_SCRIPT__", $toggleScript).Replace("__SYNC_SCRIPT__", $syncScript)
|
||||
}
|
||||
Write-Atomic $destination $contents
|
||||
}
|
||||
|
||||
$statePath = Join-Path $target "scripts\settings-sync.json"
|
||||
if (-not (Test-Path -LiteralPath $statePath)) {
|
||||
$state = [ordered]@{
|
||||
gist_id = ""
|
||||
last_synced_hash = ""
|
||||
auto_sync = $false
|
||||
interval_minutes = 15
|
||||
last_run_at = ""
|
||||
last_result = ""
|
||||
} | ConvertTo-Json
|
||||
Write-Atomic $statePath "$state`n"
|
||||
} else {
|
||||
$existingState = Get-Content -LiteralPath $statePath -Raw | ConvertFrom-Json
|
||||
$state = [ordered]@{
|
||||
gist_id = if ($existingState.gist_id -is [string]) { $existingState.gist_id } else { "" }
|
||||
last_synced_hash = if ($existingState.last_synced_hash -is [string]) { $existingState.last_synced_hash } else { "" }
|
||||
auto_sync = $existingState.auto_sync -eq $true
|
||||
interval_minutes = if ($existingState.interval_minutes -is [int] -and $existingState.interval_minutes -ge 5) { $existingState.interval_minutes } else { 15 }
|
||||
last_run_at = if ($existingState.last_run_at -is [string]) { $existingState.last_run_at } else { "" }
|
||||
last_result = if ($existingState.last_result -is [string]) { $existingState.last_result } else { "" }
|
||||
} | ConvertTo-Json
|
||||
Write-Atomic $statePath "$state`n"
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Installed Zed settings to $target"
|
||||
Write-Host "Previous settings were backed up to $backup"
|
||||
Write-Host "GitHub and Gist setup are optional and did not block installation."
|
||||
|
||||
if ($env:ZED_SYNC_SKIP_SETUP -ne "1") {
|
||||
try {
|
||||
$answer = Read-Host "Run the GitHub sync setup now? [Y/n]"
|
||||
if ([string]::IsNullOrWhiteSpace($answer) -or $answer -match "^[Yy]") {
|
||||
& node $syncScript setup
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Warning "Sync setup did not complete. Local installation is still valid; run the setup Task from Zed later."
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Warning "Could not start interactive sync setup. Run 'Zed Settings: Set Up / Reconfigure Sync...' from Zed later."
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Restart or reload Zed to use the installed configuration."
|
||||
Reference in New Issue
Block a user