mirror of
https://github.com/robbyrussell/oh-my-zsh.git
synced 2026-09-28 05:56:07 +02:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78c871176f | ||
|
|
1595e00f7c | ||
|
|
eb62826522 | ||
|
|
c15b32baa4 |
@@ -41,3 +41,49 @@ jobs:
|
||||
./themes/*.zsh-theme; do
|
||||
zsh -n "$file" || return 1
|
||||
done
|
||||
|
||||
- name: Focused syntax check for bootstrap-adjacent touched files
|
||||
if: github.event_name == 'pull_request'
|
||||
run: |
|
||||
mapfile -t touched < <(
|
||||
git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.sha }}" \
|
||||
| grep -E '^(lib/bootstrap\.zsh|lib/tests/bootstrap.*\.zsh|oh-my-zsh\.sh|lib/(completion|compfix|functions|theme-and-appearance)\.zsh|plugins/.+/.+\.plugin\.zsh|themes/.+\.zsh-theme)$' \
|
||||
|| true
|
||||
)
|
||||
|
||||
if [ "${#touched[@]}" -eq 0 ]; then
|
||||
echo "No bootstrap-adjacent files touched"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for file in "${touched[@]}"; do
|
||||
echo "Syntax checking $file"
|
||||
zsh -n "$file"
|
||||
done
|
||||
|
||||
- name: Run bootstrap unit test
|
||||
if: github.event_name == 'pull_request'
|
||||
run: zsh ./lib/tests/bootstrap.test.zsh
|
||||
|
||||
- name: Run inline bootstrap invariants smoke test
|
||||
if: github.event_name == 'pull_request'
|
||||
run: zsh ./lib/tests/bootstrap-inline-ci.test.zsh
|
||||
|
||||
plugin-manager-smoke:
|
||||
name: Plugin manager smoke (${{ matrix.manager }}:${{ matrix.scenario }})
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'ohmyzsh/ohmyzsh' && github.event_name == 'pull_request'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
manager: [antigen, zinit]
|
||||
scenario: [positive, negative]
|
||||
steps:
|
||||
- name: Set up git repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Install zsh
|
||||
run: sudo apt-get update; sudo apt-get install zsh
|
||||
|
||||
- name: Run plugin-manager bootstrap integration
|
||||
run: zsh ./lib/tests/plugin-manager-bootstrap-integration.test.zsh "${{ matrix.manager }}" "${{ matrix.scenario }}"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
name: Plugin manager integration (advisory)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 6 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
plugin-manager-matrix:
|
||||
name: ${{ matrix.manager }}:${{ matrix.scenario }}
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'ohmyzsh/ohmyzsh'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
manager: [antigen, zinit, zgen, zplug, antibody, zulu]
|
||||
scenario: [positive, negative]
|
||||
|
||||
steps:
|
||||
- name: Set up git repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Install zsh and go
|
||||
run: sudo apt-get update; sudo apt-get install zsh golang
|
||||
|
||||
- name: Run plugin-manager bootstrap integration
|
||||
run: zsh ./lib/tests/plugin-manager-bootstrap-integration.test.zsh "${{ matrix.manager }}" "${{ matrix.scenario }}"
|
||||
|
||||
- name: Rollout note
|
||||
if: always()
|
||||
run: |
|
||||
echo "Phase 2 active: full manager matrix is advisory/nightly."
|
||||
echo "Phase 3 target: promote full matrix to required after stability window."
|
||||
@@ -361,7 +361,8 @@ source "$ZSH/lib/bootstrap.zsh"
|
||||
|
||||
#### Bootstrap compatibility contract
|
||||
|
||||
`lib/bootstrap.zsh` is idempotent and guarantees:
|
||||
`lib/bootstrap.zsh` is idempotent and is the only required pre-load step for plugin-manager setups.
|
||||
It guarantees:
|
||||
|
||||
- `ZSH`, `ZSH_CUSTOM`, and `ZSH_CACHE_DIR` defaults
|
||||
- writable cache fallback to `${XDG_CACHE_HOME:-$HOME/.cache}/oh-my-zsh`
|
||||
@@ -372,7 +373,7 @@ source "$ZSH/lib/bootstrap.zsh"
|
||||
- `$ZSH_CUSTOM/functions`
|
||||
- `$ZSH_CUSTOM/completions`
|
||||
- `$ZSH_CACHE_DIR/completions`
|
||||
- public signal: `OMZ_IS_BOOTSTRAPPED=true`
|
||||
- public signal: `OMZ_IS_BOOTSTRAPPED=true` (for one-time hook guards)
|
||||
|
||||
What still requires `oh-my-zsh.sh`:
|
||||
|
||||
@@ -386,10 +387,61 @@ What still requires `oh-my-zsh.sh`:
|
||||
|
||||
Run bootstrap once, before any OMZ plugin/theme load:
|
||||
|
||||
- **Antigen:** add a one-time pre-bundle hook to source `lib/bootstrap.zsh`.
|
||||
- **Zinit:** use a pre-load/`atinit` hook for OMZ snippets/plugins.
|
||||
- **zplug:** use a load hook (`hook-load`) before OMZ plugin/theme sourcing.
|
||||
- **zgen / zulu:** source `lib/bootstrap.zsh` immediately before OMZ plugin/theme load lines.
|
||||
```zsh
|
||||
[[ -n "${OMZ_IS_BOOTSTRAPPED:-}" ]] || source "$ZSH/lib/bootstrap.zsh"
|
||||
```
|
||||
|
||||
- **Antigen** (pre-bundle hook pattern):
|
||||
|
||||
```zsh
|
||||
omz_preload() { [[ -n "${OMZ_IS_BOOTSTRAPPED:-}" ]] || source "$ZSH/lib/bootstrap.zsh"; }
|
||||
omz_preload
|
||||
antigen bundle OMZ::plugins/git
|
||||
antigen apply
|
||||
```
|
||||
|
||||
- **Zinit** (`atinit` pre-load hook):
|
||||
|
||||
```zsh
|
||||
zinit ice atinit'[[ -n "${OMZ_IS_BOOTSTRAPPED:-}" ]] || source "$ZSH/lib/bootstrap.zsh"'
|
||||
zinit snippet OMZ::plugins/git/git.plugin.zsh
|
||||
```
|
||||
|
||||
- **zgen** (pre-load hook function called before OMZ loads):
|
||||
|
||||
```zsh
|
||||
omz_preload() { [[ -n "${OMZ_IS_BOOTSTRAPPED:-}" ]] || source "$ZSH/lib/bootstrap.zsh"; }
|
||||
omz_preload
|
||||
zgen load ohmyzsh/ohmyzsh plugins/git
|
||||
```
|
||||
|
||||
- **zplug** (run pre-load hook immediately before OMZ entries):
|
||||
|
||||
```zsh
|
||||
omz_preload() { [[ -n "${OMZ_IS_BOOTSTRAPPED:-}" ]] || source "$ZSH/lib/bootstrap.zsh"; }
|
||||
omz_preload
|
||||
zplug "plugins/git", from:oh-my-zsh
|
||||
zplug load
|
||||
```
|
||||
|
||||
- **antibody** (run pre-load hook before `antibody bundle`/`source` output):
|
||||
|
||||
```zsh
|
||||
omz_preload() { [[ -n "${OMZ_IS_BOOTSTRAPPED:-}" ]] || source "$ZSH/lib/bootstrap.zsh"; }
|
||||
omz_preload
|
||||
source <(antibody bundle <<'EOF'
|
||||
ohmyzsh/ohmyzsh path:plugins/git
|
||||
EOF
|
||||
)
|
||||
```
|
||||
|
||||
- **zulu** (run pre-load hook before OMZ module loads):
|
||||
|
||||
```zsh
|
||||
omz_preload() { [[ -n "${OMZ_IS_BOOTSTRAPPED:-}" ]] || source "$ZSH/lib/bootstrap.zsh"; }
|
||||
omz_preload
|
||||
zulu install oh-my-zsh
|
||||
```
|
||||
|
||||
Compatibility matrix:
|
||||
|
||||
@@ -398,6 +450,20 @@ Compatibility matrix:
|
||||
| `source $ZSH/oh-my-zsh.sh` | ✅ | ✅ | Full OMZ framework features |
|
||||
| `source $ZSH/lib/bootstrap.zsh` + manager-loaded OMZ plugins/themes | ✅ | ❌ | Plugin/theme prerequisites only |
|
||||
|
||||
#### Manager entrypoints and OMZ-side auto-injection limits
|
||||
|
||||
Most plugin managers load OMZ by directly sourcing selected plugin/theme/lib entrypoints, not by sourcing
|
||||
`oh-my-zsh.sh`, so OMZ cannot universally inject bootstrap on its own.
|
||||
|
||||
| Manager | Typical OMZ entrypoint(s) it loads | Can OMZ auto-inject bootstrap without user hook? |
|
||||
| :-- | :-- | :--: |
|
||||
| Antigen | `antigen bundle ...` targets after `antigen use oh-my-zsh` | ❌ |
|
||||
| Zinit | `OMZ::`, `OMZL::`, `OMZP::`, `OMZT::` snippets | ❌ |
|
||||
| zgen | `zgen oh-my-zsh ...` selected OMZ paths | ❌ |
|
||||
| zplug | `from:oh-my-zsh` selected OMZ entries | ❌ |
|
||||
| antibody | `ohmyzsh/ohmyzsh path:...` selected OMZ paths | ❌ |
|
||||
| zulu | OMZ package/module entries selected by zulu | ❌ |
|
||||
|
||||
### Enable GNU ls In macOS And FreeBSD Systems
|
||||
|
||||
<a name="enable-gnu-ls"></a>
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/zsh -df
|
||||
|
||||
set -eu
|
||||
|
||||
bootstrap_file="${0:A:h:h}/bootstrap.zsh"
|
||||
|
||||
assert() {
|
||||
local condition="$1" message="$2"
|
||||
if ! eval "$condition"; then
|
||||
print -u2 "\e[31mError\e[0m: $message"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
tmp==(:)
|
||||
mkdir -p "$tmp/ohmyzsh"/{functions,completions,cache} "$tmp/ohmyzsh/custom"/{functions,completions}
|
||||
|
||||
export ZSH="$tmp/ohmyzsh"
|
||||
unset ZSH_CUSTOM ZSH_CACHE_DIR OMZ_IS_BOOTSTRAPPED
|
||||
fpath=()
|
||||
|
||||
source "$bootstrap_file"
|
||||
|
||||
assert '[[ "$OMZ_IS_BOOTSTRAPPED" == true ]]' "OMZ bootstrap signal should be true"
|
||||
assert '[[ -d "$ZSH_CACHE_DIR/completions" ]]' "cache completions directory should exist"
|
||||
assert '[[ "${fpath[(Ie)$ZSH/functions]}" -gt 0 ]]' "fpath should include OMZ functions"
|
||||
assert '[[ "${fpath[(Ie)$ZSH/completions]}" -gt 0 ]]' "fpath should include OMZ completions"
|
||||
assert '[[ "${fpath[(Ie)$ZSH_CUSTOM/functions]}" -gt 0 ]]' "fpath should include custom functions"
|
||||
assert '[[ "${fpath[(Ie)$ZSH_CUSTOM/completions]}" -gt 0 ]]' "fpath should include custom completions"
|
||||
assert '[[ "${fpath[(Ie)$ZSH_CACHE_DIR/completions]}" -gt 0 ]]' "fpath should include cache completions"
|
||||
|
||||
touch "$ZSH_CACHE_DIR/completions/_bootstrap_ci_smoke"
|
||||
assert '[[ -f "$ZSH_CACHE_DIR/completions/_bootstrap_ci_smoke" ]]' "completion cache write should succeed"
|
||||
|
||||
print -u2 "\e[32mSuccess\e[0m bootstrap inline invariants"
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/zsh -df
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if (( $# != 2 )); then
|
||||
print -u2 "Usage: $0 <manager> <positive|negative>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
manager="$1"
|
||||
scenario="$2"
|
||||
|
||||
if [[ "$scenario" != "positive" && "$scenario" != "negative" ]]; then
|
||||
print -u2 "scenario must be 'positive' or 'negative'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
repo_root="${0:A:h:h:h}"
|
||||
tmp==(:)
|
||||
workspace="$tmp/workspace"
|
||||
home_dir="$tmp/home"
|
||||
cache_dir="$tmp/cache"
|
||||
zshrc="$tmp/.zshrc"
|
||||
|
||||
mkdir -p "$workspace" "$home_dir" "$cache_dir"
|
||||
|
||||
manager_install=''
|
||||
manager_source=''
|
||||
|
||||
case "$manager" in
|
||||
antigen)
|
||||
manager_install='git clone https://github.com/zsh-users/antigen.git "$MANAGER_HOME/antigen" >/dev/null 2>&1'
|
||||
manager_source='source "$MANAGER_HOME/antigen/antigen.zsh"'
|
||||
;;
|
||||
zinit)
|
||||
manager_install='git clone https://github.com/zdharma-continuum/zinit.git "$MANAGER_HOME/zinit" >/dev/null 2>&1'
|
||||
manager_source='source "$MANAGER_HOME/zinit/zinit.zsh"'
|
||||
;;
|
||||
zgen)
|
||||
manager_install='git clone https://github.com/tarjoilija/zgen.git "$MANAGER_HOME/zgen" >/dev/null 2>&1'
|
||||
manager_source='source "$MANAGER_HOME/zgen/zgen.zsh"'
|
||||
;;
|
||||
zplug)
|
||||
manager_install='git clone https://github.com/zplug/zplug "$MANAGER_HOME/zplug" >/dev/null 2>&1'
|
||||
manager_source='export ZPLUG_HOME="$MANAGER_HOME/zplug"; source "$ZPLUG_HOME/init.zsh"'
|
||||
;;
|
||||
antibody)
|
||||
manager_install='command -v go >/dev/null 2>&1; export GOBIN="$MANAGER_HOME/bin"; mkdir -p "$GOBIN"; go install github.com/getantibody/antibody@latest >/dev/null 2>&1'
|
||||
manager_source='"$MANAGER_HOME/bin/antibody" --version >/dev/null 2>&1'
|
||||
;;
|
||||
zulu)
|
||||
manager_install='git clone https://github.com/zulu-zsh/zulu.git "$MANAGER_HOME/zulu" >/dev/null 2>&1'
|
||||
manager_source='source "$MANAGER_HOME/zulu/zulu.zsh"'
|
||||
;;
|
||||
*)
|
||||
print -u2 "Unsupported manager: $manager"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
cat > "$zshrc" <<RC
|
||||
set -eo pipefail
|
||||
|
||||
export HOME="$home_dir"
|
||||
export XDG_CACHE_HOME="$cache_dir"
|
||||
export OMZ_ROOT="$repo_root"
|
||||
export ZSH="\$OMZ_ROOT"
|
||||
export MANAGER_HOME="$workspace/$manager"
|
||||
mkdir -p "\$MANAGER_HOME"
|
||||
|
||||
$manager_install
|
||||
$manager_source
|
||||
RC
|
||||
|
||||
if [[ "$scenario" == "positive" ]]; then
|
||||
cat >> "$zshrc" <<'RC'
|
||||
source "$OMZ_ROOT/lib/bootstrap.zsh"
|
||||
[[ "${OMZ_IS_BOOTSTRAPPED:-}" == true ]] || { print -u2 "bootstrap signal missing before OMZ load"; return 1; }
|
||||
RC
|
||||
else
|
||||
cat >> "$zshrc" <<'RC'
|
||||
[[ -z "${OMZ_IS_BOOTSTRAPPED:-}" ]] || { print -u2 "bootstrap signal unexpectedly set without hook"; return 1; }
|
||||
source "$OMZ_ROOT/lib/bootstrap.zsh"
|
||||
RC
|
||||
fi
|
||||
|
||||
cat >> "$zshrc" <<RC
|
||||
[[ "\${OMZ_IS_BOOTSTRAPPED:-}" == true ]] || { print -u2 "bootstrap signal not set before OMZ entrypoint sourcing"; return 1; }
|
||||
|
||||
source "\$OMZ_ROOT/lib/functions.zsh"
|
||||
source "\$OMZ_ROOT/plugins/git/git.plugin.zsh"
|
||||
autoload -Uz compinit
|
||||
compinit -i -d "\$ZSH_CACHE_DIR/.zcompdump"
|
||||
|
||||
source "\$OMZ_ROOT/themes/robbyrussell.zsh-theme"
|
||||
|
||||
[[ -d "\$ZSH_CACHE_DIR/completions" ]] || { print -u2 "completions cache directory missing"; return 1; }
|
||||
|
||||
touch "\$ZSH_CACHE_DIR/completions/_ci_${manager}_${scenario}" || { print -u2 "completion cache write failed"; return 1; }
|
||||
[[ -f "\$ZSH_CACHE_DIR/completions/_ci_${manager}_${scenario}" ]] || { print -u2 "completion cache file missing"; return 1; }
|
||||
RC
|
||||
|
||||
zsh -df "$zshrc"
|
||||
print -u2 "\e[32mSuccess\e[0m $manager $scenario"
|
||||
@@ -48,10 +48,6 @@ fi
|
||||
0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
|
||||
0="${${(M)0:#/*}:-$PWD/$0}"
|
||||
|
||||
# Ensure cache completions dir exists when the plugin is loaded directly
|
||||
# (e.g. antigen, where oh-my-zsh.sh might not run).
|
||||
command mkdir -p "$ZSH_CACHE_DIR/completions"
|
||||
|
||||
# If the completion file doesn't exist yet, we need to autoload it and
|
||||
# bind it to `docker`. Otherwise, compinit will have already done that.
|
||||
if [[ ! -f "$ZSH_CACHE_DIR/completions/_docker" ]]; then
|
||||
|
||||
Reference in New Issue
Block a user