Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] -bash: __git_complete: command not found #1011

Closed
javidjamae opened this issue May 8, 2020 · 4 comments
Closed

[BUG] -bash: __git_complete: command not found #1011

javidjamae opened this issue May 8, 2020 · 4 comments

Comments

@javidjamae
Copy link

javidjamae commented May 8, 2020

I'm trying to set up tig along with bash-completion on a new machine (Mac).

I installed the following packages through Homebrew:
brew install git bash-completion bash-git-prompt tig

Versions:
bash - 3.2.57
tig - 2.5.1
git - 2.20.1
bash-completion: 1.3
bash-git-prompt: 2.7.1

I also configured my .bash_profile as per the info documentation for each package.

But, while bash is sourcing /usr/local/etc/bash_completion, I get the following error:
-bash: __git_complete: command not found

When I grep through my entire /usr/local/etc/bash_completion.d directory, I see that the only reference to __git_complete is in the tig-completion.bash directory.

If I'm not mistaken, the/bash_completion.d/tig-completion.bash directory is installed when brew installs tig, as per the following post-install message:

==> Caveats
A sample of the default configuration has been installed to:
  /usr/local/opt/tig/share/tig/examples/tigrc
to override the system-wide default configuration, copy the sample to:
  /usr/local/etc/tigrc

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completions and functions have been installed to:
  /usr/local/share/zsh/site-functions
==> Analytics

I couldn't find any other issues related to this (and I'm not sure if this is the right place to post this issue, so I apologize if it's not). I did find another project that seems to have identified and patched this issue here.

Am I doing something wrong here? I have the exact same configuration with slightly older library versions on another machine and everything works fine, so I'm guessing something has changed in the later versions of one of these libraries that is now causing this issue.

If this is a known bug, is there a workaround or work in progress to address it?

@ghost
Copy link

ghost commented May 18, 2020

I have the same issue. As far as I can tell, __git_complete comes from the regular git completion, and if you first complete a git command (e.g. git <tab><tab>) before trying a tig completion, this'll lazy-load the git completion and then the tig completion works as well in that shell instance.

I've had some success by modifying the bash completion file, and adding _xfunc git __git_complete tig _tig just before the __git_complete tig _tig line. This lazy-loads the git completion just before the tig completion is used, but I'm not sure this is a proper fix.

@wjrogers
Copy link

wjrogers commented Jul 2, 2020

I have the same problem with tig 2.5.1 installed via Homebrew, git 2.27.0-1ppa0ubuntu18.04.1 from the git-core PPA, on Ubuntu 18.04.

@darcyparker
Copy link
Contributor

darcyparker commented Dec 2, 2020

26ab51d#diff-c2d83732b06f9f38854d87bea185233b7ded4d5dab76d274e08b14f1e213a525R98 introduced a dependency on __git_complete, which is a good idea, but has the problem identified by this ticket.

I did some investigation and here's my take:

The problem is that __git_complete is in /usr/share/bash-completion/completions/git, which is loaded dynamically on demand by /usr/share/bash-completion/bash_completion. Because git completion is loaded dynamically, __git_complete is not always defined in the shell that is using tig completion.

In addition to its dynamic loading mechanism, the bash_completion script also sources some content eagerly from $compat_dir (ie /etc/bash_completion.d) and $user_completion (ie $HOME/.bash_completion). (See https://github.com/scop/bash-completion/blob/master/README.md#faq where it talks about this eagerly loaded cases.) So if tig-completion.bash is loaded from one of the eagerly loaded dirs, then __git_complete won't be defined yet (because it is loaded dynamically on demand when the user hits tab after typing git in an interactive shell).

Also note the warning about __git_complete; This is NOT a public function; use at your own risk. in https://github.com/git/git/blob/master/contrib/completion/git-completion.bash#L3496-L3505 (My interpretation: It's not public (ie not in in the parent interactive shell) because it is loaded by bash_completion in its dynamic context.)

#1016 attempts a fix, but I think it could do better because if __git_complete is undefined, then tig doesn't have completions. A better solution would be to source completions/git if needed. Something like this:

if ! declare -f __git_complete &>/dev/null; then
	#Notes:
	#* __git_complete (defined in https://github.com/git/git/blob/master/contrib/completion/git-completion.bash#L3496-L3505)
	# is not public and is loaded by bash_completion dynamically on demand
	#* If __git_complete are not defined, then __git_complete_command and __gitcompappend are also undefined
	#* Solution is to source git completions (from one of these common locations)
	if [ -e /usr/share/bash-completion/completions/git ]; then
		# shellcheck disable=SC1091
		. /usr/share/bash-completion/completions/git
	elif [ -f /usr/local/share/bash-completion/completions/git ]; then
		# shellcheck disable=SC1091
		. /usr/local/share/bash-completion/completions/git
	elif [ -e /etc/bash_completion.d/git ]; then
		# shellcheck disable=SC1091
		. /etc/bash_completion.d/git
	else
		#return early because `__git_complete` is not defined
		return
	fi
fi

This works and is better IMHO... but there are few things I don't like about it:

  • enumerating the different cases where git completion script may be located is not ideal (I am sure I missed some cases)
  • if tig-completion.bash is loaded from one of the eager locations (like $compat_dir (ie /etc/bash_completion.d) or $user_completion (ie $HOME/.bash_completion)), then the solution makes __git_complete public... which I don't think is intended. I believe the authors of https://github.com/git/git/blob/master/contrib/completion/git-completion.bash intended __git_complete to be private and used in the context of a specific instance of dynamically loading bash_completion for git. But maybe its not a big deal to expose it in the parent shell?

Perhaps these notes will help others contribute some ideas to resolve this issue?

darcyparker referenced this issue Dec 2, 2020
Fixes: #795 ("tab completion is really slow")

When run on a Git repository with a large amount of files, like the
linux repository, __tig_complete_file() can take a very long time to
complete. This is unfortunate because when accidentally pressing Tab in
such a repo, bash gets stuck until the completion function has finished,
and does not even allow the user to cancel the operation with Ctrl-C.

In contrast, the current git completion does not have these problems,
and since tig's command line parameters are mostly parameters to git-log
or git-diff, we can use git's native completion for those cases instead.
This also has the advantage that we do not need to care about updating
the tig completion when new parameters are added to git-log or git-diff.

I have tested this only in bash, not in zsh.

For comparison, here is an exemplary runtime measurement of the old and
the new completion in bash, showing an improvement of factor 1863.
Admittedly, this was on a fairly loaded system (a build server), but
still then the new completion runs in unnoticable time. I'm also getting
similar results on an idle system in the same repo with runtime
improvements of about factor 1000.

    linux (master) $ echo $BASH_VERSION
    5.0.3(1)-release

    linux (master) $ git describe
    v5.4-rc3-38-gbc88f85c6c09

    linux (master) $ uptime
     16:45:52 up 36 days,  3:33, 224 users,  load average: 24.17, 38.87, 31.21

    # The new completion:
    linux (master) $ . ../tig/contrib/tig-completion.bash
    linux (master) $ time COMP_WORDS=("tig log") COMP_CWORD=2 __git_wrap_tig

    real    0m0.127s
    user    0m0.085s
    sys     0m0.024s

    # The old completion:
    linux (master) $ . /usr/share/bash-completion/completions/tig
    linux (master) $ time COMP_WORDS=("tig log") COMP_CWORD=2 _tig

    real    2m1.145s
    user    1m40.379s
    sys     0m1.347s

With this change, almost nothing of the old completion remains, so
change the copyright header accordingly. I'm also now adding a
GPL-2.0-or-later dedication, which is the same license as most other
code in this repository; and which, I presume, was also the author's
intent since the first incarnation of this file.

While at it, fix some typos in old comments, and update installation
instructions.

Signed-off-by: Roland Hieber <rhi@pengutronix.de>
@felipec
Copy link
Contributor

felipec commented Dec 2, 2020

@darcyparker I wrote __git_complete. The reason the warning is there is that if people relied on this function, and we decided to change the interface we could say "not out fault". However, after many years it's clear this function is good, and many people are already using without problems. It should be made public, which means simply remove the comment.

I agree you need to manually source the completion script, however, the recommended way to do that is with pkg-config --variable=completionsdir bash-completion, check how git-completion.zsh does it in git-completion.

darcyparker added a commit to darcyparker/tig that referenced this issue Dec 2, 2020
Addresses jonas#1011

As identified in jonas#1011 (comment), there are cases where `__git_complete` is undefined because it is loaded dynamically by bash_completions.

As suggested in jonas#1011 (comment), using `pkg-config` to find `git-completion` script, which defines `__git_complete`.  And using approach similar to https://github.com/felipec/git-completion/blob/master/git-completion.zsh#L28-L49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants