Skip to content

Commit c60d061

Browse files
fix(alias): show project aliases with retired template variables migrated (#4690)
`wt config alias show` now displays project aliases with retired template variables rewritten, matching what the alias actually runs. Previously a project alias written as `code {{ repo_root }}` showed `{{ repo_root }}`, while execution (via `ProjectConfig::load`) ran the migrated `{{ repo_path }}` — and user aliases, loaded through `UserConfig::load`, already showed migrated text, so the two sources disagreed in one listing. The cause was `load_project_aliases_silent` parsing `.config/wt.toml` with a bare `toml::from_str`, on the stated premise that the `aliases` table has no deprecated forms. The first `DEPRECATION_RULES` row (`migrate_template_vars_doc`) rewrites retired variables in every string value, aliases included. The fix runs the file through the same silent `migrate_content` that `wt config show` and the user-config loader use before deserializing, and corrects that docstring. The same listing feeds the `Aliases:` section of `wt --help`, which shows names only, so only `show` changes visibly. `test_config_alias_show_migrates_retired_template_vars` configures a project alias with `{{ repo_root }}` and a user alias with `{{ worktree }}`; before the fix its snapshot showed `repo_root` for the project entry, now both show their replacements. Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
1 parent ea28955 commit c60d061

3 files changed

Lines changed: 99 additions & 6 deletions

File tree

‎src/commands/alias.rs‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -885,14 +885,15 @@ fn render_aliases_help_section(
885885
/// Callers (`augment_help`, `wt config alias show`) latch
886886
/// `suppress_warnings()` before reaching here so the standard `UserConfig::load()`
887887
/// stays quiet: no deprecation warnings, no `.new` file writes, no
888-
/// approved-commands copy. Project config is parsed directly from TOML rather
889-
/// than via `ProjectConfig::load` because the `aliases` table has no deprecated
890-
/// forms — skipping the migration avoids the unrelated warnings entirely.
888+
/// approved-commands copy. Project config is migrated and parsed directly
889+
/// rather than via `ProjectConfig::load`, avoiding its diagnostic side
890+
/// effects; the migration rewrites retired template variables, so both
891+
/// sources show the template that runs.
891892
///
892893
/// Tolerates missing or unloadable config: this is a discovery surface, not
893894
/// an execution surface, so we'd rather show the built-in commands than
894895
/// error out when a repo isn't detected or a config file is malformed.
895-
/// `step_alias` surfaces those errors at execution time.
896+
/// Running the alias surfaces those errors.
896897
pub(crate) fn load_aliases_for_listing() -> Vec<(String, CommandConfig, HookSource)> {
897898
let repo = Repository::current().ok();
898899
let project_id = repo.as_ref().and_then(|r| r.project_identifier().ok());
@@ -923,7 +924,7 @@ pub(crate) fn load_aliases_for_listing() -> Vec<(String, CommandConfig, HookSour
923924
entries
924925
}
925926

926-
/// Parse `.config/wt.toml` directly, extracting just `aliases`, without
927+
/// Migrate and parse `.config/wt.toml`, extracting just `aliases`, without
927928
/// triggering `ProjectConfig::load`'s deprecation warning and hint-writing
928929
/// side effects. See `load_aliases_for_listing` for why.
929930
fn load_project_aliases_silent(repo: &Repository) -> Option<BTreeMap<String, CommandConfig>> {
@@ -932,7 +933,8 @@ fn load_project_aliases_silent(repo: &Repository) -> Option<BTreeMap<String, Com
932933
return None;
933934
}
934935
let contents = std::fs::read_to_string(&path).ok()?;
935-
let config: ProjectConfig = toml::from_str(&contents).ok()?;
936+
let migrated = worktrunk::config::migrate_content(&contents);
937+
let config: ProjectConfig = toml::from_str(&migrated).ok()?;
936938
Some(config.aliases)
937939
}
938940

‎tests/integration_tests/step_alias.rs‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,6 +1970,31 @@ command = "echo message"
19701970
}
19711971
}
19721972

1973+
/// Project and user aliases display the templates that run: a retired
1974+
/// template variable shows as its replacement in both sources, matching the
1975+
/// migration execution applies.
1976+
#[rstest]
1977+
fn test_config_alias_show_migrates_retired_template_vars(repo: TestRepo) {
1978+
repo.write_project_config(
1979+
r#"
1980+
[aliases]
1981+
open = "code {{ repo_root }}"
1982+
"#,
1983+
);
1984+
repo.commit("Add alias config");
1985+
repo.write_test_config(
1986+
r#"
1987+
[aliases]
1988+
here = "echo {{ worktree }}"
1989+
"#,
1990+
);
1991+
1992+
let settings = setup_snapshot_settings(&repo);
1993+
let _guard = settings.bind_to_scope();
1994+
1995+
assert_cmd_snapshot!(make_snapshot_cmd(&repo, "config", &["alias", "show"], None));
1996+
}
1997+
19731998
/// `wt config alias show` with no name and no aliases configured prints a note
19741999
/// rather than empty output.
19752000
#[rstest]
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
source: tests/integration_tests/step_alias.rs
3+
info:
4+
program: wt
5+
args:
6+
- config
7+
- alias
8+
- show
9+
env:
10+
APPDATA: "[TEST_CONFIG_HOME]"
11+
CLAUDE_CONFIG_DIR: "[TEST_CLAUDE_CONFIG]"
12+
CLICOLOR_FORCE: "1"
13+
COLUMNS: "500"
14+
GIT_ALLOW_PROTOCOL: file
15+
GIT_AUTHOR_DATE: "2025-01-01T00:00:00Z"
16+
GIT_AUTHOR_EMAIL: test@example.com
17+
GIT_AUTHOR_NAME: Test User
18+
GIT_COMMITTER_DATE: "2025-01-01T00:00:00Z"
19+
GIT_COMMITTER_EMAIL: test@example.com
20+
GIT_COMMITTER_NAME: Test User
21+
GIT_CONFIG_COUNT: "2"
22+
GIT_CONFIG_GLOBAL: /nonexistent/wt/gitconfig
23+
GIT_CONFIG_KEY_0: user.useConfigOnly
24+
GIT_CONFIG_KEY_1: rerere.enabled
25+
GIT_CONFIG_SYSTEM: /nonexistent/wt/gitconfig
26+
GIT_CONFIG_VALUE_0: "true"
27+
GIT_CONFIG_VALUE_1: "false"
28+
GIT_TERMINAL_PROMPT: "0"
29+
HOME: "[TEST_HOME]"
30+
LANG: C
31+
LC_ALL: C
32+
LLVM_PROFILE_FILE: "[LLVM_PROFILE_FILE]"
33+
OPENCODE_CONFIG_DIR: "[TEST_OPENCODE_CONFIG]"
34+
PATH: "[PATH]"
35+
TERM: alacritty
36+
USERPROFILE: "[TEST_HOME]"
37+
WORKTRUNK_APPROVALS_PATH: "[TEST_APPROVALS]"
38+
WORKTRUNK_CONFIG_PATH: "[TEST_CONFIG]"
39+
WORKTRUNK_SYSTEM_CONFIG_PATH: "[TEST_SYSTEM_CONFIG]"
40+
WORKTRUNK_TEST_BASH_INSTALLED: "0"
41+
WORKTRUNK_TEST_CLAUDE_INSTALLED: "0"
42+
WORKTRUNK_TEST_CODEX_INSTALLED: "0"
43+
WORKTRUNK_TEST_DELAYED_STREAM_MS: "-1"
44+
WORKTRUNK_TEST_EPOCH: "1735776000"
45+
WORKTRUNK_TEST_FISH_INSTALLED: "0"
46+
WORKTRUNK_TEST_GEMINI_INSTALLED: "0"
47+
WORKTRUNK_TEST_MOCK_CONFIG_DIR: "[TEST_MOCK_CONFIG]"
48+
WORKTRUNK_TEST_NUSHELL_ENV: "0"
49+
WORKTRUNK_TEST_OPENCODE_INSTALLED: "0"
50+
WORKTRUNK_TEST_PARENT_SHELL: ""
51+
WORKTRUNK_TEST_POWERSHELL_ENV: "0"
52+
WORKTRUNK_TEST_POWERSHELL_INSTALLED: "0"
53+
WORKTRUNK_TEST_PROBE_TIMEOUT_MS: "60000"
54+
WORKTRUNK_TEST_SKIP_URL_HEALTH_CHECK: "1"
55+
WORKTRUNK_TEST_ZSH_INSTALLED: "0"
56+
XDG_CONFIG_HOME: "[TEST_CONFIG_HOME]"
57+
---
58+
success: true
59+
exit_code: 0
60+
----- stdout -----
61+
○ Alias here (user):
62+
  echo {{ worktree_path }}
63+
○ Alias open (project):
64+
  code {{ repo_path }}
65+
66+
----- stderr -----

0 commit comments

Comments
 (0)