| 1 | |
| 2 | if [[ -f ~/.zsh-update && ! -f "${ZSH_CACHE_DIR}/.zsh-update" ]]; then |
| 3 | mv ~/.zsh-update "${ZSH_CACHE_DIR}/.zsh-update" |
| 4 | fi |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | zstyle -s ':omz:update' mode update_mode || { |
| 15 | update_mode=prompt |
| 16 | |
| 17 | |
| 18 | [[ "$DISABLE_UPDATE_PROMPT" != true ]] || update_mode=auto |
| 19 | [[ "$DISABLE_AUTO_UPDATE" != true ]] || update_mode=disabled |
| 20 | } |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | if [[ "$update_mode" = disabled ]] \ |
| 29 | || [[ ! -w "$ZSH" || ! -O "$ZSH" ]] \ |
| 30 | || [[ ! -t 1 && ${POWERLEVEL9K_INSTANT_PROMPT:-off} == off ]] \ |
| 31 | || ! command git --version 2>&1 >/dev/null \ |
| 32 | || (builtin cd -q "$ZSH"; ! command git rev-parse --is-inside-work-tree &>/dev/null); then |
| 33 | unset update_mode |
| 34 | return |
| 35 | fi |
| 36 | |
| 37 | function current_epoch() { |
| 38 | zmodload zsh/datetime |
| 39 | echo $(( EPOCHSECONDS / 60 / 60 / 24 )) |
| 40 | } |
| 41 | |
| 42 | function is_update_available() { |
| 43 | local branch |
| 44 | branch=${"$(builtin cd -q "$ZSH"; git config --local oh-my-zsh.branch)":-master} |
| 45 | |
| 46 | local remote remote_url remote_repo |
| 47 | remote=${"$(builtin cd -q "$ZSH"; git config --local oh-my-zsh.remote)":-origin} |
| 48 | remote_url=$(builtin cd -q "$ZSH"; git config remote.$remote.url) |
| 49 | |
| 50 | local repo |
| 51 | case "$remote_url" in |
| 52 | https://github.com/*) repo=${${remote_url#https://github.com/}%.git} ;; |
| 53 | git@github.com:*) repo=${${remote_url#git@github.com:}%.git} ;; |
| 54 | *) |
| 55 | |
| 56 | |
| 57 | return 0 ;; |
| 58 | esac |
| 59 | |
| 60 | |
| 61 | [[ "$repo" = ohmyzsh/ohmyzsh ]] || return 0 |
| 62 | local api_url="https://api.github.com/repos/${repo}/commits/${branch}" |
| 63 | |
| 64 | |
| 65 | local local_head |
| 66 | local_head=$(builtin cd -q "$ZSH"; git rev-parse $branch 2>/dev/null) || return 0 |
| 67 | |
| 68 | |
| 69 | |
| 70 | local remote_head |
| 71 | remote_head=$( |
| 72 | if (( ${+commands[curl]} )); then |
| 73 | curl --connect-timeout 2 -fsSL -H 'Accept: application/vnd.github.v3.sha' $api_url 2>/dev/null |
| 74 | elif (( ${+commands[wget]} )); then |
| 75 | wget -T 2 -O- --header='Accept: application/vnd.github.v3.sha' $api_url 2>/dev/null |
| 76 | elif (( ${+commands[fetch]} )); then |
| 77 | HTTP_ACCEPT='Accept: application/vnd.github.v3.sha' fetch -T 2 -o - $api_url 2>/dev/null |
| 78 | else |
| 79 | exit 0 |
| 80 | fi |
| 81 | ) || return 1 |
| 82 | |
| 83 | |
| 84 | [[ "$local_head" != "$remote_head" ]] || return 1 |
| 85 | |
| 86 | |
| 87 | |
| 88 | local base |
| 89 | base=$(builtin cd -q "$ZSH"; git merge-base $local_head $remote_head 2>/dev/null) || return 0 |
| 90 | |
| 91 | |
| 92 | |
| 93 | [[ $base != $remote_head ]] |
| 94 | } |
| 95 | |
| 96 | function update_last_updated_file() { |
| 97 | local exit_status="$1" error="$2" |
| 98 | |
| 99 | if [[ -z "${1}${2}" ]]; then |
| 100 | echo "LAST_EPOCH=$(current_epoch)" >! "${ZSH_CACHE_DIR}/.zsh-update" |
| 101 | return |
| 102 | fi |
| 103 | |
| 104 | cat >! "${ZSH_CACHE_DIR}/.zsh-update" <<EOD |
| 105 | LAST_EPOCH=$(current_epoch) |
| 106 | EXIT_STATUS=${exit_status} |
| 107 | ERROR='${error//\'/’}' |
| 108 | EOD |
| 109 | } |
| 110 | |
| 111 | function update_ohmyzsh() { |
| 112 | local verbose_mode |
| 113 | zstyle -s ':omz:update' verbose verbose_mode || verbose_mode=default |
| 114 | |
| 115 | |
| 116 | if [[ ${POWERLEVEL9K_INSTANT_PROMPT:-off} != "off" ]]; then |
| 117 | verbose_mode=silent |
| 118 | fi |
| 119 | |
| 120 | if [[ "$update_mode" != background-alpha ]] \ |
| 121 | && LANG= ZSH="$ZSH" zsh -f "$ZSH/tools/upgrade.sh" -i -v $verbose_mode; then |
| 122 | update_last_updated_file |
| 123 | return $? |
| 124 | fi |
| 125 | |
| 126 | local exit_status error |
| 127 | if error=$(LANG= ZSH="$ZSH" zsh -f "$ZSH/tools/upgrade.sh" -i -v silent 2>&1); then |
| 128 | update_last_updated_file 0 "Update successful" |
| 129 | else |
| 130 | exit_status=$? |
| 131 | update_last_updated_file $exit_status "$error" |
| 132 | return $exit_status |
| 133 | fi |
| 134 | } |
| 135 | |
| 136 | function has_typed_input() { |
| 137 | |
| 138 | |
| 139 | emulate -L zsh |
| 140 | zmodload zsh/zselect |
| 141 | |
| 142 | |
| 143 | |
| 144 | |
| 145 | local termios |
| 146 | termios=$(stty --save 2>/dev/null) || return 1 |
| 147 | { |
| 148 | |
| 149 | |
| 150 | stty -icanon |
| 151 | |
| 152 | |
| 153 | zselect -t 0 -r 0 |
| 154 | return $? |
| 155 | } always { |
| 156 | |
| 157 | stty $termios |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | function handle_update() { |
| 162 | () { |
| 163 | emulate -L zsh |
| 164 | |
| 165 | local epoch_target mtime option LAST_EPOCH |
| 166 | |
| 167 | |
| 168 | zmodload zsh/datetime |
| 169 | zmodload -F zsh/stat b:zstat |
| 170 | if mtime=$(zstat +mtime "$ZSH/log/update.lock" 2>/dev/null); then |
| 171 | if (( (mtime + 3600 * 24) < EPOCHSECONDS )); then |
| 172 | command rm -rf "$ZSH/log/update.lock" |
| 173 | fi |
| 174 | fi |
| 175 | |
| 176 | |
| 177 | if ! command mkdir "$ZSH/log/update.lock" 2>/dev/null; then |
| 178 | return |
| 179 | fi |
| 180 | |
| 181 | |
| 182 | |
| 183 | |
| 184 | |
| 185 | |
| 186 | |
| 187 | trap " |
| 188 | ret=\$? |
| 189 | unset update_mode |
| 190 | unset -f current_epoch is_update_available update_last_updated_file update_ohmyzsh handle_update 2>/dev/null |
| 191 | command rm -rf '$ZSH/log/update.lock' |
| 192 | return \$ret |
| 193 | " EXIT INT QUIT |
| 194 | |
| 195 | |
| 196 | if ! source "${ZSH_CACHE_DIR}/.zsh-update" 2>/dev/null || [[ -z "$LAST_EPOCH" ]]; then |
| 197 | update_last_updated_file |
| 198 | return |
| 199 | fi |
| 200 | |
| 201 | |
| 202 | zstyle -s ':omz:update' frequency epoch_target || epoch_target=${UPDATE_ZSH_DAYS:-13} |
| 203 | |
| 204 | if (( ( $(current_epoch) - $LAST_EPOCH ) < $epoch_target )); then |
| 205 | return |
| 206 | fi |
| 207 | |
| 208 | |
| 209 | if ! (builtin cd -q "$ZSH" && LANG= git rev-parse &>/dev/null); then |
| 210 | echo >&2 "[oh-my-zsh] Can't update: not a git repository." |
| 211 | return |
| 212 | fi |
| 213 | |
| 214 | |
| 215 | if ! is_update_available; then |
| 216 | update_last_updated_file |
| 217 | return |
| 218 | fi |
| 219 | |
| 220 | |
| 221 | if [[ "$update_mode" = reminder ]] || { [[ "$update_mode" != background-alpha ]] && has_typed_input }; then |
| 222 | printf '\r\e[0K' |
| 223 | echo "[oh-my-zsh] It's time to update! You can do that by running \`omz update\`" |
| 224 | return 0 |
| 225 | fi |
| 226 | |
| 227 | |
| 228 | if [[ "$update_mode" = (auto|background-alpha) ]]; then |
| 229 | update_ohmyzsh |
| 230 | return $? |
| 231 | fi |
| 232 | |
| 233 | |
| 234 | |
| 235 | echo -n "[oh-my-zsh] Would you like to update? [Y/n] " |
| 236 | read -r -k 1 option |
| 237 | [[ "$option" = $'\n' ]] || echo |
| 238 | case "$option" in |
| 239 | [yY$'\n']) update_ohmyzsh ;; |
| 240 | [nN]) update_last_updated_file ;& |
| 241 | *) echo "[oh-my-zsh] You can update manually by running \`omz update\`" ;; |
| 242 | esac |
| 243 | } |
| 244 | |
| 245 | unset update_mode |
| 246 | unset -f current_epoch is_update_available update_last_updated_file update_ohmyzsh handle_update |
| 247 | } |
| 248 | |
| 249 | case "$update_mode" in |
| 250 | background-alpha) |
| 251 | autoload -Uz add-zsh-hook |
| 252 | |
| 253 | _omz_bg_update() { |
| 254 | |
| 255 | (handle_update) &| |
| 256 | |
| 257 | |
| 258 | add-zsh-hook precmd _omz_bg_update_status |
| 259 | |
| 260 | |
| 261 | add-zsh-hook -d precmd _omz_bg_update |
| 262 | unset -f _omz_bg_update |
| 263 | } |
| 264 | |
| 265 | _omz_bg_update_status() { |
| 266 | { |
| 267 | local LAST_EPOCH EXIT_STATUS ERROR |
| 268 | if [[ ! -f "$ZSH_CACHE_DIR"/.zsh-update ]]; then |
| 269 | return 1 |
| 270 | fi |
| 271 | |
| 272 | |
| 273 | . "$ZSH_CACHE_DIR/.zsh-update" |
| 274 | if [[ -z "$EXIT_STATUS" || -z "$ERROR" ]]; then |
| 275 | return 1 |
| 276 | fi |
| 277 | |
| 278 | if [[ "$EXIT_STATUS" -eq 0 ]]; then |
| 279 | print -P "\n%F{green}[oh-my-zsh] Update successful.%f" |
| 280 | return 0 |
| 281 | elif [[ "$EXIT_STATUS" -ne 0 ]]; then |
| 282 | print -P "\n%F{red}[oh-my-zsh] There was an error updating:%f" |
| 283 | printf "\n${fg[yellow]}%s${reset_color}" "$ERROR" |
| 284 | return 0 |
| 285 | fi |
| 286 | } always { |
| 287 | if (( TRY_BLOCK_ERROR == 0 )); then |
| 288 | |
| 289 | update_last_updated_file |
| 290 | |
| 291 | |
| 292 | add-zsh-hook -d precmd _omz_bg_update_status |
| 293 | unset -f _omz_bg_update_status |
| 294 | fi |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | add-zsh-hook precmd _omz_bg_update |
| 299 | ;; |
| 300 | *) |
| 301 | handle_update ;; |
| 302 | esac |