update-test: point the rehearsal straight at the fork

pre no longer builds a bare serve.git mirror, moves refs or sets
allowAnySHA1InWant. The repo-local insteadOf now rewrites the official
URLs directly to --source, so updates follow the fork's main (force-push
it to the branch under test). post still undoes the redirect via the
clone/snapshot restore.

--ref is removed: neither hermes update nor the tester's pre-branch
desktop can follow another branch through config the kit could set
without the mirror. pre now ls-remotes --source's main before writing
anything, so a bad source aborts with nothing done. The stale
global-redirect cleanup is dropped: it only matched serve.git paths.
This commit is contained in:
ethernet
2026-09-24 15:40:18 -04:00
parent 3c18ea542d
commit a5bd7e574e
5 changed files with 53 additions and 147 deletions

View File

@@ -21,7 +21,7 @@ instructions:
& ([scriptblock]::Create((irm $scriptUrl))) pre
```
this backs up your entire hermes home and any desktop app settings. _from this point on, nothing you do in hermes will be preserved, until you restore your backup at the end._
this backs up your entire hermes home and any desktop app settings, then points your install's updates at the test fork's `main` (no local mirror: `hermes update` fetches straight from the fork, so it needs network). _from this point on, nothing you do in hermes will be preserved, until you restore your backup at the end._
3. boot hermes up to ensure everything is working, still. if you normally have a background service, gateway, etc, make sure it's running.

View File

@@ -7,8 +7,8 @@
pre take a `hermes backup` of your data, snapshot the disk that holds
HERMES_HOME and the desktop app's Electron userData (Volume Shadow Copy),
then point the install's update source at a custom repo + ref so
`hermes update` pulls it. Prints what to do next.
then point the install's update source at a fork so `hermes update`
pulls that fork's main. Prints what to do next.
post put both trees back exactly as they were at the snapshot.
Plus `status`, which only prints. This script never judges your install: it
@@ -30,10 +30,8 @@
pre | post | status
.PARAMETER Source
Repo to pull the update from (default: the rehearsal fork).
.PARAMETER Ref
Branch or tag in that repo (default: main).
Repo to pull the update from; updates follow its main (default: the
rehearsal fork).
.PARAMETER BackupRoot
Where the backup lives (default: $HOME\hermes-update-rehearsal).
@@ -42,12 +40,12 @@
post: skip the confirmation.
.EXAMPLE
./hermes-update-rehearsal.ps1 pre -Source <git-url> -Ref <branch>
./hermes-update-rehearsal.ps1 pre -Source <git-url>
# ... run `hermes update`, use Hermes, test ...
./hermes-update-rehearsal.ps1 post
.NOTES
`pre` needs network access to -Source and a usable git on PATH.
`pre` and `hermes update` need network access to -Source, and a usable git on PATH.
#>
[CmdletBinding()]
param(
@@ -56,7 +54,6 @@ param(
[string]$Command = 'help',
[string]$Source = 'https://github.com/ethernet8023/hermes-agent.git',
[string]$Ref = 'main',
[string]$BackupRoot,
[switch]$Yes
)
@@ -320,10 +317,16 @@ function Invoke-Pre {
$procs | ForEach-Object { Write-Host " $($_.ProcessName) (pid $($_.Id))" }
}
else { Ok 'no Hermes processes running' }
$n = @(Invoke-GitCmd @('config', '--global', '--get-regexp', '^url\.')).Count
$n = @(Invoke-GitCmd @('config', '--global', '--get-regexp', '^url\.')).Count + @(Invoke-GitCmd @('-C', $P.Install, 'config', '--local', '--get-regexp', '^url\.')).Count
if ($n -eq 0) { Ok 'global git config has no URL rewrites' }
else { Warn "$n existing url.* insteadOf entr(y/ies) in your git config; we add more and remove only ours" }
# Before anything is written: a bad -Source or no network should abort with
# nothing done, not after the backup and snapshot.
$targetSha = ((@(Invoke-GitCmd @('ls-remote', $Source, 'refs/heads/main')) | Out-String) -split '\s+')[0]
if ($targetSha -notmatch '^[0-9a-f]{40}$') { Fail "could not read main from $Source (network? permissions? bad -Source?) -- nothing was done" }
Ok "$Source main is at $targetSha"
$stamp = (Get-Date).ToUniversalTime().ToString('yyyyMMddTHHmmssZ')
$script:Snap = Join-Path $BackupRoot $stamp
if (Test-Path -LiteralPath $script:Snap) { Fail "backup dir already exists: $($script:Snap)" }
@@ -352,28 +355,6 @@ function Invoke-Pre {
}
else { Ok "hermes-backup.zip ($([math]::Round((Get-Item $zip).Length / 1MB, 1)) MB, ${elapsed}s)" }
# --- fetch before the snapshot, so the snapshot is as late as possible -----
Step 'fetching the rehearsal source'
Say "source $Source"
Say "ref $Ref"
$serve = Join-Path $script:Snap 'serve.git'
$null = Invoke-GitCmd @('clone', '--quiet', '--bare', '--branch', $Ref, '--single-branch', $Source, $serve)
if ($LASTEXITCODE -ne 0) {
if (Test-Path -LiteralPath $serve) { Remove-Item -LiteralPath $serve -Recurse -Force }
$null = Invoke-GitCmd @('clone', '--quiet', '--bare', $Source, $serve)
if ($LASTEXITCODE -ne 0) { Fail "could not clone $Source (network? permissions? bad -Source?)" }
Ok "cloned the whole repo (-Ref '$Ref' is not a branch/tag name)"
}
else { Ok "cloned $Ref" }
$targetSha = (@(& git -C $serve rev-parse --verify "$Ref^{commit}" 2>$null | Out-String) -replace "`r", '').Trim()
# Shape-check: a warning or error line folded into the capture would otherwise
# be handed to update-ref as a bogus revision.
if ($targetSha -notmatch '^[0-9a-f]{40}$') { Fail "-Ref '$Ref' was not found in $Source" }
$null = Invoke-GitCmd @('-C', $serve, 'update-ref', 'refs/heads/main', $targetSha)
$null = Invoke-GitCmd @('-C', $serve, 'symbolic-ref', 'HEAD', 'refs/heads/main')
$null = Invoke-GitCmd @('-C', $serve, 'config', 'uploadpack.allowAnySHA1InWant', 'true')
Ok "the update will land on $targetSha"
# --- snapshot: the rollback point. Everything after this is undone by post.
Step 'snapshotting the disk'
$shadowLines = @()
@@ -417,26 +398,26 @@ function Invoke-Pre {
userdata_dir_source = $P.UserDataOrigin
userdata_existed = [bool]$userDataExists
rehearsal_source = $Source
rehearsal_ref = $Ref
}
$manifest | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $script:Snap 'manifest.json') -Encoding utf8
Step 'pointing your install at it'
Step "pointing your install at $Source"
# insteadOf is a TRANSPORT rewrite. Your checkout's origin keeps the official
# URL, which matters: `hermes update` resolves its channel from the archive and
# validates it against `git config --get remote.origin.url`. Repointing origin
# at a fork would make the update fail before any git work.
$fileUrl = 'file:///' + ($serve -replace '\\', '/')
# Straight at the fork: the updater follows main, so the fork's main is what
# lands (force-push it to the branch under test).
# REPO-LOCAL: the checkout's config lives inside the snapshotted home, so
# post's restore removes the redirect for free.
foreach ($url in @($OfficialHttps, $OfficialSsh)) {
# --add: the key is multi-valued; a plain set would drop the first URL.
$null = Invoke-GitCmd @('-C', $P.Install, 'config', '--local', '--add', "url.$fileUrl.insteadOf", $url)
$null = Invoke-GitCmd @('-C', $P.Install, 'config', '--local', '--add', "url.$Source.insteadOf", $url)
if ($LASTEXITCODE -ne 0) { Fail "could not write the URL redirect into $($P.Install)\.git\config" }
}
Set-Content -LiteralPath (Join-Path $P.Home '.skip_upstream_prompt') -Encoding utf8 -Value @()
Set-Content -LiteralPath (Join-Path $script:Snap 'target-sha') -Encoding utf8 -Value @($targetSha)
Ok 'official repo URL now resolves to the rehearsal copy'
Ok "official repo URL now resolves to $Source"
Ok "created $($P.Home)\.skip_upstream_prompt (stops the 'add upstream remote?' prompt)"
Step 'ready'
@@ -464,9 +445,9 @@ function Invoke-Status {
Say "latest $snap"
$ts = Join-Path $snap 'target-sha'
if (Test-Path -LiteralPath $ts) {
Say "prepared for $((Get-Content -LiteralPath $ts -Raw).Trim())"
Say "prepared for $((Get-Content -LiteralPath $ts -Raw).Trim()) (main at pre time)"
$manifest = Get-Content -LiteralPath (Join-Path $snap 'manifest.json') -Raw | ConvertFrom-Json
Say "source $($manifest.rehearsal_source) @ $($manifest.rehearsal_ref)"
Say "source $($manifest.rehearsal_source)"
}
else { Say 'prepared no' }
if (Test-Path -LiteralPath (Join-Path $snap 'shadows.txt')) {
@@ -485,8 +466,8 @@ function Invoke-Status {
}
Say "data backup $(if (Test-Path -LiteralPath (Join-Path $snap 'hermes-backup.zip')) { 'hermes-backup.zip' } else { 'none' })"
Say "marker $(if (Test-Path -LiteralPath (Join-Path $P.Home '.skip_upstream_prompt')) { 'present' } else { 'absent' })"
$n = @(Invoke-GitCmd @('config', '--global', '--get-regexp', '^url\.')).Count
Say "git rewrites $n global insteadOf entr(y/ies)"
$n = @(Invoke-GitCmd @('config', '--global', '--get-regexp', '^url\.')).Count + @(Invoke-GitCmd @('-C', $P.Install, 'config', '--local', '--get-regexp', '^url\.')).Count
Say "git rewrites $n insteadOf entr(y/ies)"
if (Test-Path -LiteralPath (Join-Path $P.Install '.git')) {
Say "checkout now $(Invoke-Git $P @('rev-parse', '--short', 'HEAD')) ($(Invoke-Git $P @('branch', '--show-current')))"
}
@@ -503,29 +484,6 @@ function Confirm-Action {
if ($reply -notmatch '^(y|yes)$') { Fail 'aborted -- nothing was changed' }
}
function Remove-StaleGlobalRedirect {
# An earlier version of this kit wrote the insteadOf redirect into the GLOBAL
# git config. Those entries name THIS snapshot's serve.git, which post leaves
# behind, so they would keep hijacking `hermes update` forever. Remove only
# the entries that point at our own rehearsal copy.
$serve = Join-Path $script:Snap 'serve.git'
$prefix = 'file:///' + ($serve -replace '\\', '/')
$removed = 0
foreach ($url in @($OfficialHttps, $OfficialSsh)) {
$prev = $ErrorActionPreference
$ErrorActionPreference = 'Continue'
try {
$out = & git config --global --get "url.$prefix.insteadOf" 2>$null
if ($LASTEXITCODE -eq 0 -and $out) {
$null = Invoke-GitCmd @('config', '--global', '--unset-all', "url.$prefix.insteadOf")
$removed++
}
}
finally { $ErrorActionPreference = $prev }
}
if ($removed) { Ok "removed $removed stale global URL redirect(s) from an older run of this kit" }
}
function Invoke-Post {
Load-Snapshot
Assert-Elevated
@@ -595,8 +553,6 @@ function Invoke-Post {
foreach ($s in $shadows) { Remove-Shadow $s; Ok "deleted the snapshot of $($s.Volume)" }
Restore-ShadowStorage
Remove-StaleGlobalRedirect
Step 'done'
Say "Your HERMES_HOME and the desktop app's data are back exactly as they were."
Say "Open the desktop app once and run 'hermes doctor' to confirm."
@@ -621,15 +577,14 @@ switch ($Command) {
else {
Write-Host 'hermes-update-rehearsal.ps1 -- run against an EXISTING Hermes install.'
Write-Host ''
Write-Host ' pre back up your data, snapshot the disk, point the update source at a custom repo+ref'
Write-Host ' pre back up your data, snapshot the disk, point the update source at a fork'
Write-Host ' post restore both trees exactly as they were at the snapshot'
Write-Host ' status print what is prepared (read-only; nothing is touched)'
Write-Host ''
Write-Host 'pre and post need an elevated (Run as Administrator) PowerShell.'
Write-Host ''
Write-Host 'Options:'
Write-Host ' -Source URL repo to pull the update from'
Write-Host ' -Ref REV branch or tag in that repo'
Write-Host ' -Source URL repo to pull the update from; updates follow its main'
Write-Host ' -BackupRoot DIR where the backup lives'
Write-Host ' -Yes post: skip the confirmation'
Write-Host ''

View File

@@ -4,7 +4,7 @@
# Two steps:
# pre take a `hermes backup` of your data, clone HERMES_HOME and the desktop
# app's Electron userData into the backup dir, then point the install's
# update source at a custom repo + ref so `hermes update` pulls it.
# update source at a fork so `hermes update` pulls that fork's main.
# Prints what to do next.
# post swap the clones back in, so both trees are exactly as they were.
#
@@ -15,29 +15,27 @@
# copied. Elsewhere it is a plain copy. post swaps by rename, so it is instant
# when the backup dir is on the same disk. HERMES_HOME/cache is left as it is.
#
# ./hermes-update-rehearsal.sh pre --source <git-url> --ref <branch-or-tag>
# ./hermes-update-rehearsal.sh pre --source <git-url>
# # ... run `hermes update`, use Hermes, test whatever you need ...
# ./hermes-update-rehearsal.sh post
#
# Options:
# --source URL repo to pull the update from (default: the rehearsal fork)
# --ref REV branch or tag in that repo (default: main)
# --source URL repo to pull the update from; updates follow its main
# (default: the rehearsal fork)
# --backup-root DIR where the backup lives (default ~/hermes-update-rehearsal)
# --yes post: skip the confirmation
#
# Requires: git. `pre` needs network access to --source.
# Requires: git. `pre` and `hermes update` need network access to --source.
set -euo pipefail
OFFICIAL_HTTPS="https://github.com/NousResearch/hermes-agent.git"
OFFICIAL_SSH="git@github.com:NousResearch/hermes-agent.git"
DEFAULT_SOURCE="https://github.com/ethernet8023/hermes-agent.git"
DEFAULT_REF="main"
SUBCMD=""
BACKUP_ROOT="${HOME}/hermes-update-rehearsal"
SOURCE="$DEFAULT_SOURCE"
REF="$DEFAULT_REF"
ASSUME_YES=0
say() { printf '%s\n' "$*"; }
@@ -51,13 +49,13 @@ usage() {
cat <<'EOF'
hermes-update-rehearsal.sh -- run against an EXISTING Hermes install.
pre back up your data, clone both trees, point the update source at a custom repo+ref
pre back up your data, clone both trees, point the update source at a fork
post swap the clones back in, exactly as they were
status print what is prepared (read-only; nothing is touched)
Options:
--source URL repo to pull the update from (default: the rehearsal fork)
--ref REV branch or tag in that repo (default: main)
--source URL repo to pull the update from; updates follow its main
(default: the rehearsal fork)
--backup-root DIR where the backup lives (default ~/hermes-update-rehearsal)
--yes post: skip the confirmation
@@ -78,7 +76,6 @@ while [ "$#" -gt 0 ]; do
case "$1" in
pre|post|status) SUBCMD="$1"; shift ;;
--source) [ "$#" -ge 2 ] || die "--source needs a value"; SOURCE="$2"; shift 2 ;;
--ref) [ "$#" -ge 2 ] || die "--ref needs a value"; REF="$2"; shift 2 ;;
--backup-root) [ "$#" -ge 2 ] || die "--backup-root needs a value"; BACKUP_ROOT="$2"; shift 2 ;;
--yes|-y) ASSUME_YES=1; shift ;;
-h|--help) usage ;;
@@ -124,14 +121,6 @@ resolve_paths() {
USERDATA_DIR="$(native_path "$USERDATA_DIR")"
}
# `file:///C:/x` on Windows, `file:///home/x` elsewhere.
file_url() {
case "$1" in
[A-Za-z]:*) printf 'file:///%s' "$1" ;;
*) printf 'file://%s' "$1" ;;
esac
}
latest_backup_root() {
[ -d "$BACKUP_ROOT" ] || return 1
local newest
@@ -276,6 +265,13 @@ cmd_pre() {
if [ "$n" = 0 ]; then ok "global git config has no URL rewrites"
else warn "$n existing url.* insteadOf entr(y/ies) in your git config; we add more and remove only ours"; fi
# Before anything is written: a bad --source or no network should abort with
# nothing done, not after the backup and clone.
local target_sha
target_sha="$(git ls-remote "$SOURCE" refs/heads/main 2>/dev/null | cut -f1)"
[ -n "$target_sha" ] || die "could not read main from $SOURCE (network? permissions? bad --source?) — nothing was done"
ok "$SOURCE main is at $target_sha"
SNAP="$BACKUP_ROOT/$(date -u +%Y%m%dT%H%M%SZ)"
[ ! -e "$SNAP" ] || die "backup dir already exists: $SNAP"
mkdir -p "$SNAP"
@@ -329,55 +325,31 @@ cmd_pre() {
"userdata_dir_source": "$USERDATA_SOURCE",
"userdata_existed": $userdata_existed,
"clone_mode": "$CLONE_MODE",
"rehearsal_source": "$SOURCE",
"rehearsal_ref": "$REF"
"rehearsal_source": "$SOURCE"
}
EOF
ok "manifest.json (backup of $HERMES_HOME)"
# --- point the install at the rehearsal source ---------------------------
step "fetching the rehearsal source"
say "source $SOURCE"
say "ref $REF"
local serve="$SNAP/serve.git" target_sha=""
rm -rf "$serve"
# Prefer a single-branch clone (fast); fall back to a full bare clone so a
# raw commit in --ref still resolves.
if git clone --quiet --bare --branch "$REF" --single-branch "$SOURCE" "$serve" 2>/dev/null; then
ok "cloned $REF"
else
rm -rf "$serve"
git clone --quiet --bare "$SOURCE" "$serve" \
|| die "could not clone $SOURCE (network? permissions? bad --source?)"
ok "cloned the whole repo (--ref '$REF' is not a branch/tag name)"
fi
target_sha="$(git -C "$serve" rev-parse --verify "${REF}^{commit}" 2>/dev/null || true)"
[ -n "$target_sha" ] || die "--ref '$REF' was not found in $SOURCE"
git -C "$serve" update-ref refs/heads/main "$target_sha"
git -C "$serve" symbolic-ref HEAD refs/heads/main
# The updater may ask for an exact SHA instead of a branch tip.
git -C "$serve" config uploadpack.allowAnySHA1InWant true
ok "the update will land on $target_sha"
step "pointing your install at it"
step "pointing your install at $SOURCE"
# insteadOf is a TRANSPORT rewrite. Your checkout's origin keeps the official
# URL, which matters: `hermes update` resolves its channel from the archive
# and validates it against `git config --get remote.origin.url`. Repointing
# origin at a fork would make the update fail before any git work.
local redirect url
redirect="$(file_url "$serve")"
# Straight at the fork: the updater follows main, so the fork's main is what
# lands (force-push it to the branch under test).
local url
# The redirect belongs in the REPO-LOCAL config: it lives inside the checkout
# this kit already cloned, so `post`'s swap removes it for free. A writable
# GLOBAL git config is a dependency we do not need -- requiring it aborts on
# any machine whose ~/.config/git/config is read-only or ACL-denied.
for url in "$OFFICIAL_HTTPS" "$OFFICIAL_SSH"; do
# --add: the key is multi-valued; a plain write would drop the first URL.
git -C "$INSTALL_DIR" config --local --add "url.$redirect.insteadOf" "$url" \
git -C "$INSTALL_DIR" config --local --add "url.$SOURCE.insteadOf" "$url" \
|| die "could not write the URL redirect into $INSTALL_DIR/.git/config"
done
touch "$HERMES_HOME/.skip_upstream_prompt"
printf '%s\n' "$target_sha" > "$SNAP/target-sha"
ok "official repo URL now resolves to the rehearsal copy"
ok "official repo URL now resolves to $SOURCE"
ok "created $HERMES_HOME/.skip_upstream_prompt (stops the 'add upstream remote?' prompt)"
step "ready"
@@ -405,8 +377,8 @@ cmd_status() {
fi
say "latest $SNAP"
if [ -f "$SNAP/target-sha" ]; then
say "prepared for $(tr -d '\r' < "$SNAP/target-sha")"
say "source $(sed -n 's/.*"rehearsal_source": "\(.*\)",/\1/p' "$SNAP/manifest.json" 2>/dev/null | head -1) @ $(sed -n 's/.*"rehearsal_ref": "\(.*\)"/\1/p' "$SNAP/manifest.json" 2>/dev/null | head -1)"
say "prepared for $(tr -d '\r' < "$SNAP/target-sha") (main at pre time)"
say "source $(sed -n 's/.*"rehearsal_source": "\(.*\)"/\1/p' "$SNAP/manifest.json" 2>/dev/null | head -1)"
else
say "prepared no"
fi
@@ -443,22 +415,6 @@ confirm() {
case "$reply" in y|Y|yes|YES) return 0 ;; *) die "aborted — nothing was changed (re-run with --yes to skip this prompt)" ;; esac
}
# An earlier version of this kit wrote the insteadOf redirect into the GLOBAL git
# config. Those entries name THIS snapshot's serve.git, which post leaves behind,
# so they would keep hijacking `hermes update` forever. Remove only the entries
# that point at our own rehearsal copy.
remove_stale_global_redirect() {
local prefix url removed=0
prefix="$(file_url "$SNAP/serve.git")"
for url in "$OFFICIAL_HTTPS" "$OFFICIAL_SSH"; do
if git config --global --get "url.$prefix.insteadOf" >/dev/null 2>&1; then
git config --global --unset-all "url.$prefix.insteadOf" 2>/dev/null || true
removed=$((removed + 1))
fi
done
[ "$removed" = 0 ] || ok "removed $removed stale global URL redirect(s) from an older run of this kit"
}
cmd_post() {
resolve_paths
load_snapshot
@@ -504,8 +460,6 @@ cmd_post() {
rm -rf "$aside"
ok "deleted the post-update trees ($aside)"
remove_stale_global_redirect
step "done"
say "Your HERMES_HOME and the desktop app's data are back exactly as they were."
say "Open the desktop app once and run 'hermes doctor' to confirm."

View File

@@ -234,7 +234,7 @@ try {
# Both trees as they are right now: post is checked against this for exactness.
$homeBefore = Get-TreeListing $H
$userDataBefore = Get-TreeListing $env:HERMES_DESKTOP_USER_DATA_DIR
$r = Invoke-Rehearsal -Arguments @('pre', '-Source', $Install, '-Ref', 'main', '-BackupRoot', $Backups)
$r = Invoke-Rehearsal -Arguments @('pre', '-Source', $Install, '-BackupRoot', $Backups)
Check 'pre exits 0' ($r.Code -eq 0)
$Snap = (Get-ChildItem -LiteralPath $Backups -Directory | Sort-Object Name)[-1].FullName
foreach ($f in @('hermes-backup.zip', 'shadows.txt', 'manifest.json', 'hermes-home.txt', 'target-sha')) {
@@ -246,13 +246,11 @@ try {
Check 'shadow storage cap on C: is at least 128 GB while the snapshot lives' ((Get-ShadowCapC) -ge [UInt64]128GB)
Write-Host "`n--- pre points the install at the rehearsal copy ---"
$served = (& git -C (Join-Path $Snap 'serve.git') rev-parse refs/heads/main | Out-String).Trim()
Check 'serve.git main is the custom ref' ($served -eq $HeadSha)
$cfg = (& git -C $Install config --local --get-regexp 'insteadOf' 2>$null | Out-String)
Check 'two insteadOf entries written (repo-local)' ((([regex]::Matches($cfg, 'insteadOf', 'IgnoreCase')).Count) -eq 2)
Check 'upstream-prompt marker created' (Test-Path -LiteralPath (Join-Path $H '.skip_upstream_prompt'))
$getUrl = (& git -C $Install remote get-url origin | Out-String).Trim()
Check 'remote get-url resolves to the rehearsal copy' ($getUrl -match 'serve\.git')
Check 'remote get-url resolves to -Source' ($getUrl -eq $Install)
$configured = (& git -C $Install config --get remote.origin.url | Out-String).Trim()
Check 'config --get remote.origin.url stays official' ($configured -match 'NousResearch')

View File

@@ -96,7 +96,7 @@ STATUS_BEFORE="$(git -C "$INSTALL" status --porcelain)"
mkdir -p "$ROOT/pristine/home" "$ROOT/pristine/userdata"
cp -a "$H/." "$ROOT/pristine/home/"
cp -a "$HERMES_DESKTOP_USER_DATA_DIR/." "$ROOT/pristine/userdata/"
"${RUN[@]}" pre --source "$INSTALL" --ref main --backup-root "$BACKUPS" > "$ROOT/pre.log" 2>&1
"${RUN[@]}" pre --source "$INSTALL" --backup-root "$BACKUPS" > "$ROOT/pre.log" 2>&1
check $? "pre exits 0"
SNAP="$(ls -1d "$BACKUPS"/*/ | head -1)"; SNAP="${SNAP%/}"
for f in hermes-backup.zip home manifest.json hermes-home.txt target-sha; do
@@ -116,10 +116,9 @@ check $? "clone keeps directory mtimes"
echo
echo "--- pre points the install at the rehearsal copy ---"
[ "$(git -C "$SNAP/serve.git" rev-parse refs/heads/main)" = "$HEAD_SHA" ]; check $? "serve.git main is the custom ref"
[ "$(git -C "$INSTALL" config --local --get-regexp 'insteadOf' | wc -l | tr -d ' ')" = 2 ]; check $? "two insteadOf entries written (repo-local)"
[ -f "$H/.skip_upstream_prompt" ]; check $? "upstream-prompt marker created"
git -C "$INSTALL" remote get-url origin | grep -q 'serve.git'; check $? "remote get-url resolves to the rehearsal copy"
[ "$(git -C "$INSTALL" remote get-url origin)" = "$INSTALL" ]; check $? "remote get-url resolves to --source"
git -C "$INSTALL" config --get remote.origin.url | grep -q 'NousResearch'; check $? "config --get remote.origin.url stays official"
echo