mirror of
https://github.com/max-sixty/worktrunk.git
synced 2026-09-14 20:00:38 +08:00
1eded27943
This consolidates cross-cutting models that had accumulated parallel representations, while preserving the CLI and config interfaces. ## What changed - Forge identity now flows through one `ForgeKind`, with boundary-safe network-host classification shared by CI, remote references, and structured repository metadata. Branded SSH aliases such as `github-personal` remain outside provider dispatch and receive an actionable `forge.platform` diagnostic when forge data is requested. - Worktree removal now uses one owned target type and rechecks uncached worktree topology immediately before compare-and-swap branch deletion, retaining branches that gained a live or locked checkout. - Shell integration no longer implements the retired single-file directive writer. Stale wrappers receive repair guidance, execution fails closed, and child processes cannot inherit the retired sourceable-file capability. - Zsh and Git-version probes are shared, while dead mocks, redundant dependency edges, serializer detours, pass-through types, and duplicate tests are removed. The removal guard deliberately distinguishes live, stale-prunable, and locked registrations. The detached cleanup path performs the same record-aware check before deleting a branch ref. ## Testing `cargo run -- hook pre-merge --yes` passed after merging current `origin/main`: 4,489 tests, Clippy, formatting, lockfile checks, docs, doctests, and snapshot review. > _This was written by Claude Code on behalf of max_.
117 lines
5.2 KiB
PowerShell
117 lines
5.2 KiB
PowerShell
# worktrunk shell integration for PowerShell
|
|
#
|
|
# Limitations compared to bash/zsh/fish:
|
|
# - Hooks using bash syntax won't work without Git Bash
|
|
#
|
|
# For full hook compatibility on Windows, install Git for Windows and use bash integration.
|
|
|
|
# Only initialize if wt is available (in PATH or via WORKTRUNK_BIN)
|
|
if ((Get-Command {{ cmd }} -ErrorAction SilentlyContinue) -or $env:WORKTRUNK_BIN) {
|
|
|
|
# wt wrapper function - uses split temp files for directives
|
|
#
|
|
# IMPORTANT: This function must remain a "simple function" (no [CmdletBinding()] or
|
|
# [Parameter()] attributes). Advanced functions add common parameters like -Debug,
|
|
# -Verbose, -ErrorAction, etc. that intercept short flags: e.g., -D is consumed as
|
|
# -Debug, -V as -Verbose, instead of being passed through to wt.exe. Using $args
|
|
# (automatic variable for simple functions) ensures all arguments reach the binary
|
|
# unchanged.
|
|
function {{ cmd }} {
|
|
# Use WORKTRUNK_BIN if set (for testing dev builds), otherwise find via Get-Command
|
|
# Select-Object -First 1 handles case where multiple binaries match (e.g., wt.exe from Windows Terminal)
|
|
if ($env:WORKTRUNK_BIN) {
|
|
$wtBin = $env:WORKTRUNK_BIN
|
|
} else {
|
|
$wtBin = (Get-Command {{ cmd }} -CommandType Application | Select-Object -First 1).Source
|
|
}
|
|
|
|
$cdFile = [System.IO.Path]::GetTempFileName()
|
|
$execFile = [System.IO.Path]::GetTempFileName()
|
|
|
|
try {
|
|
# Run wt with split directive env vars
|
|
# WORKTRUNK_SHELL selects PowerShell escaping for the EXEC directive payload
|
|
$env:WORKTRUNK_DIRECTIVE_CD_FILE = $cdFile
|
|
$env:WORKTRUNK_DIRECTIVE_EXEC_FILE = $execFile
|
|
$env:WORKTRUNK_SHELL = "powershell"
|
|
& $wtBin @args
|
|
$exitCode = $LASTEXITCODE
|
|
}
|
|
finally {
|
|
Remove-Item Env:\WORKTRUNK_DIRECTIVE_CD_FILE -ErrorAction SilentlyContinue
|
|
Remove-Item Env:\WORKTRUNK_DIRECTIVE_EXEC_FILE -ErrorAction SilentlyContinue
|
|
Remove-Item Env:\WORKTRUNK_SHELL -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
# Process directive files and clean up in a single try/finally so both
|
|
# temp files are removed even if cd or exec throws.
|
|
try {
|
|
# cd file holds a raw path (no shell escaping needed)
|
|
if ((Test-Path $cdFile) -and (Get-Item $cdFile).Length -gt 0) {
|
|
$target = (Get-Content -Path $cdFile -Raw).Trim()
|
|
if ($target) {
|
|
Set-Location -LiteralPath $target
|
|
if ($exitCode -eq 0) {
|
|
$exitCode = $LASTEXITCODE
|
|
}
|
|
}
|
|
}
|
|
|
|
# exec file holds arbitrary shell (e.g. from --execute)
|
|
if ((Test-Path $execFile) -and (Get-Item $execFile).Length -gt 0) {
|
|
$script = Get-Content -Path $execFile -Raw
|
|
if ($script.Trim()) {
|
|
Invoke-Expression $script
|
|
if ($exitCode -eq 0) {
|
|
$exitCode = $LASTEXITCODE
|
|
}
|
|
}
|
|
}
|
|
}
|
|
finally {
|
|
Remove-Item $cdFile -ErrorAction SilentlyContinue
|
|
Remove-Item $execFile -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
# Propagate the exit code so scripts/CI can read $LASTEXITCODE.
|
|
# Do NOT `return $exitCode`: in a PowerShell function `return <value>`
|
|
# writes the value to the output (success) stream, so it would append a
|
|
# stray exit-code line (e.g. `0`) after the real command output — that
|
|
# corrupts captures like `$out = wt list --format json`. Setting
|
|
# $global:LASTEXITCODE is what propagates the failure; the Write-Error
|
|
# below surfaces a visible error record. Note: because this is a simple
|
|
# function, Write-Error does NOT set the caller's $?, so don't rely on
|
|
# $? reflecting a wt failure.
|
|
$global:LASTEXITCODE = $exitCode
|
|
if ($exitCode -ne 0) {
|
|
# Surface a visible error record without throwing (does not set the
|
|
# caller's $? from a simple function; $LASTEXITCODE carries the code)
|
|
Write-Error "wt exited with code $exitCode" -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
|
|
# Tab completion - generate clap's completer script and eval it
|
|
# This registers Register-ArgumentCompleter with proper handling
|
|
# Use WORKTRUNK_BIN if set (for testing), otherwise find via Get-Command
|
|
if ($env:WORKTRUNK_BIN) {
|
|
$wtBinForComplete = $env:WORKTRUNK_BIN
|
|
} else {
|
|
$wtBinForComplete = (Get-Command {{ cmd }} -CommandType Application | Select-Object -First 1).Source
|
|
}
|
|
$env:COMPLETE = "powershell"
|
|
try {
|
|
# Capture output first, then pipe - avoids "Cannot run a document in the middle of a pipeline"
|
|
# error that can occur in some PowerShell configurations/terminals
|
|
$completionScript = & $wtBinForComplete 2>$null
|
|
if ($completionScript) {
|
|
$completionScript | Out-String | Invoke-Expression
|
|
}
|
|
}
|
|
catch {
|
|
# Completion registration is optional - wrapper function still works without it
|
|
}
|
|
finally {
|
|
Remove-Item Env:\COMPLETE -ErrorAction SilentlyContinue
|
|
}
|
|
}
|