1 Commits

Author SHA1 Message Date
Robby Russell
84429a7229 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
2026-06-12 11:34:27 -07:00
16 changed files with 68 additions and 43 deletions

View File

@@ -21,7 +21,7 @@ jobs:
egress-policy: audit egress-policy: audit
- name: Checkout - name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Authenticate as @ohmyzsh - name: Authenticate as @ohmyzsh
@@ -31,7 +31,7 @@ jobs:
client-id: ${{ secrets.OHMYZSH_CLIENT_ID }} client-id: ${{ secrets.OHMYZSH_CLIENT_ID }}
private-key: ${{ secrets.OHMYZSH_APP_PRIVATE_KEY }} private-key: ${{ secrets.OHMYZSH_APP_PRIVATE_KEY }}
- name: Setup Python - name: Setup Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with: with:
python-version: "3.12" python-version: "3.12"
cache: "pip" cache: "pip"

View File

@@ -31,7 +31,7 @@ jobs:
egress-policy: audit egress-policy: audit
- name: Set up git repository - name: Set up git repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Install zsh - name: Install zsh
if: runner.os == 'Linux' if: runner.os == 'Linux'
run: sudo apt-get update; sudo apt-get install zsh run: sudo apt-get update; sudo apt-get install zsh
@@ -52,7 +52,7 @@ jobs:
egress-policy: audit egress-policy: audit
- name: Checkout - name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Install Vercel CLI - name: Install Vercel CLI
run: npm install -g vercel run: npm install -g vercel
- name: Setup project and deploy - name: Setup project and deploy

View File

@@ -29,7 +29,7 @@ jobs:
egress-policy: audit egress-policy: audit
- name: Set up git repository - name: Set up git repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Install zsh - name: Install zsh
run: sudo apt-get update; sudo apt-get install zsh run: sudo apt-get update; sudo apt-get install zsh
- name: Check syntax - name: Check syntax

View File

@@ -41,7 +41,7 @@ jobs:
egress-policy: audit egress-policy: audit
- name: "Checkout code" - name: "Checkout code"
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with: with:
persist-credentials: false persist-credentials: false

View File

@@ -466,6 +466,15 @@ 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
```
### 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:

View File

@@ -162,13 +162,13 @@ if zstyle -t ':omz:alpha:lib:git' async-prompt \
# or any of the other prompt variables # or any of the other prompt variables
function _defer_async_git_register() { function _defer_async_git_register() {
# Check if git_prompt_info is used in a prompt variable # Check if git_prompt_info is used in a prompt variable
case "${PS1}:${PS2}:${PS3}:${PS4}:${RPROMPT-}:${RPS1-}:${RPS2-}:${RPS3-}:${RPS4-}" in case "${PS1}:${PS2}:${PS3}:${PS4}:${RPROMPT}:${RPS1}:${RPS2}:${RPS3}:${RPS4}" in
*(\$\(git_prompt_info\)|\`git_prompt_info\`)*) *(\$\(git_prompt_info\)|\`git_prompt_info\`)*)
_omz_register_handler _omz_git_prompt_info _omz_register_handler _omz_git_prompt_info
;; ;;
esac esac
case "${PS1}:${PS2}:${PS3}:${PS4}:${RPROMPT-}:${RPS1-}:${RPS2-}:${RPS3-}:${RPS4-}" in case "${PS1}:${PS2}:${PS3}:${PS4}:${RPROMPT}:${RPS1}:${RPS2}:${RPS3}:${RPS4}" in
*(\$\(git_prompt_status\)|\`git_prompt_status\`)*) *(\$\(git_prompt_status\)|\`git_prompt_status\`)*)
_omz_register_handler _omz_git_prompt_status _omz_register_handler _omz_git_prompt_status
;; ;;

View File

@@ -4,10 +4,10 @@ function ansible-version() {
} }
function ansible-role-init(){ function ansible-role-init(){
if [[ -n "$1" ]]; then if ! [ -z $1 ] ; then
echo "Ansible Role : $1 Creating...." echo "Ansible Role : $1 Creating...."
ansible-galaxy init "$1" ansible-galaxy init $1
tree "$1" tree $1
else else
echo "Usage : ansible-role-init <role name>" echo "Usage : ansible-role-init <role name>"
echo "Example : ansible-role-init role1" echo "Example : ansible-role-init role1"

View File

@@ -9,14 +9,14 @@ function agr() {
# Update state file if enabled # Update state file if enabled
function _aws_update_state() { function _aws_update_state() {
if [[ "$AWS_PROFILE_STATE_ENABLED" == true ]]; then if [[ "$AWS_PROFILE_STATE_ENABLED" == true ]]; then
test -d $(dirname ${AWS_STATE_FILE}) || return 1 test -d $(dirname ${AWS_STATE_FILE}) || exit 1
echo "${AWS_PROFILE} ${AWS_REGION}" > "${AWS_STATE_FILE}" echo "${AWS_PROFILE} ${AWS_REGION}" > "${AWS_STATE_FILE}"
fi fi
} }
function _aws_clear_state() { function _aws_clear_state() {
if [[ "$AWS_PROFILE_STATE_ENABLED" == true ]]; then if [[ "$AWS_PROFILE_STATE_ENABLED" == true ]]; then
test -d $(dirname ${AWS_STATE_FILE}) || return 1 test -d $(dirname ${AWS_STATE_FILE}) || exit 1
echo -n > "${AWS_STATE_FILE}" echo -n > "${AWS_STATE_FILE}"
fi fi
} }

View File

@@ -16,7 +16,7 @@ of `dnf5` and uses it as drop-in alternative to the slower `dnf`.
## Aliases ## Aliases
| Alias | Command | Description | | Alias | Command | Description |
|-------|-------------------------------|------------------------------------------| |-------|-------------------------|--------------------------|
| dnfl | `dnf list` | List packages | | dnfl | `dnf list` | List packages |
| dnfli | `dnf list --installed` | List installed packages | | dnfli | `dnf list --installed` | List installed packages |
| dnfgl | `dnf grouplist` | List package groups | | dnfgl | `dnf grouplist` | List package groups |
@@ -25,7 +25,6 @@ of `dnf5` and uses it as drop-in alternative to the slower `dnf`.
| dnfs | `dnf search` | Search package | | dnfs | `dnf search` | Search package |
| **Use `sudo`** | | **Use `sudo`** |
| dnfu | `sudo dnf upgrade` | Upgrade package | | dnfu | `sudo dnf upgrade` | Upgrade package |
| dnfur | `sudo dnf upgrade --refresh` | Upgrade package (force metadata refresh) |
| dnfi | `sudo dnf install` | Install package | | dnfi | `sudo dnf install` | Install package |
| dnfgi | `sudo dnf groupinstall` | Install package group | | dnfgi | `sudo dnf groupinstall` | Install package group |
| dnfr | `sudo dnf remove` | Remove package | | dnfr | `sudo dnf remove` | Remove package |

View File

@@ -11,7 +11,6 @@ alias dnfp="${dnfprog} info" # Show package information
alias dnfs="${dnfprog} search" # Search package alias dnfs="${dnfprog} search" # Search package
alias dnfu="sudo ${dnfprog} upgrade" # Upgrade package alias dnfu="sudo ${dnfprog} upgrade" # Upgrade package
alias dnfur="sudo ${dnfprog} upgrade --refresh" # Upgrade package and refresh repos
alias dnfi="sudo ${dnfprog} install" # Install package alias dnfi="sudo ${dnfprog} install" # Install package
alias dnfr="sudo ${dnfprog} remove" # Remove package alias dnfr="sudo ${dnfprog} remove" # Remove package
alias dnfc="sudo ${dnfprog} clean all" # Clean cache alias dnfc="sudo ${dnfprog} clean all" # Clean cache

View File

@@ -8,7 +8,7 @@ alias puo="sudo port upgrade outdated"
alias pup="sudo port selfupdate && sudo port upgrade outdated" alias pup="sudo port selfupdate && sudo port upgrade outdated"
port-livecheck-maintainer() { port-livecheck-maintainer() {
(( ${+commands[port]} )) || { (( ${+commands[port]} == 0 )) || {
print -- "port: not found" >&2 print -- "port: not found" >&2
return 1 return 1
} }

View File

@@ -26,7 +26,7 @@ typeset -g VI_MODE_CURSOR_OPPEND=${VI_MODE_CURSOR_OPPEND:=0}
typeset -g VI_KEYMAP=${VI_KEYMAP:=main} typeset -g VI_KEYMAP=${VI_KEYMAP:=main}
function _vi-mode-set-cursor-shape-for-keymap() { function _vi-mode-set-cursor-shape-for-keymap() {
[[ "$VI_MODE_SET_CURSOR" = true ]] || return 0 [[ "$VI_MODE_SET_CURSOR" = true ]] || return
# https://vt100.net/docs/vt510-rm/DECSCUSR # https://vt100.net/docs/vt510-rm/DECSCUSR
local _shape=0 local _shape=0

View File

@@ -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"

View File

@@ -51,7 +51,7 @@ USER=${USER:-$(id -u -n)}
# POSIX: https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap08.html#tag_08_03 # POSIX: https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap08.html#tag_08_03
HOME="${HOME:-$(getent passwd $USER 2>/dev/null | cut -d: -f6)}" HOME="${HOME:-$(getent passwd $USER 2>/dev/null | cut -d: -f6)}"
# macOS does not have getent, but this works even if $HOME is unset # macOS does not have getent, but this works even if $HOME is unset
HOME="${HOME:-$(eval echo ~"$USER")}" HOME="${HOME:-$(eval echo ~$USER)}"
# Track if $ZSH was provided # Track if $ZSH was provided
@@ -344,7 +344,7 @@ setup_zshrc() {
return return
fi fi
if [ "$OVERWRITE_CONFIRMATION" != "no" ]; then if [ $OVERWRITE_CONFIRMATION != "no" ]; then
# Ask user for confirmation before backing up and overwriting # Ask user for confirmation before backing up and overwriting
echo "${FMT_YELLOW}Found ${zdot}/.zshrc." echo "${FMT_YELLOW}Found ${zdot}/.zshrc."
echo "The existing .zshrc will be backed up to .zshrc.pre-oh-my-zsh if overwritten." echo "The existing .zshrc will be backed up to .zshrc.pre-oh-my-zsh if overwritten."
@@ -473,16 +473,14 @@ EOF
# be prompted for the password either way, so this shouldn't cause any issues. # be prompted for the password either way, so this shouldn't cause any issues.
# #
if user_can_sudo; then if user_can_sudo; then
sudo -k >/dev/null 2>&1 || true # -k forces the password prompt when supported sudo -k >/dev/null 2>&1 # -k forces the password prompt
sudo chsh -s "$zsh" "$USER" sudo chsh -s "$zsh" "$USER"
chsh_status=$?
else else
chsh -s "$zsh" "$USER" # run chsh normally chsh -s "$zsh" "$USER" # run chsh normally
chsh_status=$?
fi fi
# Check if the shell change was successful # Check if the shell change was successful
if [ "$chsh_status" -ne 0 ]; then if [ $? -ne 0 ]; then
fmt_error "chsh command unsuccessful. Change your default shell manually." fmt_error "chsh command unsuccessful. Change your default shell manually."
else else
export SHELL="$zsh" export SHELL="$zsh"

View File

@@ -231,6 +231,10 @@ 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}
# cooldown: minimum age (in days) of commits to apply
local cooldown_days
zstyle -s ':omz:update' cooldown cooldown_days || cooldown_days=0
# 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,7 +246,20 @@ 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 {
if (( cooldown_days > 0 )); then
zmodload zsh/datetime
local cutoff_epoch cooldown_ref
cutoff_epoch=$(( EPOCHSECONDS - cooldown_days * 86400 ))
LANG= git fetch --quiet $remote $branch && {
cooldown_ref=$(git log --format="%H %ct" "$remote/$branch" \
| awk -v c="$cutoff_epoch" '$2 <= c { print $1; exit }')
[[ -z "$cooldown_ref" ]] || LANG= git merge --ff-only --quiet "$cooldown_ref"
}
else
LANG= git pull --quiet --rebase $remote $branch
fi
}; 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." message="Oh My Zsh is already at the latest version."