Closed lcrockett closed 1 year ago
What at interesting feature request. It shouldn’t be hard to implement, although it would be necessary to make sure that the command-line parameters override the environment variables if both are specified.
Can you describe how you would use multiple chezmoi repositories like this? I’d like to understand this use case a bit better to see if there’s a different feature that might be worth considering for a future release.
4 different workstations, 3 different "users / usernames / home directories" (they're all me, private | work | work client).
Too much duplicated data (neomutt, ZSH, Neovim, GnuPG, TMUX, etc. etc.)
chezmoi --cache "$HOME/.cache/chezmoi-global" --config "$HOME/.config/chezmoi-global/chezmoi.yaml" --source "$HOME/.local/share/chezmoi-global" <whatever>
1a. This gives me all globally shared configurationchezmoi --cache "$HOME/.cache/chezmoi" --config "$HOME/.config/chezmoi/chezmoi.yaml" --source "$HOME/.local/share/chezmoi" <whatever>
OR chezmoi <whatever>
. I'd personally prefer the former in order to be explicit.
2a. This gives me all personal scoped configurationchezmoi diff
, or chezmoi apply
on one system where i'm changing / developing configuration changes until i'm satisfied and ready to commit. I'd like to be able to do this without using temporary aliases or writing out the full chezmoi command with all necessary arguments. Instead, i'd have direnv
take care of setting the appropriate environment variables that chezmoi would then pick up onHaving command-line parameters override environment variables would certainly be the standard way tools deal with order. Good catch
I’ve added a draft PR that should work. There’s no tests, barely any documentation, and I haven’t even run it myself to see if it Does The Right Thing. I’ll get to that later, but I think that this should work.
I’m sure you know this, but because I ran into this multiple times‡ myself recently (and I consider myself a direnv expert…), remember that direnv typically only updates on prompt display, so you would need to run direnv exec DIR COMMAND [...ARGS]
in your wrapper script to ensure that direnv updates are applied.
In my case I was doing for d in env-*; do cd $d && terraform plan -out plan && cd ..; done
but needed to do for d in env-*; do cd $d && direnv exec . terraform plan -out plan && cd ..; done
. Oops.
Thanks for the detailed info @lcrockett. A few questions/comments:
chezmoi is designed to generate dotfiles for multiple machines/configurations from a single source of truth. Is there a reason that you can't merge the dotfiles from the three "all you" users into a single repo?
The cache and source directories can be set in chezmoi's configuration file. With this, you only need to specify -C
to chezmoi to switch all directories.
Currently chezmoi sets various CHEZMOI_
environment variables itself (#2429, #2743). I'm concerned that there will be some subtle and possibly bad interactions between these and chezmoi also reading environment variables. At least some careful thought is required so that running chezmoi cd
and then another chezmoi command has the desired effect.
@twpayne, I’m not @lcrockett, but I can think of places where I might use this:
$CHEZMOI_CONFIG
would still be useful for integration with direnv
and not having to remember to supply -C
. I’m going to be doing some work with #2773 and will probably push the documentation in that direction (I’ll try to update the documentation as its own commit so that it can be separated off later).assets/chezmoi.io/docs/user-guide/advanced/use-chezmoi-with-watchman.md
.@twpayne
chezmoi cd
(never really used this option), i'm proposing chezmoi to pick up on additional variables when it's run in a regular shell. In my use case I would always already sit in the appropriate directory (~/.local/share/chezmoi
or ~/.local/share/chezmoi-global
)@halostatue
Thank you for the PR, I could test it out once you're done with it. The $CHEZMOI_CONFIG
proposal sounds good. Also, i'm aware of the direnv
specifics you've mentioned. In this specific case I would always sit in an interactive shell and any directory change would trigger a prompt display anyways. Cheers
Interesting, I implemented a system of my own to solve what you are proposing. I have a bunch of scripts:
cz
- aka defaultczb
- aka baseczx
- aka externalseach of those work in a different context - cz
and czb
are working with a different config path and in different git repos.
czx
is just a different configuration within the czb
repo.
cz
initializes czb
via run_
and run_once_
scripts, and czb
initializes czx
.
My different chezmoi based scripts use an environment variable named CONTEXT.
CONTEXT when missing, defaults to cz
, but it can be set to czb
or czx
to interact with that different context.
I too use direnv
to manipulate the default context, depending on my work, and so switching CONTEXT does that.
My scripts look like this:
cz
alias cz="chezmoi"
czb
[[ -z "$CZ_B" ]] && echo "CZ_B isn't defined!" && exit 1
chezmoi --source "$CZ_B" --config ${USER_HOME:-$HOME}/.config/chezmoi/_base/chezmoi.toml "${@}"
czx
[[ -z "$CZ_X" ]] && echo "CZ_X isn't defined!" && exit 1
chezmoi --source "$CZ_X" --config ${USER_HOME:-$HOME}/.config/chezmoi/_externals/config.toml "${@}"
paired with the following aliases:
alias Cb="CONTEXT=czb "
alias Cx="CONTEXT=czx "
As you can see the variation is in both --source
location and --conifg
location.
A good example where the concept of CONTEXT comes into play is my cz-get-data
script.
cz-get-data
:
#! /usr/bin/env bash
CONTEXT=${CONTEXT:-cz}
QUERY="${@:-my_data_root_name_here}"
[[ $QUERY == "." ]] && QUERY=""
${CONTEXT} data --format json | jq -r ".${QUERY}"
Or cz-init
script (which calls the above cz-get-data):
#! /usr/bin/env bash
export CONTEXT=${CONTEXT:-cz}
$CONTEXT init --config-path "$(cz-get-data chezmoi.configFile)" ${@}
I wrote cz-init
because just using a different CONTEXT for the init
wasn't enough, as the --config-path
argument was required.
I invoke it from command line like this:
CONTEXT=czb cz-init
# or
Cb cz-init
The layered approach you are describing, will allow me to do this without all of the scripting infrastructure.
I just wrote in https://github.com/twpayne/chezmoi/pull/2773#issuecomment-1462700844:
Sorry, I am against this [PR].
Currently chezmoi sets a wide range of environment variables for processes that it spawns. All of these variables begin with
CHEZMOI
.This PR adds a special environment variable which is the first and only one to be read by chezmoi. This is inconsistent with chezmoi's existing use of environment variables.
I don't like configuration being set via environment variables as they are generally not trivially visible to the user (unlike, say command line arguments). I think the original problem is better solved with a wrapper script or alias.
Is your feature request related to a problem? Please describe.
When working with different chezmoi source directories on the same machine it is useful to be able to run a chezmoi command that is influenced by environment variables. For instance,
direnv
can be used to set different "cache | config | source" directory environment variables that chezmoi will use when executed.This allows one to cd to alternative source directories and being allowed to use
chezmoi diff
,chezmoi apply
, etc. while in the alternative directory and actually use that same source directory as a source path, and other alternative directories for the cache and configuration. This will prevent the necessity to always use--cache
|--config
|--source
with every invocation of chezmoi when using alternative directories.Describe the solution you'd like
Have chezmoi obey environment variables to influence the used cache | config | source directories. For instance
CHEZMOI_CACHE_PATH
|CHEZMOI_CONFIG_PATH
|CHEZMOI_SOURCE_PATH
.Describe alternatives you've considered
Alternatives are to add a local
.bin
directory to$PATH
with a script calledchezmoi
that executes chezmoi with the alternative directories set as arguments and then havedirenv
add that.bin
directory automatically upon entering a chezmoi source directory. Works, but using environment variables are more suited for this scenario and easier to maintain.