twpayne / chezmoi

Manage your dotfiles across multiple diverse machines, securely.
https://www.chezmoi.io/
MIT License
13.36k stars 493 forks source link

Can't use templates from `.chezmoitemplates` in `modify_` scripts that are executed as templates #3334

Closed awebeer256 closed 11 months ago

awebeer256 commented 12 months ago

Describe the bug

chezmoi can't see my templates in .chezmoitemplates when I try to call them inside a modify_ script-template.

To reproduce

  1. In your source directory, create .chezmoitemplates/T, containing, "asdf".
  2. In your source directory, create modify_f.txt, containing this:
    {{/* chezmoi:modify-template
    */}}{{- template "T" . -}}
  3. run chezmoi apply

Expected behavior

In the destination directory, there should be a file called f.txt, containing, "asdf".

Output of command with the --verbose flag

$ chezmoi --verbose apply
chezmoi: template: modify_f.txt:1:17: executing "modify_f.txt" at <{{template "T" .}}>: template "T" not defined

Output of chezmoi doctor

```console $ chezmoi doctor RESULT CHECK MESSAGE warning version v2.33.6, built by nixpkgs warning latest-version v2.40.4 ok os-arch linux/amd64 (NixOS 23.05 (Stoat)) ok uname Linux r2nixos 6.1.62 #1-NixOS SMP PREEMPT_DYNAMIC Wed Nov 8 13:11:05 UTC 2023 x86_64 GNU/Linux ok go-version go1.20.8 (gc) ok executable /nix/store/1s97kazgzq5d8akdnhy757i9523vpdj3-chezmoi-2.33.6/bin/chezmoi ok upgrade-method upgrade-package ok config-file no config file found warning source-dir ~/.local/share/chezmoi is a git working tree (dirty) ok suspicious-entries no suspicious entries warning working-tree ~/.local/share/chezmoi is a git working tree (dirty) ok dest-dir ~ is a directory ok umask 022 ok cd-command found /run/current-system/sw/bin/fish ok cd-args /run/current-system/sw/bin/fish info diff-command not set ok edit-command found /run/current-system/sw/bin/nano ok edit-args /run/current-system/sw/bin/nano ok git-command found /run/current-system/sw/bin/git, version 2.40.1 warning merge-command vimdiff not found in $PATH ok shell-command found /run/current-system/sw/bin/fish ok shell-args /run/current-system/sw/bin/fish info age-command age not found in $PATH ok gpg-command found /run/current-system/sw/bin/gpg, version 2.4.0 info pinentry-command not set info 1password-command op not found in $PATH info bitwarden-command bw not found in $PATH info dashlane-command dcli not found in $PATH info gopass-command gopass not found in $PATH info keepassxc-command keepassxc-cli not found in $PATH info keepassxc-db not set info keeper-command keeper not found in $PATH info lastpass-command lpass not found in $PATH info pass-command pass not found in $PATH info passhole-command ph not found in $PATH info rbw-command rbw not found in $PATH info vault-command vault not found in $PATH info secret-command not set ```

Additional context

My use case is combining Handle different file locations on different systems with the same contents with Manage part, but not all, of a file. There's a software program that combines configuration and state in the same file, and I sometimes install the program as a Flatpak and sometimes as a native package.

halostatue commented 12 months ago

I believe that template is provided by go templates, but Chezmoi uses includeTemplate.

I believe template requires that all of the templates are defined and loaded prior to template resolution, which is non-trivial for Chezmoi to resolve in advance.

twpayne commented 12 months ago

I believe that template is provided by go templates, but Chezmoi uses includeTemplate.

Exactly. Also, modify_f.txt is missing the .tmpl extension required to tell chezmoi that it is a template.

I was able to verify that chezmoi behaves correctly with the following testscript:

# test that modify_ scripts can use templates in .chezmoitemplates
exec chezmoi apply
cmp $HOME/.file golden/.file

-- golden/.file --
contents of template.tmpl
-- home/user/.local/share/chezmoi/.chezmoitemplates/template.tmpl --
contents of template.tmpl
-- home/user/.local/share/chezmoi/dot_file.tmpl --
{{/* chezmoi:modify-template
*/}}{{- includeTemplate "template.tmpl" -}}
bradenhilton commented 12 months ago

@twpayne This is a modify_ template, not a modify_ script. My understanding is that it should not have a .tmpl extension, based on https://github.com/twpayne/chezmoi/issues/2563#issuecomment-1310185941.

I think the main cause of the issue is the fact that the directive line is removed, which means the template ends up being */}}{{- <func> "T" . -}}, as demonstrated here:

# test that modify_ templates can use templates in .chezmoitemplates
exec chezmoi apply
cmp $HOME/f.txt golden/f.txt

-- golden/f.txt --
asdf
-- home/user/.local/share/chezmoi/.chezmoitemplates/T --
asdf
-- home/user/.local/share/chezmoi/modify_f.txt --
{{/* chezmoi:modify-template
*/}}{{- includeTemplate "T" -}}
❯ go test ./internal/cmd/... -run=TestScript/^issue3334$
--- FAIL: TestScript (0.00s)
    --- FAIL: TestScript/issue3334 (0.10s)
        testscript.go:534: # test that modify_ templates can use templates in .chezmoitemplates (0.096s)
            > exec chezmoi apply
            > cmp $HOME/f.txt golden/f.txt
            diff $WORK\home\user/f.txt golden/f.txt
            --- $WORK\home\user/f.txt
            +++ golden/f.txt
            @@ -1,1 +1,1 @@
            -*/}}asdf
            +asdf

            FAIL: testdata\scripts\issue3334.txtar:3: $WORK\home\user/f.txt and golden/f.txt differ

FAIL
FAIL    github.com/twpayne/chezmoi/v2/internal/cmd      0.207s
FAIL

# test that modify_ templates can use templates in .chezmoitemplates
exec chezmoi apply
cmp $HOME/f.txt golden/f.txt

-- golden/f.txt --
asdf
-- home/user/.local/share/chezmoi/.chezmoitemplates/T --
asdf
-- home/user/.local/share/chezmoi/modify_f.txt --
{{/* chezmoi:modify-template */}}
{{- includeTemplate "T" -}}
❯ go test ./internal/cmd/... -run=TestScript/^issue3334$
ok      github.com/twpayne/chezmoi/v2/internal/cmd      0.198s
twpayne commented 11 months ago

Hopefully this is now resolved. Please re-open if needed.

awebeer256 commented 11 months ago

Yes, using includeTemplate instead of template results in the behaviour I want.