Public/Sharing.ps1
|
# PSSnips — Shared snippet storage (Publish-Snip, Sync-SharedSnips). function Publish-Snip { <# .SYNOPSIS Copies a local snippet to the configured shared storage directory. .DESCRIPTION Copies the snippet file to SharedSnippetsDir and updates shared-index.json in the shared directory with the snippet's metadata. .PARAMETER Name Mandatory. The local snippet name to publish. .PARAMETER Force Optional switch. Overwrites the snippet in shared storage if it already exists. .EXAMPLE Publish-Snip my-snippet .EXAMPLE Publish-Snip my-snippet -Force .INPUTS None. .OUTPUTS None. .NOTES SharedSnippetsDir must be set via Set-SnipConfig -SharedSnippetsDir <path>. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, Position=0, HelpMessage='Local snippet name to publish to shared storage')] [ValidateNotNullOrEmpty()] [string]$Name, [switch]$Force ) script:InitEnv $sharedDir = script:GetSharedDir if (-not $sharedDir) { return } $idx = script:LoadIdx if (-not $idx.snippets.ContainsKey($Name)) { Write-Error "Snippet '$Name' not found." -ErrorAction Continue; return } $srcPath = script:FindFile -Name $Name if (-not $srcPath -or -not (Test-Path $srcPath)) { Write-Error "Snippet file for '$Name' not found." -ErrorAction Continue; return } $destFile = Join-Path $sharedDir (Split-Path $srcPath -Leaf) if ((Test-Path $destFile) -and -not $Force) { script:Out-Warn "Snippet '$Name' already exists in shared storage. Use -Force to overwrite." return } if ($PSCmdlet.ShouldProcess($destFile, "Publish snippet '$Name'")) { Copy-Item $srcPath $destFile -Force # Update shared-index.json with advisory lock + atomic write $sharedIdxFile = Join-Path $sharedDir 'shared-index.json' $sharedIdx = if (Test-Path $sharedIdxFile) { try { $raw = Get-Content $sharedIdxFile -Raw -Encoding UTF8 -ErrorAction Stop if ($raw) { $si = $raw | ConvertFrom-Json -AsHashtable if (-not $si.ContainsKey('snippets')) { $si['snippets'] = @{} } $si } else { @{ snippets = @{} } } } catch { @{ snippets = @{} } } } else { @{ snippets = @{} } } $sharedIdx['snippets'][$Name] = if ($idx.snippets[$Name] -is [SnippetMetadata]) { $idx.snippets[$Name].ToHashtable() } else { $idx.snippets[$Name] } $sharedLockFile = "$sharedIdxFile.lock" $sharedLock = script:AcquireLock -LockFile $sharedLockFile try { $sharedTmp = "$sharedIdxFile.tmp" $sharedIdx | ConvertTo-Json -Depth 10 | Set-Content -Path $sharedTmp -Encoding UTF8 Move-Item -Path $sharedTmp -Destination $sharedIdxFile -Force } finally { script:ReleaseLock -Stream $sharedLock -LockFile $sharedLockFile if (Test-Path "$sharedIdxFile.tmp") { Remove-Item "$sharedIdxFile.tmp" -ErrorAction SilentlyContinue } } script:Out-OK "Published '$Name' to shared storage: $destFile" } } function Sync-SharedSnips { <# .SYNOPSIS Imports snippets from shared storage into the local snippet collection. .DESCRIPTION Reads shared-index.json from SharedSnippetsDir and copies any snippet not present locally (or all snippets with -Force) into the local collection. .PARAMETER Force Optional switch. Imports all shared snippets, overwriting local ones. .EXAMPLE Sync-SharedSnips .EXAMPLE Sync-SharedSnips -Force .INPUTS None. .OUTPUTS None. .NOTES SharedSnippetsDir must be set via Set-SnipConfig -SharedSnippetsDir <path>. #> [CmdletBinding(SupportsShouldProcess)] param( [switch]$Force ) script:InitEnv $sharedDir = script:GetSharedDir if (-not $sharedDir) { return } $sharedIdxFile = Join-Path $sharedDir 'shared-index.json' if (-not (Test-Path $sharedIdxFile)) { script:Out-Info "No shared-index.json found at $sharedDir." return } $sharedIdx = try { $raw = Get-Content $sharedIdxFile -Raw -Encoding UTF8 -ErrorAction Stop if ($raw) { $si = $raw | ConvertFrom-Json -AsHashtable if (-not $si.ContainsKey('snippets')) { $si['snippets'] = @{} } $si } else { @{ snippets = @{} } } } catch { @{ snippets = @{} } } $cfg = script:LoadCfg $localIdx = script:LoadIdx $synced = 0 foreach ($snipName in @($sharedIdx['snippets'].Keys)) { if ($localIdx.snippets.ContainsKey($snipName) -and -not $Force) { continue } $meta = $sharedIdx['snippets'][$snipName] if ($meta -is [hashtable]) { $meta = [SnippetMetadata]::FromHashtable($meta) } $lang = $meta.Language $srcFile = Join-Path $sharedDir "$snipName.$lang" if (-not (Test-Path $srcFile)) { $found = @(Get-ChildItem $sharedDir -Filter "$snipName.*" -ErrorAction SilentlyContinue) if ($found.Count -gt 0) { $srcFile = $found[0].FullName } else { continue } } if ($PSCmdlet.ShouldProcess($snipName, 'Sync snippet from shared storage')) { $destFile = Join-Path $cfg.SnippetsDir (Split-Path $srcFile -Leaf) Copy-Item $srcFile $destFile -Force $localIdx.snippets[$snipName] = $meta $synced++ } } script:SaveIdx -Idx $localIdx script:Out-OK "Synced $synced new snippet(s) from shared storage." } |