| 1 | #!/usr/bin/env pwsh |
| 2 | # scripts/notes/fetch.ps1 |
| 3 | # ───────────────────────────────────────────────────────────────────────────── |
| 4 | # Fetch git notes from remote. Run on every Ralph-watch startup and before |
| 5 | # any agent reads or writes notes. |
| 6 | # |
| 7 | # Usage: |
| 8 | # ./scripts/notes/fetch.ps1 # fetch only |
| 9 | # ./scripts/notes/fetch.ps1 -Setup # first-time: add refspec + fetch |
| 10 | # ./scripts/notes/fetch.ps1 -Merge # fetch + merge (use after push conflict) |
| 11 | # ───────────────────────────────────────────────────────────────────────────── |
| 12 | |
| 13 | [CmdletBinding()] |
| 14 | param( |
| 15 | [string]$Remote = "origin", |
| 16 | [string]$RepoPath = ".", |
| 17 | [switch]$Setup, |
| 18 | [switch]$Merge, |
| 19 | [switch]$Quiet |
| 20 | ) |
| 21 | |
| 22 | function Log ([string]$msg, [string]$color = "White") { |
| 23 | if (-not $Quiet) { Write-Host "[notes/fetch] $msg" -ForegroundColor $color } |
| 24 | } |
| 25 | |
| 26 | $repo = Resolve-Path $RepoPath |
| 27 | |
| 28 | # ── One-time setup: add fetch refspec ────────────────────────────────────── |
| 29 | if ($Setup) { |
| 30 | $existing = git -C $repo config --get-all "remote.$Remote.fetch" 2>&1 | |
| 31 | Where-Object { $_ -match "refs/notes" } |
| 32 | if ($existing) { |
| 33 | Log "Notes refspec already configured." DarkGray |
| 34 | } else { |
| 35 | git -C $repo config --add "remote.$Remote.fetch" "refs/notes/*:refs/notes/*" |
| 36 | Log "Added notes refspec to remote.$Remote.fetch" Green |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | # ── Fetch notes ───────────────────────────────────────────────────────────── |
| 41 | Log "Fetching notes from $Remote..." |
| 42 | $output = git -C $repo fetch $Remote "refs/notes/*:refs/notes/*" 2>&1 |
| 43 | if ($LASTEXITCODE -ne 0) { |
| 44 | Log "Fetch warning: $output" DarkYellow |
| 45 | } else { |
| 46 | Log "Notes fetched." Green |
| 47 | } |
| 48 | |
| 49 | # ── Merge notes if requested (after push conflict) ────────────────────────── |
| 50 | if ($Merge) { |
| 51 | # Abort any stale merge-in-progress state |
| 52 | $mergeLock = Join-Path $repo ".git/NOTES_MERGE_PARTIAL" |
| 53 | if (Test-Path $mergeLock) { |
| 54 | Log "Stale notes merge in progress — aborting before retry" DarkYellow |
| 55 | git -C $repo notes merge --abort 2>&1 | Out-Null |
| 56 | } |
| 57 | |
| 58 | $namespaces = git -C $repo for-each-ref "refs/notes/squad/" --format="%(refname)" 2>&1 |
| 59 | foreach ($ref in $namespaces) { |
| 60 | $ns = $ref -replace "refs/notes/", "" |
| 61 | $remoteRef = "refs/notes/remotes/$Remote/$ns" |
| 62 | $remoteExists = git -C $repo for-each-ref $remoteRef --format="%(refname)" 2>&1 |
| 63 | if ($remoteExists) { |
| 64 | Log "Merging notes: $ns (cat_sort_uniq)" |
| 65 | git -C $repo notes --ref=$ns merge -s cat_sort_uniq $remoteRef 2>&1 | Out-Null |
| 66 | if ($LASTEXITCODE -ne 0) { |
| 67 | Log " Merge failed on $ns — aborting and continuing" Red |
| 68 | git -C $repo notes merge --abort 2>&1 | Out-Null |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | Log "Notes merge complete." Green |
| 73 | } |
| 74 | |
| 75 | # ── Show available namespaces ──────────────────────────────────────────────── |
| 76 | if (-not $Quiet) { |
| 77 | $refs = git -C $repo for-each-ref "refs/notes/squad/" --format="%(refname)" 2>&1 |
| 78 | if ($refs) { |
| 79 | Log "Available namespaces:" |
| 80 | foreach ($r in $refs) { |
| 81 | $count = (git -C $repo notes --ref=($r -replace "refs/notes/","") list 2>&1 | |
| 82 | Where-Object { $_ -ne "" } | Measure-Object -Line).Lines |
| 83 | Log " $r ($count notes)" DarkGray |
| 84 | } |
| 85 | } else { |
| 86 | Log "No squad notes yet." DarkGray |
| 87 | } |
| 88 | } |