stdlib: skip absent user-library globs when globbing is disabled
Summary
When Bash pathname expansion is disabled (set -f / noglob), direnv's global-library loop attempts to source a literal file named *.sh when ~/.config/direnv/lib/ is absent or empty. This emits a spurious error even though the project environment loads successfully.
Reproduction
tmp=$(mktemp -d "$TMPDIR/direnv-noglob-proof.XXXXXX")
mkdir -p "$tmp/home" "$tmp/project" "$tmp/config/direnv"
printf "%s\n" "export DIRENV_NOGLOB_PROOF=1" > "$tmp/project/.envrc"
HOME="$tmp/home" XDG_CONFIG_HOME="$tmp/config" DIRENV_CONFIG="$tmp/config/direnv" \
direnv allow "$tmp/project/.envrc"
(
cd "$tmp/project"
env HOME="$tmp/home" XDG_CONFIG_HOME="$tmp/config" DIRENV_CONFIG="$tmp/config/direnv" \
SHELLOPTS=braceexpand:hashall:interactive-comments:noglob \
direnv export bash >/dev/null
)Expected: no stderr output related to optional global library files.
Actual (exit status remains zero):
environment:1428: /tmp/.../config/direnv/lib/*.sh: No such file or directoryThe relevant stdlib code is:
for lib in "$direnv_config_dir/lib/"*.sh; do
# shellcheck disable=SC1090
source "$lib"
donenullglob handles an unmatched pattern only while pathname expansion is enabled. With noglob, the pattern remains literal and the loop body runs once.
Proposed fix
Guard each candidate before sourcing it:
for lib in "$direnv_config_dir/lib/"*.sh; do
[[ -f $lib ]] || continue
# shellcheck disable=SC1090
source "$lib"
doneThis preserves the intended behavior for existing libraries and makes the optional directory truly optional regardless of the caller's Bash globbing option. A regression test should run direnv with noglob and a missing or empty config lib directory, then assert that no missing-file diagnostic is emitted.
Source: direnv/direnv