# 機能設計書 82-handle_update

## 概要

本ドキュメントは、Oh My Zshの自動更新機能における更新処理の制御を行う`handle_update`関数の機能設計について記述する。

### 本機能の処理概要

更新モード（prompt/auto/reminder/background-alpha/disabled）に応じて、Oh My Zshの更新処理を適切に実行する機能である。ユーザーの設定に基づき、確認プロンプト表示、自動更新、リマインダー表示、バックグラウンド更新のいずれかの動作を行う。

**業務上の目的・背景**：Oh My Zshユーザーには様々な利用スタイルがあり、自動更新に対する要望も多様である。「毎回確認したい」「自動で更新してほしい」「通知だけでよい」「バックグラウンドで処理してほしい」といった異なるニーズに対応するため、複数の更新モードを提供し、それぞれに適した更新フローを実装している。

**機能の利用シーン**：zshシェルの起動時に更新間隔（デフォルト13日）を超過している場合、本関数が呼び出される。更新モードに応じて、ユーザーへの確認、自動更新実行、リマインダー表示のいずれかが行われる。

**主要な処理内容**：
1. ロックディレクトリの確認・作成（同時実行防止）
2. 最終更新チェック日時の確認
3. 更新間隔の判定（zstyleまたはUPDATE_ZSH_DAYS変数）
4. 更新可否のチェック（is_update_available関数呼び出し）
5. 更新モードに応じた処理分岐
6. 更新実行またはリマインダー表示
7. ロックディレクトリのクリーンアップ

**関連システム・外部連携**：tools/upgrade.shスクリプトを呼び出して実際の更新処理を実行する。

**権限による制御**：$ZSHディレクトリへの書き込み権限と所有権が必要。権限がない場合は更新処理がスキップされる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | check_for_upgrade.sh | 主画面 | 更新モードに応じて更新処理を実行 |

## 機能種別

制御処理 / バッチ処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | 引数は受け取らない | - |

### 入力データソース

- `$update_mode`変数：更新モード（prompt/auto/reminder/background-alpha/disabled）
- `$ZSH_CACHE_DIR/.zsh-update`：最終更新チェック日時
- zstyle `:omz:update` frequency：更新間隔（日数）
- `$UPDATE_ZSH_DAYS`環境変数：更新間隔（日数、レガシー設定）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 画面出力 | 文字列 | 更新確認プロンプト、リマインダーメッセージ |
| .zsh-update | ファイル | 最終更新チェック日時の更新 |

### 出力先

- 標準出力：ユーザーへのメッセージ
- `$ZSH_CACHE_DIR/.zsh-update`：更新状態ファイル

## 処理フロー

### 処理シーケンス

```
1. ロックディレクトリの管理
   └─ 古いロック（24時間以上）の削除、新規ロック作成
2. トラップハンドラの設定
   └─ EXIT/INT/QUITシグナルでロック削除
3. 最終更新日時の確認
   └─ .zsh-updateファイルの読み込み
4. 更新間隔のチェック
   └─ 指定日数未経過の場合は終了
5. gitリポジトリの確認
   └─ $ZSHがgitリポジトリでない場合はエラー
6. 更新可否の判定
   └─ is_update_available()を呼び出し
7. 更新モード別処理
   ├─ reminder: リマインダーメッセージ表示
   ├─ auto/background-alpha: 自動更新実行
   └─ prompt: 確認プロンプト表示後に実行
8. クリーンアップ
   └─ ロックディレクトリ削除、関数のunset
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{ロック取得可能?}
    B -->|No| Z[終了]
    B -->|Yes| C[トラップ設定]
    C --> D{.zsh-update読み込み成功?}
    D -->|No| E[更新日時初期化]
    E --> Z
    D -->|Yes| F{更新間隔経過?}
    F -->|No| Z
    F -->|Yes| G{gitリポジトリ?}
    G -->|No| H[エラーメッセージ]
    H --> Z
    G -->|Yes| I{更新利用可能?}
    I -->|No| J[更新日時更新]
    J --> Z
    I -->|Yes| K{更新モード}
    K -->|reminder| L[リマインダー表示]
    K -->|auto/background| M[自動更新実行]
    K -->|prompt| N[確認プロンプト]
    N --> O{ユーザー選択}
    O -->|Y/Enter| M
    O -->|N/その他| P[手動更新案内]
    L --> Z
    M --> Z
    P --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-82-001 | ロックタイムアウト | 24時間以上経過したロックは自動削除 | ロックディレクトリのmtimeが24時間以上前 |
| BR-82-002 | デフォルト更新間隔 | 更新間隔未設定時は13日 | zstyleおよびUPDATE_ZSH_DAYS未設定時 |
| BR-82-003 | 入力検知リマインダー | ユーザーがタイプ中の場合はリマインダーモード | has_typed_input()がtrueを返す場合 |
| BR-82-004 | 自動モード確認なし | auto/background-alphaモードは確認なしで更新 | update_modeがautoまたはbackground-alpha |
| BR-82-005 | プロンプトモードデフォルト | Y/Enter入力で更新実行 | update_modeがpromptで入力がy/Y/Enter |

### 計算ロジック

更新間隔判定：
- `(current_epoch - LAST_EPOCH) < epoch_target` の場合、更新チェックをスキップ
- current_epochは`EPOCHSECONDS / 60 / 60 / 24`（日数）で計算

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | gitリポジトリエラー | $ZSHがgitリポジトリでない | エラーメッセージを表示して終了 |
| - | ロック取得失敗 | 他プロセスが更新中 | 処理をスキップ |
| - | 更新スクリプトエラー | upgrade.shが失敗 | エラー情報を.zsh-updateに記録 |

### リトライ仕様

リトライは行わない。次回シェル起動時に再度更新チェックが実行される。

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

ファイルシステムレベルでのロック機構を使用：
- `$ZSH/log/update.lock`ディレクトリの作成でロック取得
- 処理完了またはシグナル受信時にロック解放

## パフォーマンス要件

- シェル起動への影響を最小化するため、更新間隔内はすぐに終了
- background-alphaモードではサブシェルで非同期実行

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

- ロックディレクトリによる競合状態の防止
- シグナルハンドラによる確実なクリーンアップ
- 更新スクリプトの実行はユーザー権限で行われる

## 備考

- background-alphaモードは実験的機能
- Powerlevel9kのインスタントプロンプト有効時は自動的にsilentモードになる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | 1-35行目: 更新モードの設定と前提条件チェック |

**読解のコツ**: zstyleコマンドはzshの設定管理機能。`-s`オプションで値を変数に格納する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | 161行目: handle_update関数の定義開始 |

**主要処理フロー**:
1. **167-174行目**: ロックディレクトリの管理（24時間タイムアウト）
2. **177-179行目**: 新規ロック取得の試行
3. **187-193行目**: トラップハンドラの設定
4. **196-199行目**: .zsh-updateファイルの読み込み
5. **202-206行目**: 更新間隔のチェック
6. **209-212行目**: gitリポジトリの確認
7. **215-218行目**: 更新可否判定（is_update_available呼び出し）
8. **221-225行目**: reminderモードまたは入力検知時の処理
9. **228-231行目**: auto/background-alphaモードの自動更新
10. **235-242行目**: promptモードの確認プロンプト処理

#### Step 3: 補助関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | 37-40行目: current_epoch関数 |
| 3-2 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | 96-109行目: update_last_updated_file関数 |
| 3-3 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | 111-134行目: update_ohmyzsh関数 |
| 3-4 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | 136-159行目: has_typed_input関数 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | check_for_upgrade.sh | `tools/check_for_upgrade.sh` | 249-302行目: background-alphaモードの実装 |

**主要処理フロー**:
- **253-263行目**: _omz_bg_update関数（サブシェルで更新実行）
- **265-296行目**: _omz_bg_update_status関数（結果の表示）
- **298行目**: precmdフックへの登録

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

```
check_for_upgrade.sh
    │
    ├─ handle_update()  ← 本機能
    │      │
    │      ├─ current_epoch()
    │      ├─ is_update_available()
    │      ├─ has_typed_input()
    │      ├─ update_ohmyzsh()
    │      │      └─ tools/upgrade.sh
    │      └─ update_last_updated_file()
    │
    └─ (background-alphaモード)
           ├─ _omz_bg_update()
           │      └─ handle_update() (サブシェル)
           └─ _omz_bg_update_status()
```

### データフロー図

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

$update_mode ────────┐
                     │
.zsh-update ─────────┼─▶ handle_update() ───────────▶ 画面出力
                     │         │                      (メッセージ)
zstyle frequency ────┤         │
                     │         ├─▶ update.lock/      .zsh-update
$UPDATE_ZSH_DAYS ────┘         │   (ロック)          (更新)
                               │
                               └─▶ upgrade.sh
                                   (更新実行)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| check_for_upgrade.sh | `tools/check_for_upgrade.sh` | ソース | 更新チェック・更新処理の統合スクリプト |
| upgrade.sh | `tools/upgrade.sh` | ソース | 実際のgit pull処理を実行 |
| .zsh-update | `$ZSH_CACHE_DIR/.zsh-update` | キャッシュ | 最終更新日時・結果を保存 |
| update.lock | `$ZSH/log/update.lock` | ロック | 同時実行防止用ディレクトリ |
