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

fix: source files using absolute paths for absolute BASH_SOURCE #1221

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

akinomyoga
Copy link
Collaborator

Depending on the setup, we source the completion files with relative paths. This causes a problem when a completion script uses BASH_SOURCE to specify the helper script after the current working directory is changed. For example, with the following steps, the problem happens:

$ bash --norc
$ source bash_completion
$ make [TAB]
$ cd testdir
$ make [TAB]awk: fatal: cannot open source file `./completions/../helpers/make-extract-targets.awk' for reading: No such file or directory

This is because _comp_cmd_make__extract_targets (called by _comp_cmd_make) uses BASH_SOURCE to identify the location of the helper script, but BASH_SOURCE contains a relative path from the directory where the completion file is first sourced.

$ complete -p make
complete -F _comp_cmd_make make
$ type _comp_cmd_make__extract_targets
_comp_cmd_make__extract_targets is a function
_comp_cmd_make__extract_targets ()
{
    local mode=$1;
    local -x prefix=$2;
    local -x prefix_replace=$prefix;
    [[ $mode == -d && $prefix == */* ]] && prefix_replace=${prefix##*/};
    _comp_awk -f "${BASH_SOURCE[0]%/*}/../helpers/make-extract-targets.awk"
}
$ shopt -s extdebug
$ declare -F _comp_cmd_make__extract_targets
_comp_cmd_make__extract_targets 8 ./completions/make

Full processing of .. in _comp_abspath

In the second commit 67e98c6, I modified _comp_abspath to properly handle ... In the original implementation of _comp_abspath, we just removed the beginning ../ and .. in the middle path segments were left. In this PR, I changed _comp_abspath to fully resolve ... However, was there a reason to just remove ..? I initially thought it might be intended to prevent directory traversing, but it didn't work for that purpose because the middle .. segments are anyway left.

Note

In the following place, I replaced . with the path to the directory containing the file bash_completion, which is determined on the initialization. This aligns with the behavior described in the code comment.

# 2) From the location of bash_completion: Completions relative to the main
# script. This is primarily for run-in-place-from-git-clone setups, where
# we want to prefer in-tree completions over ones possibly coming with a
# system installed bash-completion. (Due to usual install layouts, this
# often hits the correct completions in system installations, too.)
if [[ $BASH_SOURCE == */* ]]; then
dirs+=("${BASH_SOURCE%/*}/completions")
else
dirs+=(./completions)
fi

This means that we have been sourcing the file located in the completion in the actual current directory ./completions/xxx, but this change will remove that behavior.

Some completion functions use BASH_SOURCE to identify the path to the
file where the functions are defined.  However, if the file was
sourced with the relative path (e.g. `. ./completions/make`),
BASH_SOURCE referenced by the function contains the relative path.
This causes the problem after the current working directory is changed
from the one where the file was sourced.  To make BASH_SOURCE
available to the completion files, we should replace a relative path
to the absolute path before passing the path to `source` or `.`.

To supply the absolute path, we add a new global variable
`_comp__base_directory`, which contains the directory where
`bash_completion` is located.
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 this pull request may close these issues.

1 participant