oh-my-fish / theme-bobthefish

A Powerline-style, Git-aware fish theme optimized for awesome.
MIT License
1.44k stars 223 forks source link

very slow shell when using theme on sshfs mounted git repository #291

Closed VietTralala closed 3 years ago

VietTralala commented 3 years ago

I experience significant lag when using this theme on a sshfs-mounted directory inside a git repository. I used the command fish --profile FILE -c 'fish_prompt; type -q fish_right_prompt; and fish_right_prompt' for profiling as mentioned in another issue in the original fish-shell repo

The lag is negligible when using stock fish-shell without this theme.

Here is an excerpt of the profiling result ``` 15 40005 ----> if [ "$theme_git_worktree_support" != 'yes' ] set -l git_toplevel (command git rev-parse --show-toplevel 2>/dev/null) [ -z "$git_toplevel" ] and return # If there are no symlinks, just use git toplevel switch $real_pwd/ case $git_toplevel/\* echo $git_toplevel return end # Otherwise, we need to find the equivalent directory in the $PWD set -l d $real_pwd while not [ -z "$d" ] if [ (realpath "$d") = "$git_toplevel" ] echo $d return end [ "$d" = '/' ] and return set d (__bobthefish_dirname $d) end return ... 6 6 -----> [ "$theme_git_worktree_support" != 'yes' ] 149 39939 -----> set -l git_toplevel (command git rev-parse --show-toplevel 2>/dev/null) 39790 39790 ------> command git rev-parse --show-toplevel 2>/dev/null 14 14 -----> [ -z "$git_toplevel" ] 10 31 -----> switch $real_pwd/ case $git_toplevel/\* echo $git_toplevel return ... 16 16 ------> echo $git_toplevel 5 5 ------> return 105 147 --> set -l hg_root_dir (__bobthefish_hg_project_dir $real_pwd) 27 42 ---> __bobthefish_hg_project_dir $real_pwd 11 11 ----> [ "$theme_display_hg" = 'yes' ] 4 4 ----> return 13 2687290 --> if [ "$git_root_dir" -a "$hg_root_dir" ] # only show the closest parent switch $git_root_dir case $hg_root_dir\* __bobthefish_prompt_git $git_root_dir $real_pwd case \* __bobthefish_prompt_hg $hg_root_dir $real_pwd end else if [ "$git_root_dir" ] __bobthefish_prompt_git $git_root_dir $real_pwd else if [ "$hg_root_dir" ] __bobthefish_prompt_hg $hg_root_dir $real_pwd else __bobthefish_prompt_dir $real_pwd ... 16 16 ---> [ "$git_root_dir" -a "$hg_root_dir" ] 5 5 ---> [ "$git_root_dir" ] 129 2687256 ---> __bobthefish_prompt_git $git_root_dir $real_pwd 9 9 ----> set -l dirty '' 46 128253 ----> if [ "$theme_display_git_dirty" != 'no' ] set -l show_dirty (command git config --bool bash.showDirtyState 2>/dev/null) if [ "$show_dirty" != 'false' ] set dirty (command git diff --no-ext-diff --quiet --exit-code 2>/dev/null; or echo -n "$git_dirty_glyph") if [ "$dirty" -a "$theme_display_git_dirty_verbose" = 'yes' ] set dirty "$dirty"(__bobthefish_git_dirty_verbose) end end ... 8 8 -----> [ "$theme_display_git_dirty" != 'no' ] 149 31052 -----> set -l show_dirty (command git config --bool bash.showDirtyState 2>/dev/null) 30903 30903 ------> command git config --bool bash.showDirtyState 2>/dev/null 27 97147 -----> if [ "$show_dirty" != 'false' ] set dirty (command git diff --no-ext-diff --quiet --exit-code 2>/dev/null; or echo -n "$git_dirty_glyph") if [ "$dirty" -a "$theme_display_git_dirty_verbose" = 'yes' ] set dirty "$dirty"(__bobthefish_git_dirty_verbose) end ... 15 15 ------> [ "$show_dirty" != 'false' ] 324 97022 ------> set dirty (command git diff --no-ext-diff --quiet --exit-code 2>/dev/null; or echo -n "$git_dirty_glyph") 96591 96591 -------> command git diff --no-ext-diff --quiet --exit-code 2>/dev/null 107 107 -------> echo -n "$git_dirty_glyph" 16 83 ------> if [ "$dirty" -a "$theme_display_git_dirty_verbose" = 'yes' ] set dirty "$dirty"(__bobthefish_git_dirty_verbose) ... 67 67 -------> [ "$dirty" -a "$theme_display_git_dirty_verbose" = 'yes' ] 340 228017 ----> set -l staged (command git diff --cached --no-ext-diff --quiet --exit-code 2>/dev/null; or echo -n "$git_staged_glyph") 227677 227677 -----> command git diff --cached --no-ext-diff --quiet --exit-code 2>/dev/null 159 86176 ----> set -l stashed (__bobthefish_git_stashed) 61 86017 -----> __bobthefish_git_stashed 76 85956 ------> if [ "$theme_display_git_stashed_verbose" = 'yes' ] set -l stashed (command git rev-list --walk-reflogs --count refs/stash 2>/dev/null) or return echo -n "$git_stashed_glyph$stashed" else command git rev-parse --verify --quiet refs/stash >/dev/null and echo -n "$git_stashed_glyph" ... 55 55 -------> [ "$theme_display_git_stashed_verbose" = 'yes' ] 85825 85825 -------> command git rev-parse --verify --quiet refs/stash >/dev/null 180 451544 ----> set -l ahead (__bobthefish_git_ahead) 65 451364 -----> __bobthefish_git_ahead 3 19 ------> if [ "$theme_display_git_ahead_verbose" = 'yes' ] __bobthefish_git_ahead_verbose return ... 16 16 -------> [ "$theme_display_git_ahead_verbose" = 'yes' ] 8 8 ------> set -l ahead 0 6 6 ------> set -l behind 0 302 451134 ------> for line in (command git rev-list --left-right '@{upstream}...HEAD' 2>/dev/null) switch "$line" case '>*' if [ $behind -eq 1 ] echo '±' return end set ahead 1 case '<*' if [ $ahead -eq 1 ] echo "$git_plus_minus_glyph" return end set behind 1 end ... 450832 450832 -------> command git rev-list --left-right '@{upstream}...HEAD' 2>/dev/null 30 132 ------> if [ $ahead -eq 1 ] echo "$git_plus_glyph" else if [ $behind -eq 1 ] echo "$git_minus_glyph" ... 76 76 -------> [ $ahead -eq 1 ] 26 26 -------> [ $behind -eq 1 ] 39 39 ----> set -l new '' 35 1696654 ----> if [ "$theme_display_git_untracked" != 'no' ] set -l show_untracked (command git config --bool bash.showUntrackedFiles 2>/dev/null) if [ "$show_untracked" != 'false' ] set new (command git ls-files --other --exclude-standard --directory --no-empty-directory 2>/dev/null) if [ "$new" ] set new "$git_untracked_glyph" end end ... 35 35 -----> [ "$theme_display_git_untracked" != 'no' ] 365 54204 -----> set -l show_untracked (command git config --bool bash.showUntrackedFiles 2>/dev/null) 53839 53839 ------> command git config --bool bash.showUntrackedFiles 2>/dev/null 38 1642380 -----> if [ "$show_untracked" != 'false' ] set new (command git ls-files --other --exclude-standard --directory --no-empty-directory 2>/dev/null) if [ "$new" ] set new "$git_untracked_glyph" end ... 57 57 ------> [ "$show_untracked" != 'false' ] 1336 1642031 ------> set new (command git ls-files --other --exclude-standard --directory --no-empty-directory 2>/dev/null) 1640695 1640695 -------> command git ls-files --other --exclude-standard --directory --no-empty-directory 2>/dev/null 32 254 ------> if [ "$new" ] set new "$git_untracked_glyph" ... ```

As one can see the git commands take quite some time. Thus I was wondering if one could exclude sshfs mounted directories from the additional git-functionality of this theme.

bobthecow commented 3 years ago

It is possible to exclude directories from the git features. But you might also be able to get it usable without completely disabling git. Showing dirty state and untracked files can be (very) slow on large network mounts. You can disable the dirty state flag and '...' output when there are untracked files,

…either globally via fish config:

set -g theme_display_git_dirty no
set -g theme_display_git_untracked no

…or locally via git repo config:

git config bash.showDirtyState false
git config bash.showUntrackedFiles false

I'd suggest doing it per-repo, via git config. Try each of those to see whether they resolve your issue.

If that doesn't solve your problem, you can use $theme_vcs_ignore_paths to completely ignore git/hg integration for a path:

set -g theme_vcs_ignore_paths /path/to/foo /path/to/bar

… or $theme_display_git to disable git integration entirely:

set -g theme_display_git no
VietTralala commented 3 years ago

I first thought about including the following lines into the head of the function __bobthefish_git_project_dir' which was defined in the file fish_prompt.fish

if test -z (df -P . | awk 'NR==2 {print$1}' | string match '/dev/*') 
     # if empty then return, since probably sshfs mount
     return
end

But your solution to set set -g theme_vcs_ignore_paths /path/to/foo/ /path/to/bar in the fish.config is way better and fully satisfies my needs.

Thank you for the fast and helpful response!

vcfvct commented 2 years ago

the git config bash.showDirtyState false && git config bash.showUntrackedFiles false works nicely for specific repo. Thank you!

blueforesticarus commented 2 years ago

none of the above suggestions make any difference for me I still get a several second delay before the prompt shows up, and it still shows "(master)"