twpayne / chezmoi

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

nvim chezmoi edit returns exit status 134 #2922

Closed kaddkaka closed 1 year ago

kaddkaka commented 1 year ago

What exactly are you trying to do?

Editing a tracked config file with nvim and closing it with :wq will cause chezmoi to return with exit status 134 when this autocmd is present in my nvim config:

autocmd BufWritePost /tmp/chezmoi-edit*       silent! !chezmoi apply --source-path "%"

As recommended from https://www.chezmoi.io/user-guide/tools/editor/#configure-vim-to-run-chezmoi-apply-whenever-you-save-a-dotfile (except the filename is changed to the one used when invoking e.g. chezmoi edit .config/nvim/init.vim)

The problem is not seen when saving and quitting separately: :w :q.

The problem is not seen with vim

$ nvim --version
NVIM v0.9.0-dev-1254+g84027f751
$ vim --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Apr 03 2023 07:45:49)

Where else have you checked for solutions?

I tried to find documentation about exit status, but I didn't find any.

Output of any commands you've tried with --verbose flag

$ chezmoi --verbose edit .config/nvim/init.vim
chezmoi: exit status 134
$ echo $?
1

Output of chezmoi doctor

```console $ chezmoi doctor RESULT CHECK MESSAGE ok version v2.33.1, commit bc4478d84f59ea38084cf7e58b9226278d0e046d, built at 2023-04-07T22:36:48Z, built by goreleaser ok latest-version v2.33.1 ok os-arch linux/amd64 (Ubuntu 22.04.2 LTS (Jammy Jellyfish)) ok uname Linux Tugge 5.15.0-69-generic #76-Ubuntu SMP Fri Mar 17 17:19:29 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux ok go-version go1.20.3 (gc) ok executable ~/bin/chezmoi ok upgrade-method replace-executable 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 002 ok cd-command found /usr/bin/bash ok cd-args /usr/bin/bash info diff-command not set ok edit-command found ~/bin/nvim ok edit-args ~/bin/nvim ok git-command found /usr/bin/git, version 2.40.0 ok merge-command found /usr/bin/vimdiff ok shell-command found /usr/bin/bash ok shell-args /usr/bin/bash info age-command age not found in $PATH ok gpg-command found /usr/bin/gpg, version 2.2.27 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

Doing the same change with vim and the same autocmd does not cause the bad exit status:

$ EDITOR=vim chezmoi edit .config/nvim/init.vim
$

Doing the changes "manually" in the `~/.local/ folder and vim/nvim gives no surprising exit status:

$ vim ~/.local/share/chezmoi/dot_bashrc
$ echo $?
0
$ nvim ~/.local/share/chezmoi/dot_bashrc
$ echo $?
0

(using this autocmd: autocmd BufWritePost ~/.local/share/chezmoi/* silent! !chezmoi apply --source-path "%")

kaddkaka commented 1 year ago

Oh, I realized having silent! on the !chezmoi external command was a bit stupid. And now I see this error when trigger the autocmd with :w:

"/tmp/chezmoi-edit391288291/.config/nvim/init.vim" 149L, 4739B written
:!chezmoi apply
chezmoi: open /dev/tty: no such device or address

shell returned 1

What to make of that?

twpayne commented 1 year ago

Presumably you're using a password manager that requires a password to store your secrets?

chezmoi: open /dev/tty: no such device or address means that chezmoi is trying to get a TTY to read your password manager password, but NVIM doesn't allow this when you run :!chezmoi apply.

kaddkaka commented 1 year ago

Almost, it was asking for what to do with another tracked file that had diffs (diff/overwrite/skip).

vim shows the prompt, but I'm not sure if I was able to interact with it, it seems to trigger on the first key stroke (which might be the default behavior, e.g. o means overwrite)

twpayne commented 1 year ago

Running chezmoi apply outside of NVIM should reveal exactly why chezmoi needs a TTY. It may well be the "file has changed since chezmoi last wrote it" warning. You can run chezmoi apply --force instead if you're feeling lucky.

Also consider chezmoi edit --watch and see https://www.chezmoi.io/links/related-software/.

kaddkaka commented 1 year ago

so I updated my autocmds to be:

autocmd BufWritePost ~/.local/share/chezmoi/* ! chezmoi apply --source-path "%"
autocmd BufWritePost /tmp/chezmoi-edit*       ! chezmoi apply

so that when editing a file directly under ~/.local/ only that file is applied. However I'm not sure if anything similar is possible with the /tmp/chezmoi-edit* so I left it with the "catch-all" command chezmoi apply. This has the drawback of applying changes to all files, not just the one being edited.

kaddkaka commented 1 year ago

Thanks for pointing out related software. The Lilja plugin should work for the chezmoi edit invocation as it uses ugly code to get the cmdline from the parent pid to extract the dotfile being edited:

if stridx(l:parentPidFileSplitted[0], l:chezmoiBinary) != -1 && l:parentPidFileSplitted[1] == "edit"
  let l:dotfile = l:parentPidFileSplitted[-1]

Would it be possible for the chezmoi edit command to modify the actual file under ~/.local/share/chezmoi/ instead of a temporary file? That would simplify some of this.

twpayne commented 1 year ago

Would it be possible for the chezmoi edit command to modify the actual file under ~/.local/share/chezmoi/ instead of a temporary file?

Yes and no.

Yes: chezmoi edit invokes your editor with a filename equal to the target file name and a hardlink target of the source file, i.e. chezmoi edit already edits the file in the actual file under ~/.local/share/chezmoi/.

No: this only works if the file is not encrypted. With encrypted files, chezmoi edit transparently decrypts and re-encrypts them for you.

i.e. this is already the case.

kaddkaka commented 1 year ago

Right, so is it possible to get the ~/.local/share/chezmoi/-path from the /tmp/chezmoi-edit1361922538/.config/nvim/init.vim?

Since chezmoi apply --source-path works with the first kind of path, but not the second.

kaddkaka commented 1 year ago

I guess the following is useful to find the source file:

$ find "$XDG_DATA_HOME"/chezmoi/ -samefile /tmp/chezmoi-edit332538725/.config/nvim/init.vim 2>/dev/null
$XDG_DATA_HOME/chezmoi/dot_config/nvim/init.vim

I am not sure what this means exactly

chezmoi edit invokes your editor with a filename equal to the target file name and a hardlink target of the source file, i.e. chezmoi edit already edits the file in the actual file under ~/.local/share/chezmoi/.

in vim/nvim, the name of the file being edited (the name of the buffer at least) is the tmp name, and I'm, not sure if target file name is available anywhere.

twpayne commented 1 year ago

The target path is visible after the temporary path, i.e. remove the /tmp/chezmoi-edit332538725/ prefix.

You can use the target path with chezmoi apply if you don't pass the --source-path flag.

kaddkaka commented 1 year ago

Oh! That's quite obvious now that you point it out. How is that tmppath generated (i.e. chezmoi-edit332538725)? Would this pattern substitution be a good enough way to extract the interesting part? s?/tmp/chezmoi-edit[0-9]*/??, as used in:

fnamemodify(expand('%'), ":s?/tmp/chezmoi-edit[0-9]*/??")

Also I just found the chezmoi edit apply command (https://www.chezmoi.io/user-guide/frequently-asked-questions/usage/), does that make the above vim autocmds redundant?

twpayne commented 1 year ago

How is that tmppath generated (i.e. chezmoi-edit332538725)?

/tmp comes from $TMPDIR (depending on your OS), the chezmoi-edit prefix is set by chezmoi, and the suffix is randomly generated. However, any or all of the above might change from OS to OS or from chezmoi version to chezmoi version.

Would this pattern substitution be a good enough way to extract the interesting part? s?/tmp/chezmoi-edit[0-9]*/??

No, for the reason above.

Also I just found the chezmoi edit apply command (https://www.chezmoi.io/user-guide/frequently-asked-questions/usage/), does that make the above vim autocmds redundant?

Pretty much. You should also look at the --watch flag and the edit.watch config variable.

twpayne commented 1 year ago

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