# 機能設計書 80-自動更新チェック

## 概要

本ドキュメントは、Oh My Zshの自動更新チェックスクリプト（tools/check_for_upgrade.sh）の機能設計について記述する。

### 本機能の処理概要

`check_for_upgrade.sh`は、Oh My Zshの更新が利用可能かどうかを定期的にチェックし、設定されたモードに応じて更新処理を実行するスクリプトである。シェル起動時に読み込まれ、前回のチェックからの経過日数に基づいて更新を確認する。GitHub APIを使用してリモートのHEADコミットと比較し、更新の有無を判定する。

**業務上の目的・背景**：Oh My Zshは継続的に更新されるプロジェクトであり、セキュリティ修正や新機能が随時追加される。手動での更新確認は忘れがちなため、自動的に更新を確認し、ユーザーに通知または自動更新する仕組みが必要とされる。

**機能の利用シーン**：
- 新しいターミナルセッションを開始した時（シェル起動時）
- 指定された更新間隔（デフォルト13日）が経過した時
- zstyle ':omz:update' modeで設定されたモードに応じた動作

**主要な処理内容**：
1. .zsh-updateファイルの$ZSH_CACHE_DIRへの移行（レガシー対応）
2. 更新モードの取得（prompt/auto/reminder/background-alpha/disabled）
3. 更新実行条件の確認（権限、tty、git利用可能性）
4. 前回更新からの経過日数の確認
5. GitHub APIを使用した更新有無の確認（is_update_available）
6. モードに応じた更新処理の実行（handle_update）
7. ロックディレクトリによる排他制御

**関連システム・外部連携**：GitHub API（更新確認）、curl/wget/fetch（HTTP通信）、upgrade.sh（実際の更新処理）。

**権限による制御**：$ZSHディレクトリへの書き込み権限と所有権が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | check_for_upgrade.sh | 主機能 | 指定間隔でGitHub APIを使用して更新を確認 |

## 機能種別

自動更新チェック・スケジューリング

## 入力仕様

### 入力パラメータ

スクリプトは引数を取らない。以下の設定で動作を制御する。

### zstyle設定

| 設定 | 値 | 説明 |
|------|-----|------|
| :omz:update mode | prompt | ユーザーに確認してから更新（デフォルト） |
| :omz:update mode | auto | 自動的に更新 |
| :omz:update mode | reminder | 更新可能であることを通知 |
| :omz:update mode | background-alpha | バックグラウンドで更新（実験的） |
| :omz:update mode | disabled | 自動更新を無効化 |
| :omz:update frequency | 数値 | チェック間隔（日数、デフォルト13） |
| :omz:update verbose | default/minimal/silent | 更新時の詳細度 |

### 環境変数

| 変数名 | 説明 |
|--------|------|
| DISABLE_UPDATE_PROMPT | true でautoモード（レガシー） |
| DISABLE_AUTO_UPDATE | true でdisabled（レガシー） |
| UPDATE_ZSH_DAYS | チェック間隔（レガシー、デフォルト13） |

### 入力データソース

- $ZSH_CACHE_DIR/.zsh-update（前回チェック日時）
- GitHub API（リモートHEAD取得）
- ローカルGitリポジトリ（ローカルHEAD）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| .zsh-update | file | LAST_EPOCH、EXIT_STATUS、ERRORを含む |
| 更新通知 | stdout | 更新プロンプトまたはリマインダーメッセージ |

### 出力先

- $ZSH_CACHE_DIR/.zsh-update
- 標準出力（メッセージ）

## 処理フロー

### 処理シーケンス

```
1. レガシーファイル移行
   └─ ~/.zsh-update → $ZSH_CACHE_DIR/.zsh-update
2. 更新モード取得
   └─ zstyle ':omz:update' mode または レガシー変数
3. 更新条件確認
   └─ disabled、権限なし、非tty、git不可、非gitリポジトリ → 中止
4. 経過日数確認
   └─ LAST_EPOCH + frequency < current_epoch → 続行
5. 更新有無確認（is_update_available）
   └─ GitHub APIでリモートHEAD取得、ローカルと比較
6. 更新処理（handle_update）
   └─ ロックディレクトリ作成
   └─ モードに応じた処理
      - reminder: リマインダー表示
      - auto/background-alpha: 自動更新
      - prompt: 確認ダイアログ
7. クリーンアップ
   └─ ロックディレクトリ削除
   └─ 関数定義削除
```

### フローチャート

```mermaid
flowchart TD
    A[check_for_upgrade.sh読み込み] --> B[レガシーファイル移行]
    B --> C[更新モード取得]
    C --> D{mode=disabled?}
    D -->|Yes| E[return]
    D -->|No| F{権限/tty/git確認}
    F -->|NG| E
    F -->|OK| G[経過日数確認]
    G --> H{frequency日経過?}
    H -->|No| E
    H -->|Yes| I[is_update_available]
    I --> J{更新あり?}
    J -->|No| K[LAST_EPOCH更新]
    K --> E
    J -->|Yes| L[handle_update]
    L --> M{mode?}
    M -->|reminder| N[リマインダー表示]
    M -->|auto/bg| O[自動更新]
    M -->|prompt| P[確認ダイアログ]
    N --> E
    O --> E
    P --> Q{Y/Enter?}
    Q -->|Yes| R[更新実行]
    Q -->|No| S[LAST_EPOCH更新]
    R --> E
    S --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-80-01 | デフォルト間隔 | 13日ごとに更新確認 | frequency未設定時 |
| BR-80-02 | 権限チェック | $ZSHへの書き込み権限と所有権が必要 | 常時 |
| BR-80-03 | TTY必須 | 非tty環境では確認不可（P10K例外あり） | prompt/reminderモード時 |
| BR-80-04 | ロック制御 | 24時間以上経過したロックは削除 | ロック存在時 |
| BR-80-05 | GitHub以外 | GitHub以外のリモートは常に更新ありと判定 | 非GitHubリモート時 |
| BR-80-06 | 公式リポジトリ以外 | ohmyzsh/ohmyzsh以外は常に更新ありと判定 | フォーク使用時 |

### 計算ロジック

```
# 経過日数の計算
current_epoch = EPOCHSECONDS / 60 / 60 / 24
elapsed_days = current_epoch - LAST_EPOCH
need_check = elapsed_days >= frequency
```

## データベース操作仕様

### 操作別データベース影響一覧

データベース操作なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | 権限エラー | $ZSHへの書き込み権限がない | 権限を修正 |
| N/A | Git不可 | gitコマンドが利用不可 | gitをインストール |
| N/A | 非リポジトリ | $ZSHがgitリポジトリでない | 再インストール |
| N/A | ネットワークエラー | GitHub APIアクセス失敗 | 更新をスキップ |

### リトライ仕様

- ネットワークエラー時は次回チェックまでスキップ
- ロック取得失敗時はreturn（他プロセスが更新中）

## トランザクション仕様

- ロックディレクトリ（$ZSH/log/update.lock）で排他制御
- trapでクリーンアップを確実に実行
- SIGINT時も適切に終了

## パフォーマンス要件

- GitHub APIタイムアウト: 2秒
- シェル起動への影響を最小限にするため、background-alphaモードではサブシェルで実行

## セキュリティ考慮事項

- HTTPSでGitHub APIにアクセス
- GitHub API応答はSHA形式を要求（application/vnd.github.v3.sha）

## 備考

- Powerlevel10k instant promptとの互換性のためverbose=silentを強制する場合がある
- background-alphaモードは実験的機能
- has_typed_input()でユーザーが入力中かどうかを検出し、入力中はreminderモードにフォールバック

---

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

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

### 推奨読解順序

#### Step 1: 初期化と更新モード設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | 初期化とモード設定（1-35行目） |

**読解のコツ**: `zstyle -s`はzstyle設定を変数に取得。`${VAR:-default}`は変数が未設定時にデフォルト値を使用。

**主要処理フロー**:
- **1-4行目**: レガシーファイル（~/.zsh-update）の移行
- **6-20行目**: 更新モードの取得（zstyle優先、レガシー変数フォールバック）
- **22-35行目**: 更新キャンセル条件の確認

#### Step 2: 更新確認ロジックを理解する

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

**主要処理フロー**:
- **43-44行目**: branch/remote設定の取得
- **46-58行目**: リモートURLからリポジトリ名を抽出
- **61行目**: 非公式リポジトリは更新ありと判定
- **65-66行目**: ローカルHEADの取得
- **71-81行目**: curl/wget/fetchでリモートHEADを取得
- **84行目**: ローカルとリモートの比較
- **88-93行目**: merge-baseで関係性を確認

#### Step 3: 更新処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | handle_update関数（161-247行目） |

**主要処理フロー**:
- **167-174行目**: 古いロックディレクトリの削除（24時間以上）
- **177-179行目**: ロックディレクトリの作成（排他制御）
- **187-193行目**: trapでクリーンアップを設定
- **195-199行目**: LAST_EPOCH読み込みと初期化
- **202-206行目**: frequency日数経過確認
- **214-218行目**: 更新がない場合はLAST_EPOCH更新
- **220-225行目**: reminderモードまたはユーザー入力中
- **227-231行目**: autoモードでの自動更新
- **233-242行目**: promptモードでの確認ダイアログ

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | background-alpha処理（249-302行目） |

**主要処理フロー**:
- **251行目**: add-zsh-hookをautoload
- **253-263行目**: _omz_bg_update関数（precmdフックで実行）
- **265-296行目**: _omz_bg_update_status関数（結果表示）
- **298行目**: precmdフックに登録

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

```
check_for_upgrade.sh (tools/check_for_upgrade.sh)
    │
    ├─ zstyle -s ':omz:update' mode
    │
    ├─ current_epoch()
    │      └─ zmodload zsh/datetime; EPOCHSECONDS計算
    │
    ├─ is_update_available()
    │      ├─ git config --local oh-my-zsh.branch/remote
    │      ├─ git rev-parse $branch
    │      └─ curl/wget/fetch (GitHub API)
    │
    ├─ handle_update()
    │      ├─ mkdir "$ZSH/log/update.lock"
    │      ├─ source "$ZSH_CACHE_DIR/.zsh-update"
    │      ├─ is_update_available()
    │      └─ update_ohmyzsh()
    │             └─ zsh -f "$ZSH/tools/upgrade.sh"
    │
    └─ [background-alpha]
           ├─ add-zsh-hook precmd _omz_bg_update
           └─ add-zsh-hook precmd _omz_bg_update_status
```

### データフロー図

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

zstyle設定 ─────────────▶ 更新モード決定
                                 │
$ZSH_CACHE_DIR/.zsh-update ─────▶│
(LAST_EPOCH)                     │
                                 ▼
                           経過日数確認
                                 │
                                 ▼
GitHub API ─────────────▶ is_update_available ─────▶ 更新有無判定
(リモートHEAD)                   │
                                 │
ローカルHEAD ───────────────────┘
                                 │
                                 ▼
                           handle_update
                                 │
                                 ├──[prompt]──▶ 確認ダイアログ
                                 │
                                 ├──[auto]───▶ upgrade.sh実行
                                 │
                                 └──[reminder]──▶ メッセージ表示
                                 │
                                 ▼
                           .zsh-update更新 ─────▶ $ZSH_CACHE_DIR/.zsh-update
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| check_for_upgrade.sh | `tools/check_for_upgrade.sh` | ソース | 自動更新チェックスクリプト |
| upgrade.sh | `tools/upgrade.sh` | ソース | 実際の更新処理 |
| .zsh-update | `$ZSH_CACHE_DIR/.zsh-update` | データ | 前回チェック日時、更新結果 |
| oh-my-zsh.sh | `oh-my-zsh.sh` | ソース | check_for_upgrade.shを読み込み |
