From f0476cb78be51b2819df87fe713944c13d2c4f35 Mon Sep 17 00:00:00 2001 From: Thomas Witt Date: Thu, 12 Feb 2026 16:59:11 +0200 Subject: [PATCH] feat(dotenv): support glob patterns in allowed and disallowed lists The allowed and disallowed list files now support zsh glob patterns (e.g., /path/to/projects/*) in addition to exact paths. This is useful for git worktree setups and other workflows where multiple directories share a common prefix. Comment lines and blank lines are now also supported in list files. --- plugins/dotenv/README.md | 25 +++++++++++++++++++++++++ plugins/dotenv/dotenv.plugin.zsh | 22 ++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/plugins/dotenv/README.md b/plugins/dotenv/README.md index ab9d329f6..0021d7eec 100644 --- a/plugins/dotenv/README.md +++ b/plugins/dotenv/README.md @@ -78,6 +78,31 @@ change. NOTE: if a directory is found in both the allowed and disallowed lists, the disallowed list takes preference, _i.e._ the .env file will never be sourced. +### Glob/Wildcard Patterns + +The allowed and disallowed list files support glob (wildcard) patterns in addition to exact +paths. This is useful when you want to allow or disallow entire directory trees at once. + +For example, if you use [git worktrees](https://git-scm.com/docs/git-worktree) and all your +worktrees live under a common prefix, you can add a single pattern instead of allowing each +one individually: + +```sh +# In your dotenv-allowed.list file: +/Users/me/Dev/my-project-wt-* +``` + +Supported patterns: + +| Pattern | Matches | +|---------|---------| +| `*` | Any characters in a single path component | +| `**` | Any characters across path components | +| `?` | Any single character | +| `[abc]` | Any one of the listed characters | + +Lines starting with `#` are treated as comments. Blank lines are ignored. + ## Version Control **It's strongly recommended to add `.env` file to `.gitignore`**, because usually it contains sensitive information such as your credentials, secret keys, passwords etc. You don't want to commit this file, it's supposed to be local only. diff --git a/plugins/dotenv/dotenv.plugin.zsh b/plugins/dotenv/dotenv.plugin.zsh index 46cd4b10a..b4d209b67 100644 --- a/plugins/dotenv/dotenv.plugin.zsh +++ b/plugins/dotenv/dotenv.plugin.zsh @@ -10,6 +10,20 @@ ## Functions +_dotenv_list_match() { + emulate -L zsh + local dirpath=$1 list_file=$2 line + + [[ -r $list_file ]] || return 1 + + while IFS= read -r line || [[ -n $line ]]; do + [[ -z "$line" || "$line" == \#* ]] && continue + [[ $dirpath == ${~line} ]] && return 0 + done < "$list_file" + + return 1 +} + source_env() { if [[ ! -f "$ZSH_DOTENV_FILE" ]]; then return @@ -23,12 +37,12 @@ source_env() { touch "$ZSH_DOTENV_DISALLOWED_LIST" # early return if disallowed - if command grep -Fx -q "$dirpath" "$ZSH_DOTENV_DISALLOWED_LIST" &>/dev/null; then + if _dotenv_list_match "$dirpath" "$ZSH_DOTENV_DISALLOWED_LIST"; then return fi # check if current directory's .env file is allowed or ask for confirmation - if ! command grep -Fx -q "$dirpath" "$ZSH_DOTENV_ALLOWED_LIST" &>/dev/null; then + if ! _dotenv_list_match "$dirpath" "$ZSH_DOTENV_ALLOWED_LIST"; then # get cursor column and print new line before prompt if not at line beginning local column echo -ne "\e[6n" > /dev/tty @@ -44,8 +58,8 @@ source_env() { # check input case "$confirmation" in [nN]) return ;; - [aA]) echo "$dirpath" >> "$ZSH_DOTENV_ALLOWED_LIST" ;; - [eE]) echo "$dirpath" >> "$ZSH_DOTENV_DISALLOWED_LIST"; return ;; + [aA]) print -r -- "${(b)dirpath}" >> "$ZSH_DOTENV_ALLOWED_LIST" ;; + [eE]) print -r -- "${(b)dirpath}" >> "$ZSH_DOTENV_DISALLOWED_LIST"; return ;; *) ;; # interpret anything else as a yes esac fi