Skip to content

feat(pattern): allow default values for env vars via {.env.X:-fallback} - #139

Merged
timvw merged 3 commits into
mainfrom
fix/pattern-variable-defaults
Aug 20, 2026
Merged

feat(pattern): allow default values for env vars via {.env.X:-fallback}#139
timvw merged 3 commits into
mainfrom
fix/pattern-variable-defaults

Conversation

@timvw

@timvw timvw commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • Pattern variables referencing environment variables now support bash-style defaults: {.env.WT_CATEGORY:-personal} uses personal when WT_CATEGORY is unset
  • Default values respect the configured separator (e.g. with separator = "-", {.env.X:-a/b} yields a-b)
  • Hard-failing when a variable has neither a value nor a default is preserved as a design property, not an incidental leftover — it is what makes a misspelled {.brnach} a loud failure rather than a silently mangled path

Closes #136

What this changes

The hard error on a missing variable is intended behaviour and stays. What was missing is a way to opt out of it for a specific variable. The three cases are now:

Situation Behaviour
value available use it
no value, default provided use the default
no value and no default hard error — unchanged

Previously only the first and third existed. PR #127 documents {.env.WT_CATEGORY} as the recommended way to group clones by category, so a user who has not exported the variable gets the error correctly but has no way to declare a fallback in the pattern.

Syntax: {.env.X:-fallback} (bash parameter expansion style)

The implementation preprocesses the pattern string to rewrite {.env.X:-fallback} into an internal envOr template function call before template.Parse, keeping missingkey=error in force for every other reference.

Alternatives rejected

  • {envOr "X" "default"} (template function) — trivially correct but drops the bash-like ergonomics that were asked for.
  • {.env.X | default "default"} (sprig pipeline) — cannot work with missingkey=error, because the map lookup errors before the pipeline runs. Adopting it would mean relaxing the very option that produces the wanted error.

What still errors

  • {.env.UNSET_VAR} (no :-) — hard error, same as before
  • {.brnach} or any misspelled non-env key — hard error, same as before

These are the headline guarantees of this change, and both are pinned by tests.

Scope

Adds the default-value syntax for {.env.*} references in both pattern (worktree placement) and repo_pattern (clone placement). It does not add {.var.X}, a [vars] config section, or wt.var.* git config keys — that is #137. Nor does it address where a per-group value comes from — that is #138. Tracking issue: #132.

Test coverage

  • Unit tests (internal/tmpl/tmpl_test.go): default used when unset, default ignored when set, empty default, slash in default, separator applied to default, set-to-empty-string uses value not default, multiple defaults, mixed with plain env ref, unset without default still errors, misspelled non-env key still errors
  • E2E scenarios (e2e/scenarios/env-vars.yaml): default used when unset, default ignored when set, empty default, slash in default, separator applied to default
  • Red-green verified: broke envOr to always return the fallback, confirmed the "default ignored when set" test failed, restored

Test plan

  • go test ./... — 531 passed
  • go vet ./... — clean
  • gofmt -l . — clean
  • go run e2e/run.go — 247 passed, 0 failed
  • Codex review loop (2 rounds): separator inconsistency fixed, wt info output updated

@timvw timvw changed the title fix(pattern): support default values for env vars via {.env.X:-fallback} feat(pattern): allow default values for env vars via {.env.X:-fallback} Aug 19, 2026
@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.56%. Comparing base (8d63b05) to head (d46a5b4).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
cmd/info.go 0.00% 5 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #139      +/-   ##
==========================================
+ Coverage   41.50%   42.56%   +1.06%     
==========================================
  Files          34       34              
  Lines        3542     3580      +38     
==========================================
+ Hits         1470     1524      +54     
+ Misses       2072     2056      -16     
Files with missing lines Coverage Δ
cmd/clone_path.go 69.23% <100.00%> (ø)
cmd/worktree_path.go 61.06% <100.00%> (ø)
internal/tmpl/tmpl.go 89.47% <100.00%> (+89.47%) ⬆️
cmd/info.go 0.00% <0.00%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@timvw
timvw force-pushed the fix/pattern-variable-defaults branch from 555d0e7 to 69e9a21 Compare August 20, 2026 08:23
timvw added 3 commits August 20, 2026 10:34
Pattern variables referencing unset environment variables now support
bash-style defaults: {.env.WT_CATEGORY:-personal} uses "personal" when
WT_CATEGORY is unset. Without the :- syntax, unset variables still error
(preserving typo detection for misspelled keys).

The implementation preprocesses the pattern string to rewrite
{.env.X:-fallback} into an envOr template function call before
template.Parse, keeping missingkey=error intact for all other variables.

Closes #136
Default values in {.env.X:-fallback} now respect the configured
separator, consistent with how actual env values are transformed.
E.g. with separator="-", {.env.X:-a/b} yields "a-b" when X is unset.
@timvw
timvw force-pushed the fix/pattern-variable-defaults branch from 69e9a21 to d46a5b4 Compare August 20, 2026 08:34
@timvw
timvw enabled auto-merge (squash) August 20, 2026 08:34
@timvw
timvw merged commit e241cf1 into main Aug 20, 2026
14 checks passed
@timvw
timvw deleted the fix/pattern-variable-defaults branch August 20, 2026 08:39
timvw added a commit that referenced this pull request Aug 20, 2026
Grouping by WT_CATEGORY is documented as an env var in the pattern, but
the only ways to supply it were per-command or a single machine-wide
export. direnv covers the per-directory case with no wt changes, and the
:- defaults from #139 make it degrade gracefully where no .envrc exists.

Refs #138
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pattern: allow a default value for pattern variables

1 participant