twpayne / chezmoi

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

Add support for multiple sources state nested in multiple subdirectories #2390

Closed issenn closed 2 years ago

issenn commented 2 years ago

Is your feature request related to a problem? Please describe.

I want to create multiple subdirectories that manage the source state when I structure dotfiles. The relevant configuration files for each application/project are in a separate subdirectory (probably also do not need a git submodule), and the target path of each source subdirectory can be different (not necessarily is $HOME). like in my dotfiles use another dotfiles manager.

But chezmoi only supports a single source directory ~/.local/share/chezmoi (or a single source subdirectory defined in .chezmoiroot) as the root directory of the source state, and keeps all configuration files in one (root) directory together.

Describe the solution you'd like

I want to add a .chezmoirc in each application package path to configure the target path for chezmoi, if this file exists, the source path is the path where this file is located. And a global .chezmoirc in $HOME/$XDG_CONFIG_HOME for root directory ~/.local/share/chezmoi. Like .stowrc in GNU Stow.

Possible configurations are --destination(same as target above) --source --working-tree --config etc.

This is the perfect structure dotfiles of the source subdirectories I wanted: (and some .chezmoirc tagged with *)

dotefiles="~/.local/share/chezmoi/"

# It only represents the mapping relationship, the directory itself will not be created with a Symbolic link

# source path                                             => target path
# "$dotefiles/gpg-config/"                                => "$HOME/"
"$dotefiles/gpg-config/.config/gnupg/gpg.conf"            => "$HOME/.config/gnupg/gpg.conf"

# "$dotefiles/zsh-config/"                                => "$HOME/"
"$dotefiles/zsh-config/.config/zsh/.zshrc"                => "$HOME/.config/zsh/.zshrc"
"$dotefiles/zsh-config/.local/share/zsh/zinit"            => "$HOME/.local/share/zsh/zinit"

# "$dotefiles/frp-config/"                                => "/usr/local/"
# "$dotefiles/frp-config/etc/frpc/"                       => "/usr/local/etc/frp/"
# "$dotefiles/frp-config/etc/frps/"                       => "/usr/local/etc/frp/"
"$dotefiles/frp-config/etc/frpc/frpc.ini"                 => "/usr/local/etc/frp/frpc.ini"
"$dotefiles/frp-config/etc/frps/frps.ini"                 => "/usr/local/etc/frp/frps.ini"
# "$dotefiles/frp-config/opt/frpc/"                       => "/usr/local/opt/frpc/"
# "$dotefiles/frp-config/opt/frps/"                       => "/usr/local/opt/frps/"
"$dotefiles/frp-config/opt/frpc/homebrew.mxcl.frpc.plist" => "/usr/local/opt/frps/homebrew.mxcl.frpc.plist"

~/.local/share/chezmoi
...
├── .chezmoirc *
├── gpg-config/
│   ├── .chezmoirc *
│   └── .config
│       └── gnupg
│           ├── gpg.conf
│           └── gpg-agent.conf
├── zsh-config
│   ├── .chezmoirc *
│   ├── .config
│   │   ├── .chezmoirc *
│   │   └── zsh
│   │       ├── .zprofile
│   │       └── .zshrc
│   └── .local
│       ├── .chezmoirc *
│       └── share
│           └── zsh
│               └── zinit
└── frp-config
    ├── .chezmoirc *
    ├── etc
    │   ├── .chezmoirc *
    │   ├── frps
    │   │   └── frps.ini
    │   └── frpc
    │       └── frpc.ini
    └── opt
        ├── .chezmoirc *
        ├── frps
        │   └── homebrew.mxcl.frps.plist
        └── frpc
            └── homebrew.mxcl.frpc.plist

This allows nested chezmoi source.

Describe alternatives you've considered

Like .stowrc .stow-local-ignore .stow-global-ignore in GNU Stow.

# .stowrc
--target=${HOME}/Library/LaunchAgents/
--no-folding

Additional context

Sometimes it is necessary to apply some configurations in advance before continuing to apply other configurations. For example, some configurations are encrypted with gpg, and some configurations are obtained from the password manager. Then you need to apply the gpg configuration separately, import some keys, start the gpg agent, or apply some bitwarden cli toolchains, and then apply the subsequent dotfiles. There are many such situations. Therefore, it is necessary to cut an all in one source directory into independent subdirectories for separate management.

Different package managers or precompilers place configuration files in different places (even on the same OS), such as $HOME, $HOME/.config, $HOME/Library, /usr/local/etc, and so on.

Also I would like to show dotfiles in a human-intuitive way. Add a configuration to disable dot_ conversion and display it as the original .filename, avoid visual confusion with other scripts (like run_, once_, modify_, etc) pre-run by chezmoi.

I have searched other related issues or discussions, and also read the documentation of .chezmoiexternal. But none of them solve my problem, or maybe I haven't found the correct documentation. chezmoi has many other very advanced features, but problems with these basic requirements prevent me from further experience of its advanced features.

I wish it was relatively freestyle and nice structured configuration management.

twpayne commented 2 years ago

tl;dr no, a key part of chezmoi's approach is that there is a single source of truth, and multiple source states are incompatible with this.

Previous discussion: #1992, #2021, #189, #226.

Sometimes it is necessary to apply some configurations in advance before continuing to apply other configurations.

Use run_before_ and run_after_ scripts for this.

Different package managers or precompilers place configuration files in different places (even on the same OS), such as $HOME, $HOME/.config, $HOME/Library, /usr/local/etc, and so on.

See this FAQ entry.

Also I would like to show dotfiles in a human-intuitive way. Add a configuration to disable dot_ conversion and display it as the original .filename, avoid visual confusion with other scripts (like run_, once_, modify_, etc) pre-run by chezmoi.

See this FAQ entry.

twpayne commented 2 years ago

2391 collects the rationale into a single FAQ entry.