A software engineer website

Zsh: debugging git remotes completion

Gautier DI FOLCO May 31, 2023 [dev] #dev #development #flow #tools #zsh #git

I spend most of my day in a linux terminal (KDE's konsole), doing so, I interact directly with git.

I usually starts working on a topic:

$ git co -b feature/something-useful
# 'co' is an alias for checkout
# I create a new branch

Then, I work intensively and I conclude by adding my changes in a commit

$ git add -p
# I stage each chuncks
$ git ci -m "feat(area): something useful (#42)"

Finally, I want to push by branch:

$ git push <Tab>

I try to trigger zsh's git completion, but after several seconds, I've got an unfortunate:

zsh: do you wish to see all 148622 possibilities (74311 lines)?

Going deeper, it looks like NSFW domains I have populated in my /etc/hosts with blocked hosts from StevenBlack's hosts.

So, it breaks my flow, and does not give me relevant results.

In order to fix that, I have to limit completion to actual registered remotes.

First, I had to locate the completion function:

$ which _git
_git () {
        # undefined
        builtin autoload -XUz
}

Mmh, it does not look good, I had to pull, well, to fetch the tarball, the relevant functions are the following:

# zsh-5.9/Completion/Unix/Command/_git
(( $+functions[__git_remotes] )) ||
__git_remotes () {
  local remotes expl

  remotes=(${(f)"$(_call_program remotes git remote 2>/dev/null)"})
  __git_command_successful $pipestatus || return 1

  _wanted remotes expl remote compadd "$@" -a - remotes
}

(( $+functions[__git_remote_repositories] )) ||
__git_remote_repositories () {
  if compset -P '*:'; then
    _remote_files -/ -- ssh
  else
    _ssh_hosts -S:
  fi
}

(( $+functions[__git_local_repositories] )) ||
__git_local_repositories () {
  local expl

  _wanted local-repositories expl 'local repository' _directories
}

(( $+functions[__git_any_repositories] )) ||
__git_any_repositories () {
  # TODO: should also be $GIT_DIR/remotes/origin
  _alternative \
    'local-repositories::__git_local_repositories' \
    'remotes: :__git_remotes' \
    'remote-repositories::__git_remote_repositories'
}

The entry-point is __git_any_repositories which relies (_alternative) on three functions:

Thankfully with the syntax:

(( $+functions[__git_fn] )) ||
__git_fn () {
}

the function is only defined when it wasn't defined previously, such as in my ~/.zshrc:

__git_remote_repositories (){}
__git_local_repositories (){}

which grive me the expected behavior:

$ git push <Tab>
origin  upstream