# 機能設計書 79-upgrade.sh

## 概要

本ドキュメントは、Oh My Zshのアップグレードスクリプト（tools/upgrade.sh）の機能設計について記述する。

### 本機能の処理概要

`upgrade.sh`は、Oh My Zshを最新版に更新するためのZshスクリプトである。`git pull --rebase`を使用してリモートリポジトリから最新のコードを取得し、更新の成否に応じて適切なメッセージを表示する。古いリモートURL（robbyrussell/oh-my-zsh）の自動更新、Git設定の最適化、チェンジログ表示などの機能も持つ。

**業務上の目的・背景**：Oh My Zshは継続的に新機能追加やバグ修正が行われるプロジェクトであり、ユーザーは定期的に更新を行う必要がある。本スクリプトは、安全かつ簡単にOh My Zshを最新版に更新する手段を提供する。

**機能の利用シーン**：
- `omz update`コマンドの実行時
- 自動更新チェック（check_for_upgrade.sh）からの呼び出し時
- 手動でupgrade.shを実行した場合

**主要な処理内容**：
1. Zsh以外のシェルで実行された場合はZshで再実行
2. 古いリモートURL（robbyrussell）を新しいURL（ohmyzsh）に更新
3. Git設定の最適化（eol、autocrlf、fsck、autoStash）
4. リポジトリ設定（remote、branch）の取得
5. 現在のブランチとコミットを保存
6. git pull --rebaseで更新を実行
7. 更新結果に応じてメッセージを表示
8. 更新成功時はチェンジログを表示（対話モード時）
9. 元のブランチに戻る
10. 一時的なGit設定を元に戻す

**関連システム・外部連携**：Git（バージョン管理）、GitHub（リモートリポジトリ）、changelog.sh（チェンジログ表示）。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | omz update | 関連 | omz updateコマンドからの呼び出し |
| 19 | upgrade.sh | 主機能 | OMZリポジトリをgit pull --rebaseで更新 |

## 機能種別

アップグレード・更新処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -v | option | No | 詳細度（default/minimal/silent） | default, minimal, silentのみ有効 |
| -i | flag | No | 対話モード（チェンジログ表示有効） | - |

### 環境変数

| 変数名 | デフォルト | 説明 |
|--------|-----------|------|
| $ZSH | スクリプトの親ディレクトリ | Oh My Zshインストールディレクトリ |

### 入力データソース

- Git設定（oh-my-zsh.remote、oh-my-zsh.branch）
- GitHubリモートリポジトリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 更新されたリポジトリ | directory | 最新のOh My Zshコード |
| oh-my-zsh.lastVersion | git config | 更新前のコミットSHA |
| 成功/失敗メッセージ | stdout | 更新結果のメッセージ |

### 出力先

- $ZSH（Oh My Zshディレクトリ）
- 標準出力（メッセージ）

## 処理フロー

### 処理シーケンス

```
1. シェル確認
   └─ Zsh以外ならexec zshで再実行
2. ソーシング防止
   └─ ZSH_EVAL_CONTEXTで確認
3. $ZSH設定
   └─ 未定義ならスクリプトパスから推定
4. オプション解析
   └─ getoptsで-v/-iを解析
5. カラー設定
   └─ TTY判定とTruecolor/Hyperlinks検出
6. リモートURL更新
   └─ robbyrussell→ohmyzshに変更
7. Git設定最適化
   └─ eol、autocrlf、fsck、autoStash
8. 現在状態保存
   └─ remote、branch、HEAD、last_commit
9. 更新ブランチにチェックアウト
10. git pull --rebase
    └─ 成功: 更新メッセージ、チェンジログ
    └─ 失敗: エラーメッセージ
11. 元のブランチに戻る
12. Git設定を復元
    └─ rebase.autoStash
13. 終了コードを返す
```

### フローチャート

```mermaid
flowchart TD
    A[upgrade.sh開始] --> B{Zshで実行?}
    B -->|No| C[exec zsh $0]
    B -->|Yes| D[オプション解析]
    D --> E[カラー設定]
    E --> F[リモートURL更新]
    F --> G[Git設定最適化]
    G --> H[現在状態保存]
    H --> I[更新ブランチにチェックアウト]
    I --> J["git pull --rebase"]
    J --> K{成功?}
    K -->|Yes| L{更新あり?}
    L -->|Yes| M[更新メッセージ]
    L -->|No| N[最新版メッセージ]
    M --> O{対話モード?}
    O -->|Yes| P[チェンジログ表示]
    O -->|No| Q[元のブランチに戻る]
    P --> Q
    N --> Q
    K -->|No| R[エラーメッセージ]
    R --> Q
    Q --> S[Git設定復元]
    S --> T[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-79-01 | Zsh必須 | Zsh以外のシェルではZshで再実行 | 常時 |
| BR-79-02 | ソーシング禁止 | ファイルとしてソースされた場合はエラー | 常時 |
| BR-79-03 | 旧URL更新 | robbyrussellのURLを自動的にohmyzshに変更 | 旧URL検出時 |
| BR-79-04 | autoStash | rebase.autoStashを一時的にtrueに設定 | 更新実行時 |
| BR-79-05 | 浅いクローン対応 | --depth=1でもfetchできるよう設定 | 常時 |
| BR-79-06 | 詳細度制御 | verbose_modeに応じてメッセージ量を調整 | 常時 |

### 計算ロジック

特になし

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

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

データベース操作なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | ソーシングエラー | ファイルとしてソースされた | スクリプトとして実行 |
| 1 | checkoutエラー | 更新ブランチへのチェックアウト失敗 | gitステータスを確認 |
| non-zero | pullエラー | git pullが失敗 | ネットワーク確認、後で再実行 |

### リトライ仕様

"Try again later?"のメッセージを表示

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

- 更新実行前に現在のブランチとコミットを保存
- 失敗時も元のブランチに戻る
- rebase.autoStashを使用して未コミットの変更を保護

## パフォーマンス要件

ネットワーク速度に依存（通常数秒〜数十秒）

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

- HTTPSでGitHubから取得
- 古いgitプロトコル（port 9418）を自動的にHTTPSに変換

## 備考

- `-v silent`はPowerlevel10k instant promptとの互換性のため
- `oh-my-zsh.lastVersion`はチェンジログ表示用に保存
- TruecolorとHyperlinksのサポートを検出してリッチな出力を提供

---

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

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

### 推奨読解順序

#### Step 1: スクリプトの初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | upgrade.sh | `tools/upgrade.sh` | 初期化処理（1-38行目） |

**読解のコツ**: `#!/usr/bin/env zsh`でZshスクリプト。`set +u`でnounsetを無効化。`exec zsh "$0" "$@"`で他シェルからの実行をZshに転送。

**主要処理フロー**:
- **2行目**: `set +u` - 未定義変数のエラーを無効化
- **4行目**: `local ret=0` - 終了コード初期化
- **7-9行目**: Zsh以外のシェルで実行された場合の再実行
- **12-14行目**: ソーシング防止チェック
- **17-19行目**: $ZSH未定義時のデフォルト設定
- **21行目**: $ZSHディレクトリに移動
- **26-38行目**: オプション解析（-v/-i）

#### Step 2: リモートURL更新処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | upgrade.sh | `tools/upgrade.sh` | リモートURL更新（195-214行目） |

**主要処理フロー**:
- **195行目**: `git remote -v | while read remote url extra` - リモート一覧を取得
- **196-207行目**: 古いURL（robbyrussell）を検出してohmyzshに更新
- **212-213行目**: `git config --local oh-my-zsh.remote`を設定

#### Step 3: Git設定最適化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | upgrade.sh | `tools/upgrade.sh` | Git設定（216-226行目） |

**主要処理フロー**:
- **218-219行目**: `core.eol lf`、`core.autocrlf false` - 改行設定
- **220-223行目**: `fsck.zeroPaddedFilemode ignore` - fsckエラー回避
- **225行目**: 現在のautoStash設定を保存
- **226行目**: `rebase.autoStash true` - 一時的に有効化

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | upgrade.sh | `tools/upgrade.sh` | 更新実行（228-283行目） |

**主要処理フロー**:
- **231-232行目**: remote/branch取得
- **235行目**: 現在のHEADを保存
- **237行目**: 更新ブランチにチェックアウト
- **239行目**: 更新前のコミットを保存
- **245行目**: `git pull --quiet --rebase $remote $branch`
- **247-263行目**: 成功時の処理（チェンジログ表示含む）
- **280-283行目**: 失敗時のエラー処理

#### Step 5: 後処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | upgrade.sh | `tools/upgrade.sh` | 後処理（285-295行目） |

**主要処理フロー**:
- **286行目**: 元のブランチに戻る
- **289-292行目**: autoStash設定を復元
- **295行目**: 終了コードを返す

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

```
upgrade.sh (tools/upgrade.sh)
    │
    ├─ [Zsh以外] exec zsh "$0" "$@"
    │
    ├─ getopts "v:i" (オプション解析)
    │
    ├─ is_tty() / supports_truecolor() / supports_hyperlinks()
    │
    ├─ git remote -v (リモートURL確認)
    │      └─ git remote set-url (必要時)
    │
    ├─ git config (複数回)
    │      ├─ core.eol lf
    │      ├─ core.autocrlf false
    │      ├─ fsck.zeroPaddedFilemode ignore
    │      └─ rebase.autoStash true
    │
    ├─ git symbolic-ref / git rev-parse (現在状態保存)
    │
    ├─ git checkout -q "$branch"
    │
    ├─ git pull --quiet --rebase $remote $branch
    │
    ├─ [成功時] changelog.sh HEAD "$last_commit"
    │
    ├─ git checkout -q "$last_head"
    │
    └─ git config --unset / rebase.autoStash (復元)
```

### データフロー図

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

-v オプション ─────────────▶ verbose_mode設定
-i オプション ─────────────▶ interactive設定
                                 │
oh-my-zsh.remote ─────────────▶│
oh-my-zsh.branch ─────────────▶│
                                 │
                                 ▼
GitHubリポジトリ ─────────▶ git pull --rebase ────▶ 更新された$ZSH/
                                 │
                                 ├──────────────────▶ oh-my-zsh.lastVersion
                                 │                    (git config)
                                 │
                                 ▼
                           [成功時] changelog.sh ──▶ チェンジログ表示
                                 │
                                 ▼
                           成功/失敗メッセージ ──▶ 標準出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| upgrade.sh | `tools/upgrade.sh` | ソース | メインアップグレードスクリプト |
| changelog.sh | `tools/changelog.sh` | ソース | チェンジログ表示 |
| check_for_upgrade.sh | `tools/check_for_upgrade.sh` | ソース | 自動更新チェック（upgrade.shを呼び出し） |
| lib/cli.zsh | `lib/cli.zsh` | ソース | omz updateコマンド（upgrade.shを呼び出し） |
