# 画面設計書 20-check_for_upgrade.sh

## 概要

本ドキュメントは、Oh My Zshの更新確認スクリプト `check_for_upgrade.sh` の画面設計書です。

### 本画面の処理概要

`check_for_upgrade.sh` は、Oh My Zshの自動更新チェック機能を提供するスクリプトです。zshセッション起動時に自動的にsourceされ、設定された間隔で更新の有無を確認します。

**業務上の目的・背景**：ユーザーが手動で更新を確認する手間を省き、Oh My Zshを常に最新の状態に保つことが重要です。本スクリプトは、設定可能な間隔（デフォルト13日）で更新をチェックし、更新モードに応じて自動更新、プロンプト表示、リマインダー表示などを行います。これにより、ユーザーは新機能やセキュリティ修正を適時に受け取ることができます。

**画面へのアクセス方法**：zshセッション起動時に自動的に実行されます（oh-my-zsh.shからsource）。

**主要な操作・処理内容**：
1. 更新モードの取得（zstyle ':omz:update' mode）
2. 更新条件の確認（書き込み権限、git、TTY等）
3. 最終更新日からの経過日数を確認
4. GitHub APIで更新の有無を確認
5. 更新モードに応じた処理を実行
6. .zsh-updateファイルを更新

**画面遷移**：
- 遷移元: oh-my-zsh.shからのsource（zsh起動時）
- 遷移先: 更新実行時はupgrade.shを呼び出し

**権限による表示制御**：$ZSHディレクトリの書き込み権限がない場合、更新チェックはスキップされます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 80 | 自動更新チェック | 主機能 | 指定間隔（デフォルト13日）でGitHub APIを使用して更新を確認 |
| 81 | is_update_available | 補助機能 | ローカルとリモートのHEADを比較して更新があるか判定 |
| 82 | handle_update | 補助機能 | 更新モード（prompt/auto/reminder/background-alpha/disabled）に応じて更新処理を実行 |

## 画面種別

シェルスクリプト（バックグラウンド処理/対話型）

## URL/ルーティング

通常は自動的にsourceされます。直接実行は想定されていません。

```bash
# 自動実行（zsh起動時）
source $ZSH/tools/check_for_upgrade.sh

# 更新モード設定（.zshrcで設定）
zstyle ':omz:update' mode prompt  # デフォルト: 確認プロンプト
zstyle ':omz:update' mode auto    # 自動更新
zstyle ':omz:update' mode reminder # リマインダーのみ
zstyle ':omz:update' mode disabled # 無効化
zstyle ':omz:update' mode background-alpha # バックグラウンド更新（実験的）
```

## 入出力項目

### 入力項目（zstyle設定）

| 項目名 | 型 | 必須 | デフォルト | 説明 |
|--------|-----|------|----------|------|
| :omz:update mode | 文字列 | 任意 | prompt | 更新モード |
| :omz:update frequency | 数値 | 任意 | 13 | 更新チェック間隔（日数） |
| :omz:update verbose | 文字列 | 任意 | default | 詳細モード |

### 入力項目（レガシー環境変数）

| 項目名 | 型 | 必須 | デフォルト | 説明 |
|--------|-----|------|----------|------|
| DISABLE_UPDATE_PROMPT | bool | 任意 | - | trueでautoモード |
| DISABLE_AUTO_UPDATE | bool | 任意 | - | trueでdisabledモード |
| UPDATE_ZSH_DAYS | 数値 | 任意 | 13 | 更新間隔（日数） |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 確認プロンプト | テキスト | 更新確認（promptモード時） |
| リマインダー | テキスト | 更新案内（reminderモード時） |
| 更新結果 | テキスト | 更新処理の結果 |

## 表示項目

| 表示項目 | 表示条件 | 説明 |
|----------|----------|------|
| 確認プロンプト | promptモード・更新あり | "[oh-my-zsh] Would you like to update? [Y/n]" |
| リマインダー | reminderモード・更新あり | "[oh-my-zsh] It's time to update! You can do that by running `omz update`" |
| 更新結果 | background-alphaモード | 更新成功/失敗メッセージ |
| gitエラー | gitリポジトリでない場合 | "[oh-my-zsh] Can't update: not a git repository." |

## イベント仕様

### 1-更新モード取得

更新モードを設定から取得します。

- zstyle ':omz:update' modeから取得
- 未設定時はレガシー環境変数をチェック
  - DISABLE_UPDATE_PROMPT=trueならautoモード
  - DISABLE_AUTO_UPDATE=trueならdisabledモード
- デフォルトはpromptモード

### 2-更新条件確認

更新チェックを実行するかどうかを判定します。

以下のいずれかの場合、更新チェックをスキップ：
- update_mode = disabled
- $ZSHに書き込み権限がない
- $ZSHの所有者でない
- TTYでない（POWERLEVEL9K_INSTANT_PROMPT=off時）
- gitコマンドがない
- $ZSHがgitリポジトリでない

### 3-最終更新日確認

前回更新からの経過日数を確認します。

- $ZSH_CACHE_DIR/.zsh-updateファイルをsource
- LAST_EPOCH変数を取得
- current_epoch関数で現在のエポック日数を計算
- 経過日数がfrequency未満ならスキップ

### 4-更新有無確認

GitHub APIで更新の有無を確認します（is_update_available関数）。

- oh-my-zsh.remoteとoh-my-zsh.branchを取得
- リモートURLからGitHubリポジトリを判定
- ohmyzsh/ohmyzsh以外のフォークは常に更新ありと判定
- GitHub APIでリモートHEADを取得（curl/wget/fetch）
- ローカルHEADと比較
- merge-baseで実際に更新があるか確認

### 5-更新処理実行

更新モードに応じた処理を実行します（handle_update関数）。

- **promptモード**: 確認プロンプトを表示、Y/y/Enterで更新
- **autoモード**: 自動的にupdate_ohmyzshを実行
- **reminderモード**: リマインダーメッセージのみ表示
- **background-alphaモード**: バックグラウンドで更新、結果をprecmdで表示
- **disabledモード**: 何もしない

### 6-ロック管理

更新処理の排他制御を行います。

- $ZSH/log/update.lockディレクトリをmkdirで作成
- 1日以上経過したロックは自動削除
- 処理完了時またはシグナル受信時にロックを削除

### 7-.zsh-update更新

最終更新日を記録します。

- update_last_updated_file関数
- LAST_EPOCH、EXIT_STATUS、ERRORを記録
- $ZSH_CACHE_DIR/.zsh-updateに書き込み

## データベース更新仕様

本スクリプトはデータベースを使用しません。

### 操作別ファイルシステム影響一覧

| 操作 | 対象 | 操作種別 | 概要 |
|------|------|---------|------|
| .zsh-update読み込み | $ZSH_CACHE_DIR/.zsh-update | READ | 最終更新日を取得 |
| .zsh-update更新 | $ZSH_CACHE_DIR/.zsh-update | UPDATE | 最終更新日を記録 |
| ロック作成 | $ZSH/log/update.lock | CREATE | 排他制御用ディレクトリ |
| ロック削除 | $ZSH/log/update.lock | DELETE | 処理完了時に削除 |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|----------|
| プロンプト | "[oh-my-zsh] Would you like to update? [Y/n]" | promptモード・更新あり |
| 情報 | "[oh-my-zsh] It's time to update! You can do that by running `omz update`" | reminderモード・更新あり |
| 情報 | "[oh-my-zsh] You can update manually by running `omz update`" | promptモードで更新拒否時 |
| エラー | "[oh-my-zsh] Can't update: not a git repository." | gitリポジトリでない時 |
| 情報 | "[oh-my-zsh] Update successful." | background-alphaモード成功時 |
| エラー | "[oh-my-zsh] There was an error updating:" | background-alphaモード失敗時 |

## 例外処理

| 例外状態 | 処理内容 |
|----------|----------|
| disabledモード | 即座にreturn |
| 書き込み権限なし | 即座にreturn |
| 非TTY環境 | POWERLEVEL9K_INSTANT_PROMPT=off以外はreturn |
| gitなし | 即座にreturn |
| gitリポジトリでない | 即座にreturn |
| ロック取得失敗 | 即座にreturn（他のプロセスが更新中） |
| .zsh-update読み込み失敗 | ファイルを再作成 |
| API接続失敗 | 更新をスキップ |
| ユーザー入力あり | reminderモードに切り替え |

## 備考

- POWERLEVEL9K_INSTANT_PROMPTが有効な場合、verbose_modeは強制的にsilentになります
- background-alphaモードは実験的機能です
- GitHub API接続タイムアウトは2秒です
- 古いロック（1日以上経過）は自動的に削除されます
- ~/.zsh-updateは自動的に$ZSH_CACHE_DIR/.zsh-updateに移行されます

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、更新チェックで使用される主要な変数とファイルを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` 行6-20 | update_mode変数と設定取得 |
| 1-2 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` 行37-40 | current_epoch関数 |
| 1-3 | .zsh-update | `$ZSH_CACHE_DIR/.zsh-update` | LAST_EPOCH、EXIT_STATUS、ERROR変数 |

**読解のコツ**: zstyleによる設定取得と環境変数のフォールバックを理解してください。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` 行1-35 | スクリプト冒頭の条件チェック |

**主要処理フロー**:
- **行1-4**: .zsh-updateファイルの移行処理
- **行8-20**: update_modeの取得（zstyleまたはレガシー環境変数）
- **行22-35**: 更新条件の確認（disabled、権限、TTY、git等）

#### Step 3: 更新確認関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` 行42-94 | is_update_available関数 |

**is_update_availableの処理フロー**:
- **行43-48**: リモートとブランチの取得
- **行51-58**: リモートURLからGitHubリポジトリを判定
- **行61-62**: ohmyzsh/ohmyzsh以外は常に更新ありと判定
- **行65-66**: ローカルHEADの取得
- **行70-81**: GitHub APIでリモートHEAD取得（curl/wget/fetch）
- **行84**: ローカルとリモートの比較
- **行88-93**: merge-baseで実際の更新を確認

#### Step 4: 更新処理関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` 行111-134 | update_ohmyzsh関数 |
| 4-2 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` 行161-247 | handle_update関数 |

**update_ohmyzshの処理フロー**:
- **行113**: verbose_mode取得
- **行116-118**: p10k instant prompt時はsilentモード
- **行120-124**: upgrade.sh実行（通常モード）
- **行126-133**: upgrade.sh実行（background-alphaモード）

**handle_updateの処理フロー**:
- **行167-174**: 古いロックの削除
- **行177-179**: ロック取得
- **行196-206**: 更新間隔チェック
- **行214-218**: 更新有無チェック
- **行220-225**: reminderモードまたはユーザー入力ありの処理
- **行227-231**: autoモードの処理
- **行233-242**: promptモードの処理

#### Step 5: バックグラウンド更新を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` 行249-302 | background-alphaモードの処理 |

**background-alphaの処理フロー**:
- **行251-263**: _omz_bg_update関数（precmdフックでバックグラウンド実行）
- **行265-296**: _omz_bg_update_status関数（結果表示）
- **行298**: add-zsh-hookでprecmdに登録

### プログラム呼び出し階層図

```
source check_for_upgrade.sh (zsh起動時)
    │
    ├─ 条件チェック [tools/check_for_upgrade.sh:22-35]
    │      ├─ update_mode確認
    │      ├─ 書き込み権限確認
    │      ├─ git確認
    │      └─ gitリポジトリ確認
    │
    ├─ handle_update [tools/check_for_upgrade.sh:161-247]
    │      │
    │      ├─ ロック管理
    │      │
    │      ├─ .zsh-update読み込み
    │      │
    │      ├─ 経過日数チェック
    │      │
    │      ├─ is_update_available [tools/check_for_upgrade.sh:42-94]
    │      │      ├─ git config読み込み
    │      │      ├─ GitHub API呼び出し (curl/wget/fetch)
    │      │      └─ HEAD比較
    │      │
    │      └─ モード別処理
    │             ├─ prompt: 確認 → update_ohmyzsh
    │             ├─ auto: update_ohmyzsh
    │             ├─ reminder: メッセージ表示
    │             └─ disabled: スキップ
    │
    └─ update_ohmyzsh [tools/check_for_upgrade.sh:111-134]
           └─ upgrade.sh実行
```

### データフロー図

```
[入力]                    [処理]                           [出力]

zstyle設定 ─────────▶ update_mode取得
                           │
                           ▼
                     条件チェック ─────────────────────▶ 条件不一致時return
                           │
                           ▼
                     .zsh-update読み込み ──────────────▶ LAST_EPOCH取得
                           │
                           ▼
                     経過日数チェック ─────────────────▶ 未到達時return
                           │
                           ▼
                     is_update_available ──────────────▶ 更新なし時return
                           │
                           ▼
                     モード別処理
                           │
               ┌───────────┼───────────┐
               ▼           ▼           ▼
           prompt       auto      reminder
               │           │           │
               ▼           │           ▼
           確認プロンプト  │       メッセージ表示
               │           │
               └─────┬─────┘
                     ▼
               update_ohmyzsh
                     │
                     ▼
               upgrade.sh実行 ──────────────────────▶ 更新結果
                     │
                     ▼
               .zsh-update更新 ─────────────────────▶ LAST_EPOCH保存
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| check_for_upgrade.sh | `tools/check_for_upgrade.sh` | ソース | 自動更新チェック機能 |
| upgrade.sh | `tools/upgrade.sh` | ソース | 実際の更新処理 |
| oh-my-zsh.sh | `oh-my-zsh.sh` | ソース | check_for_upgrade.shをsource |
| .zsh-update | `$ZSH_CACHE_DIR/.zsh-update` | 設定 | 最終更新日、更新結果 |
| update.lock | `$ZSH/log/update.lock` | ロック | 排他制御用ディレクトリ |
