pure
pure copied to clipboard
Pure does not respect $GIT_DIR and $GIT_WORK_TREE
General information
With pure prompt, git status is not displayed if you use a different git dir path (and set $GIT_DIR
and $GIT_WORK_TREE
accordingly).
System report (output of prompt_pure_system_report
):
- Zsh: zsh 5.8 (x86_64-pc-linux-gnu) (/usr/bin/zsh)
- Operating system: Linux (#1 ZEN SMP PREEMPT Wed, 06 May 2020 17:32:39 +0000)
- Terminal program: Konsole 20.04.0 (but also occurs in latest iTerm2)
- Tmux: yes
- Git: git version 2.26.2
- Pure state:
- username: `''`
- prompt: `❯`
- version: `1.11.0`
- PROMPT: `typeset -g PROMPT=$'%F{${prompt_pure_colors[path]}}%~%f
%{
%}%(12V.%F{$prompt_pure_colors[virtualenv]}%12v%f .)%(?.%F{$prompt_pure_colors[prompt:success]}.%F{$prompt_pure_colors[prompt:error]})${prompt_pure_state[prompt]}%f '`
- Colors: `typeset -g -A prompt_pure_colors=( [execution_time]=yellow [git:action]=yellow [git:arrow]=cyan [git:branch]=magenta [git:branch:cached]=red [git:dirty]=218 [git:stash]=cyan [host]=yellow [path]=blue [prompt:continuation]=242 [prompt:error]=red [prompt:success]=green [user]=green [user:root]=default [virtualenv]=242 )`
- Virtualenv: `export VIRTUAL_ENV_DISABLE_PROMPT=1`
- Conda: `export CONDA_CHANGEPS1=no`
- Detected frameworks: None
I have:
- [x] Tested with another terminal program and can reproduce the issue:
- [x] Followed the integration instructions for my framework
Problem description
$GIT_DIR
and $GIT_WORK_TREE
are not respected unless already set before prompt is loaded.
Reproduction steps
- Open shell with pure prompt (see .zshrc below)
- Create empty git repo with non-traditional git_dir:
cd /tmp/puregit
export GIT_DIR=`pwd`/.notgit GIT_WORK_TREE=`pwd`
git init
- Confirm that git is working as expected (and picks up the git repo in the
./.notgit
dir:
git status
- Observe that the prompt does not display the git branch
- Launch a new
zsh
(from this shell)
zsh
- Observe that the prompt now displays the git branch
My .zshrc
:
#!/usr/bin/env zsh
declare -A ZINIT
ZINIT[HOME_DIR]="$HOME/.zinit"
ZINIT[BIN_DIR]="${ZINIT[HOME_DIR]}/bin"
source "${ZINIT[BIN_DIR]}/zinit.zsh"
zinit ice compile'(pure|async).zsh' pick'async.zsh' src'pure.zsh'
zinit light "sindresorhus/pure"
Thoughts
I think this is related to the fact that the vcs_info stuff is done in an async subshell(?). When you export the git env vars, they aren't passed to the async processes, so they don't take them into account.
Is there any way to have the async process get these variables after it's initialized? It doesn't have to be immediate (since, you know, it's async), but the next vcs_info check should be passed these variables.
It's possible to update the env info in the async worker via the async_worker_eval
, here's an example use already in Pure:
https://github.com/sindresorhus/pure/blob/02643fd167b6bace2f31ad248fc317e32a42d3fd/pure.zsh#L399
There we change the directory, but it could just as well be an export GIT_DIR=...
to set or a unset GIT_DIR
to remove.
A good place to detect this could be in prompt_pure_preexec
as that is after the user has issued a command or then it could always be done as part of prompt_pure_async_tasks
. Since we're anyway issuing one worker eval there, it might be most performant to combine them. Perhaps something like:
async_worker_eval "prompt_pure" "builtin cd -q ${(q)PWD}; export GIT_DIR=${(q)GIT_DIR}" ...
The reason we're using (q)
for variables here is that it performs necessary shell escaping on the input so that the command(s) will be interpreted correctly. It's a small current limitation of the eval implementation in zsh-async
where if we want to issue multiple commands (i.e. use ;
) we must quote the entire input.
Is that something that should be done user-side? Or within pure itself?
Hmm, it could be either TBH. I guess the question is, do people rely on this functionality and expect Pure to obey the variables? Which is more intuitive?
This should work:
async_git_envs() {
async_worker_eval "prompt_pure" 'git_dir='"${(q)GIT_DIR}"'; git_work_tree='"${(q)GIT_WORK_TREE}"'; if [[ -n $git_dir ]]; then export GIT_DIR=$git_dir; else unset GIT_DIR; fi; if [[ -n $git_work_tree ]]; then export GIT_WORK_TREE=$git_work_tree; else unset GIT_WORK_TREE; fi'
}
add-zsh-hook preexec async_git_envs