mirror of
https://github.com/robbyrussell/oh-my-zsh.git
synced 2026-09-21 18:46:06 +02:00
feat(updater): add cooldown option to delay applying updates (#13814)
* feat(updater): add cooldown option to delay applying updates (#13813) Introduces a new `zstyle ':omz:update' cooldown <days>` setting that limits the updater to only apply commits that are at least N days old. Defaults to 0 (current behavior — always pull latest). When cooldown is set, the updater fetches the remote branch and finds the most recent commit whose committer timestamp is at least N days old, then applies it via `git merge --ff-only`. If the local copy is already at or past the cooldown ref, nothing changes. - tools/upgrade.sh: reads cooldown zstyle, replaces git pull with fetch + merge --ff-only when cooldown > 0 - README.md: documents the new setting under "Getting Updates" - templates/zshrc.zsh-template: adds commented-out cooldown example alongside frequency, with rephrased comments to clarify how the two work together * fix(updater): address cooldown review feedback Pass cooldown into upgrade.sh as -c, extract the update helpers, and only prompt when a cooldown-eligible commit would actually move HEAD. * fix(updater): follow first-parent history for cooldown
This commit is contained in:
@@ -474,6 +474,22 @@ zstyle ':omz:update' frequency 7
|
|||||||
zstyle ':omz:update' frequency 0
|
zstyle ':omz:update' frequency 0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default, updates always pull the latest changes. If you'd rather let others kick the tires first
|
||||||
|
before an update reaches your machine, you can set a cooldown (in days). You'll still get everything —
|
||||||
|
just a little later:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Only apply updates that are at least 10 days old
|
||||||
|
zstyle ':omz:update' cooldown 10
|
||||||
|
```
|
||||||
|
|
||||||
|
`omz update` honors this setting. If you call `upgrade.sh` directly, pass the same
|
||||||
|
value with `-c`, because that script does not read your `.zshrc`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ZSH/tools/upgrade.sh -c 10
|
||||||
|
```
|
||||||
|
|
||||||
### Updates Verbosity
|
### Updates Verbosity
|
||||||
|
|
||||||
You can also limit the update verbosity with the following settings:
|
You can also limit the update verbosity with the following settings:
|
||||||
|
|||||||
+4
-1
@@ -903,8 +903,11 @@ function _omz::update {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Run update script
|
# Run update script
|
||||||
|
local verbose_mode cooldown_days
|
||||||
zstyle -s ':omz:update' verbose verbose_mode || verbose_mode=default
|
zstyle -s ':omz:update' verbose verbose_mode || verbose_mode=default
|
||||||
ZSH="$ZSH" command zsh -f "$ZSH/tools/upgrade.sh" -i -v $verbose_mode || return $?
|
zstyle -s ':omz:update' cooldown cooldown_days || cooldown_days=0
|
||||||
|
[[ $cooldown_days == <-> ]] || cooldown_days=0
|
||||||
|
ZSH="$ZSH" command zsh -f "$ZSH/tools/upgrade.sh" -i -v $verbose_mode -c $cooldown_days || return $?
|
||||||
|
|
||||||
# Update last updated file
|
# Update last updated file
|
||||||
zmodload zsh/datetime
|
zmodload zsh/datetime
|
||||||
|
|||||||
@@ -28,9 +28,12 @@ ZSH_THEME="robbyrussell"
|
|||||||
# zstyle ':omz:update' mode auto # update automatically without asking
|
# zstyle ':omz:update' mode auto # update automatically without asking
|
||||||
# zstyle ':omz:update' mode reminder # just remind me to update when it's time
|
# zstyle ':omz:update' mode reminder # just remind me to update when it's time
|
||||||
|
|
||||||
# Uncomment the following line to change how often to auto-update (in days).
|
# Uncomment the following line to change the frequency the auto-updater is run (in days).
|
||||||
# zstyle ':omz:update' frequency 13
|
# zstyle ':omz:update' frequency 13
|
||||||
|
|
||||||
|
# Uncomment the following line to set how old an update must be before it's applied, manually or via the auto-updater (in days).
|
||||||
|
# zstyle ':omz:update' cooldown 10
|
||||||
|
|
||||||
# Uncomment the following line if pasting URLs and other text is messed up.
|
# Uncomment the following line if pasting URLs and other text is messed up.
|
||||||
# DISABLE_MAGIC_FUNCTIONS="true"
|
# DISABLE_MAGIC_FUNCTIONS="true"
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,26 @@ function is_update_available() {
|
|||||||
remote=${"$(builtin cd -q "$ZSH"; git config --local oh-my-zsh.remote)":-origin}
|
remote=${"$(builtin cd -q "$ZSH"; git config --local oh-my-zsh.remote)":-origin}
|
||||||
remote_url=$(builtin cd -q "$ZSH"; git config remote.$remote.url)
|
remote_url=$(builtin cd -q "$ZSH"; git config remote.$remote.url)
|
||||||
|
|
||||||
|
local cooldown_days
|
||||||
|
zstyle -s ':omz:update' cooldown cooldown_days || cooldown_days=0
|
||||||
|
[[ $cooldown_days == <-> ]] || cooldown_days=0
|
||||||
|
|
||||||
|
if (( cooldown_days > 0 )); then
|
||||||
|
local local_head cutoff_epoch cooldown_ref
|
||||||
|
local_head=$(builtin cd -q "$ZSH"; git rev-parse $branch 2>/dev/null) || return 0
|
||||||
|
(builtin cd -q "$ZSH"; LANG= git fetch --quiet $remote $branch) || return 1
|
||||||
|
zmodload zsh/datetime
|
||||||
|
cutoff_epoch=$(( EPOCHSECONDS - cooldown_days * 86400 ))
|
||||||
|
cooldown_ref=$(builtin cd -q "$ZSH"; git log --first-parent --format="%H %ct" FETCH_HEAD \
|
||||||
|
| awk -v c="$cutoff_epoch" '$2 <= c { print $1; exit }')
|
||||||
|
[[ -n "$cooldown_ref" ]] || return 1
|
||||||
|
[[ "$cooldown_ref" != "$local_head" ]] || return 1
|
||||||
|
if (builtin cd -q "$ZSH"; git merge-base --is-ancestor "$cooldown_ref" "$local_head" 2>/dev/null); then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
local repo
|
local repo
|
||||||
case "$remote_url" in
|
case "$remote_url" in
|
||||||
https://github.com/*) repo=${${remote_url#https://github.com/}%.git} ;;
|
https://github.com/*) repo=${${remote_url#https://github.com/}%.git} ;;
|
||||||
@@ -129,8 +149,10 @@ EOD
|
|||||||
}
|
}
|
||||||
|
|
||||||
function update_ohmyzsh() {
|
function update_ohmyzsh() {
|
||||||
local verbose_mode
|
local verbose_mode cooldown_days
|
||||||
zstyle -s ':omz:update' verbose verbose_mode || verbose_mode=default
|
zstyle -s ':omz:update' verbose verbose_mode || verbose_mode=default
|
||||||
|
zstyle -s ':omz:update' cooldown cooldown_days || cooldown_days=0
|
||||||
|
[[ $cooldown_days == <-> ]] || cooldown_days=0
|
||||||
|
|
||||||
# Force verbose mode to silent if p10k instant prompt is enabled
|
# Force verbose mode to silent if p10k instant prompt is enabled
|
||||||
if [[ ${POWERLEVEL9K_INSTANT_PROMPT:-off} != "off" ]]; then
|
if [[ ${POWERLEVEL9K_INSTANT_PROMPT:-off} != "off" ]]; then
|
||||||
@@ -138,13 +160,13 @@ function update_ohmyzsh() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$update_mode" != background-alpha ]] \
|
if [[ "$update_mode" != background-alpha ]] \
|
||||||
&& LANG= ZSH="$ZSH" zsh -f "$ZSH/tools/upgrade.sh" -i -v $verbose_mode; then
|
&& LANG= ZSH="$ZSH" zsh -f "$ZSH/tools/upgrade.sh" -i -v $verbose_mode -c $cooldown_days; then
|
||||||
update_last_updated_file
|
update_last_updated_file
|
||||||
return $?
|
return $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local exit_status error
|
local exit_status error
|
||||||
if error=$(LANG= ZSH="$ZSH" zsh -f "$ZSH/tools/upgrade.sh" -i -v silent 2>&1); then
|
if error=$(LANG= ZSH="$ZSH" zsh -f "$ZSH/tools/upgrade.sh" -i -v silent -c $cooldown_days 2>&1); then
|
||||||
update_last_updated_file 0 "Update successful"
|
update_last_updated_file 0 "Update successful"
|
||||||
else
|
else
|
||||||
exit_status=$?
|
exit_status=$?
|
||||||
|
|||||||
+43
-3
@@ -13,6 +13,8 @@ case "$ZSH_EVAL_CONTEXT" in
|
|||||||
*:file) echo "error: this file should not be sourced" && return 1 ;;
|
*:file) echo "error: this file should not be sourced" && return 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
zmodload zsh/datetime
|
||||||
|
|
||||||
# Define "$ZSH" if not defined -- in theory this should be `export`ed by the calling script
|
# Define "$ZSH" if not defined -- in theory this should be `export`ed by the calling script
|
||||||
if [[ -z "$ZSH" ]]; then
|
if [[ -z "$ZSH" ]]; then
|
||||||
ZSH="${0:a:h:h}"
|
ZSH="${0:a:h:h}"
|
||||||
@@ -22,8 +24,9 @@ cd "$ZSH"
|
|||||||
|
|
||||||
verbose_mode="default"
|
verbose_mode="default"
|
||||||
interactive=false
|
interactive=false
|
||||||
|
cooldown_days=0
|
||||||
|
|
||||||
while getopts "v:i" opt; do
|
while getopts "v:ic:" opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
v)
|
v)
|
||||||
if [[ $OPTARG == default || $OPTARG == minimal || $OPTARG == silent ]]; then
|
if [[ $OPTARG == default || $OPTARG == minimal || $OPTARG == silent ]]; then
|
||||||
@@ -34,6 +37,14 @@ while getopts "v:i" opt; do
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
i) interactive=true ;;
|
i) interactive=true ;;
|
||||||
|
c)
|
||||||
|
if [[ $OPTARG == <-> ]]; then
|
||||||
|
cooldown_days=$OPTARG
|
||||||
|
else
|
||||||
|
echo "[oh-my-zsh] update cooldown '$OPTARG' is not valid"
|
||||||
|
echo "[oh-my-zsh] valid options are a non-negative integer (days)"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -231,6 +242,28 @@ local ret=0
|
|||||||
remote=${"$(git config --local oh-my-zsh.remote)":-origin}
|
remote=${"$(git config --local oh-my-zsh.remote)":-origin}
|
||||||
branch=${"$(git config --local oh-my-zsh.branch)":-master}
|
branch=${"$(git config --local oh-my-zsh.branch)":-master}
|
||||||
|
|
||||||
|
update_with_cooldown() {
|
||||||
|
local cutoff_epoch cooldown_ref
|
||||||
|
|
||||||
|
cutoff_epoch=$(( EPOCHSECONDS - cooldown_days * 86400 ))
|
||||||
|
LANG= git fetch --quiet $remote $branch || return $?
|
||||||
|
|
||||||
|
cooldown_ref=$(git log --first-parent --format="%H %ct" FETCH_HEAD \
|
||||||
|
| awk -v c="$cutoff_epoch" '$2 <= c { print $1; exit }')
|
||||||
|
|
||||||
|
[[ -n "$cooldown_ref" ]] || return 0
|
||||||
|
|
||||||
|
LANG= git merge --ff-only --quiet "$cooldown_ref"
|
||||||
|
}
|
||||||
|
|
||||||
|
perform_update() {
|
||||||
|
if (( cooldown_days > 0 )); then
|
||||||
|
update_with_cooldown
|
||||||
|
else
|
||||||
|
LANG= git pull --quiet --rebase $remote $branch
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# repository state
|
# repository state
|
||||||
last_head=$(git symbolic-ref --quiet --short HEAD || git rev-parse HEAD)
|
last_head=$(git symbolic-ref --quiet --short HEAD || git rev-parse HEAD)
|
||||||
# checkout update branch
|
# checkout update branch
|
||||||
@@ -242,10 +275,17 @@ last_commit=$(git rev-parse "$branch")
|
|||||||
if [[ $verbose_mode != silent ]]; then
|
if [[ $verbose_mode != silent ]]; then
|
||||||
printf "${BLUE}%s${RESET}\n" "Updating Oh My Zsh"
|
printf "${BLUE}%s${RESET}\n" "Updating Oh My Zsh"
|
||||||
fi
|
fi
|
||||||
if LANG= git pull --quiet --rebase $remote $branch; then
|
if perform_update; then
|
||||||
# Check if it was really updated or not
|
# Check if it was really updated or not
|
||||||
if [[ "$(git rev-parse HEAD)" = "$last_commit" ]]; then
|
if [[ "$(git rev-parse HEAD)" = "$last_commit" ]]; then
|
||||||
message="Oh My Zsh is already at the latest version."
|
if (( cooldown_days > 0 )); then
|
||||||
|
head_ct=$(git log -1 --format=%ct HEAD)
|
||||||
|
age_days=$(( (EPOCHSECONDS - head_ct) / 86400 ))
|
||||||
|
(( age_days < 0 )) && age_days=0
|
||||||
|
message="Oh My Zsh is already at a version ${age_days} days old."
|
||||||
|
else
|
||||||
|
message="Oh My Zsh is already at the latest version."
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
message="Hooray! Oh My Zsh has been updated!"
|
message="Hooray! Oh My Zsh has been updated!"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user