# 画面設計書 23-require_tool.sh

## 概要

本ドキュメントは、Oh My Zshのツール要件確認スクリプト `require_tool.sh` の設計仕様を定義する。このスクリプトは指定されたツール（プログラム）が必要なバージョン以上でインストールされているかを確認するユーティリティである。

### 本画面の処理概要

本スクリプトは、指定されたツールのバージョンが最小要件を満たしているかを確認し、結果を終了コードで返すユーティリティスクリプトである。

**業務上の目的・背景**：Oh My Zshやその関連スクリプトが依存するツール（git, curl, awk等）のバージョン要件を事前にチェックすることで、不適切な環境での実行を防ぎ、ユーザーに明確なエラーメッセージを提供する。シェルスクリプトから呼び出して依存関係の検証を自動化できる。

**画面へのアクセス方法**：
1. 直接実行: `$ZSH/tools/require_tool.sh <TOOL> <MIN_VERSION>`
2. スクリプト内から呼び出し: `source $ZSH/tools/require_tool.sh && require_tool <TOOL> <MIN_VERSION>`
3. ヘルプ表示: `require_tool.sh -h` または `require_tool.sh --help`

**主要な操作・処理内容**：
1. 指定されたツール名から実行可能ファイルのパスを特定
2. 環境変数（ツール名を大文字化したもの）が設定されていれば、その値をツールパスとして使用
3. ツールの `--version` オプションを実行してバージョン情報を取得
4. 取得したバージョンと要求バージョンをセマンティックバージョニング形式で比較
5. 要件を満たしていれば終了コード0、そうでなければ終了コード1を返す

**画面遷移**：
- 入口：他スクリプトからの呼び出しまたはユーザーによる直接実行
- 出口：終了コードで結果を返す（他画面への遷移なし）

**権限による表示制御**：特になし。ただし、チェック対象ツールの実行権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 85 | require_tool.sh | 主機能 | 必要なツールがインストールされているか確認するユーティリティ |

## 画面種別

CLIユーティリティ（バージョン確認ツール）

## URL/ルーティング

```
$ZSH/tools/require_tool.sh [options] [TOOL MIN_VERSION]
```

### コマンドラインオプション

| オプション | 説明 |
|-----------|------|
| -h, --help | ヘルプメッセージを表示して終了 |
| TOOL | チェック対象のツール名またはパス |
| MIN_VERSION | 要求する最小バージョン（例: 2.0, 4.6.3） |

## 入出力項目

### 入力パラメータ

| No | パラメータ名 | 位置 | 必須 | デフォルト値 | 説明 |
|----|-------------|------|------|-------------|------|
| 1 | TOOL | $1 | はい | なし | チェック対象のツール名（例: git, gcc, emacs） |
| 2 | MIN_VERSION | $2 | はい | なし | 要求する最小バージョン番号 |

### 環境変数

| 変数名 | 必須 | 説明 |
|--------|------|------|
| ${TOOL^^} | いいえ | ツール名を大文字にした環境変数（例: GCC, EMACS）が設定されていればツールパスとして使用 |
| PATH | はい | ツール検索用のPATH環境変数 |

### 出力（終了コード）

| 終了コード | 意味 |
|-----------|------|
| 0 | ツールが存在し、バージョン要件を満たしている |
| 1 | ツールが存在しない、またはバージョン要件を満たしていない |

## 表示項目

### エラーメッセージ

| 条件 | メッセージ | 出力先 |
|-----|----------|--------|
| ツールが見つからない | "{tool} is required" | stderr |
| バージョン不足 | "{TOOL} {MIN_VERSION} or better is required: this is {tool} {version}" | stderr |
| パラメータ過多 | "ERROR: expecting 2 parameters. Please see option --help" | stdout |

### ヘルプメッセージ

`-h` または `--help` オプション指定時に詳細な使用方法を表示。

## イベント仕様

### 1-ヘルプ表示

**トリガー**: `-h` または `--help` オプション指定

**処理内容**:
1. `usage` 関数を呼び出してヘルプメッセージを表示
2. 終了コード0で終了

### 2-パラメータ検証

**トリガー**: スクリプト実行時

**処理内容**:
1. パラメータ数が2より多い場合、エラーメッセージを表示して終了コード1で終了
2. パラメータが適切であれば `require_tool` 関数を呼び出し

### 3-ツールパス解決

**トリガー**: `require_tool` 関数呼び出し

**処理内容**:
1. ツール名を大文字に変換して環境変数名を生成
2. その環境変数が設定されていれば、その値をツールパスとして使用
3. 環境変数が未設定であれば、ツール名をそのままパスとして使用

### 4-バージョン取得

**トリガー**: ツールパス解決後

**処理内容**:
1. `{tool} --version` を実行
2. 出力からバージョン番号を正規表現で抽出（`[0-9]*\.[0-9.]*` パターン）
3. バージョンが取得できなければエラーメッセージを表示して終了コード1で返す

### 5-バージョン比較

**トリガー**: バージョン取得成功後

**処理内容**:
1. `__require_tool_version_compare` 関数でバージョンを比較
2. awkスクリプトを使用してstrverscmp相当の比較を実行
3. 要求バージョンが実際のバージョンより大きい場合、エラーメッセージを表示

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

本スクリプトはデータベースを使用しない。読み取り専用の検証処理のみを行う。

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

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

## メッセージ仕様

| No | メッセージ種別 | メッセージ内容 | 表示条件 |
|----|---------------|---------------|----------|
| 1 | エラー | "{tool} is required" | ツールが見つからない、またはバージョン取得できない場合 |
| 2 | エラー | "{TOOL} {MIN_VERSION} or better is required: this is {tool} {version}" | バージョン要件を満たさない場合 |
| 3 | エラー | "ERROR: expecting 2 parameters. Please see option --help" | パラメータが2より多い場合 |

## 例外処理

| No | 例外状況 | 処理内容 |
|----|---------|----------|
| 1 | ツールが存在しない | エラーメッセージをstderrに出力し、終了コード1で終了 |
| 2 | ツールに--versionオプションがない | バージョン取得に失敗し、"{tool} is required"メッセージで終了 |
| 3 | バージョン番号のパースに失敗 | バージョンが空となり、"{tool} is required"メッセージで終了 |
| 4 | バージョン要件未達 | 詳細なエラーメッセージを表示して終了コード1で終了 |

## 備考

- バージョン比較ロジックはstrverscmp関数（GNU libc）相当の動作を再現
- 7th edition Unix awk (1978)との互換性を考慮したawkスクリプトを使用
- 環境変数によるツールパスのオーバーライドが可能（例: `CC=g++ require_tool.sh cc 4.6`）
- バージョン番号は `[数字].[数字...]` のパターンで抽出される
- 分数形式のバージョン（0で始まるもの）も正しく比較される

---

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

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

### 推奨読解順序

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

本スクリプトは複雑なデータ構造を使用しないが、バージョン番号の比較ロジックが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | require_tool.sh | `tools/require_tool.sh` | 行8-63: バージョン比較用のawkスクリプト |

**読解のコツ**: awkスクリプトはstrverscmpアルゴリズムを実装しており、数字を整数として比較しつつ、分数形式（0で始まる数字列）も正しく処理する。

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

処理の起点となるメイン処理を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | require_tool.sh | `tools/require_tool.sh` | 行148-161: コマンドライン引数の処理とrequire_tool呼び出し |

**主要処理フロー**:
1. **行148-155**: forループで引数を走査し、-h/--helpをチェック
2. **行156-159**: 引数が2より多い場合はエラー
3. **行161**: `require_tool $@` で実際の処理を実行

#### Step 3: ツール検出処理を理解する

ツールのパス解決とバージョン取得。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | require_tool.sh | `tools/require_tool.sh` | 行87-103: require_tool関数 |

**主要処理フロー**:
- **行89**: ツール名を大文字に変換して環境変数名を生成
- **行90**: printenvで環境変数を取得、未設定ならツール名をそのまま使用
- **行91-92**: `{tool} --version` を実行し、sedでバージョン番号を抽出
- **行93-96**: バージョンが空なら "{tool} is required" を出力して終了
- **行97-101**: バージョン比較を実行し、要件未達ならエラー出力

#### Step 4: バージョン比較処理を理解する

strverscmp相当のバージョン比較ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | require_tool.sh | `tools/require_tool.sh` | 行1-71: __require_tool_version_compare関数 |

**主要処理フロー**:
- **行6**: `set +e` でエラー無視モード（比較結果で終了コードが変わるため）
- **行8-63**: awkスクリプト本体
  - **行16-53**: 数字が先頭にある場合の比較処理（整数比較または分数比較）
  - **行54-58**: 通常の文字比較処理
  - **行59-60**: 比較結果に基づいてexitコードを設定
- **行64**: awkを実行
- **行65-69**: awkの終了コードを`<`、`=`、`>`の記号に変換

#### Step 5: ヘルプ表示を理解する

使用方法の表示処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | require_tool.sh | `tools/require_tool.sh` | 行105-146: usage関数 |

**主要処理フロー**:
- **行106-145**: ヒアドキュメントで詳細なヘルプメッセージを出力

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

```
require_tool.sh [TOOL] [MIN_VERSION]
    |
    +-- (引数解析ループ: 行148-155)
    |       |
    |       +-- -h/--help: usage() -> exit 0
    |
    +-- (パラメータ数チェック: 行156-159)
    |       |
    |       +-- > 2: エラーメッセージ -> exit 1
    |
    +-- require_tool($1, $2) (行161)
            |
            +-- (環境変数解決: 行89-90)
            |       +-- ${TOOL^^} 環境変数をチェック
            |       +-- 設定されていればその値をツールパスに
            |
            +-- (バージョン取得: 行91-92)
            |       +-- {tool} --version | sed
            |
            +-- (バージョン検証: 行93-96)
            |       +-- 空ならエラー終了
            |
            +-- __require_tool_version_compare($2, $version) (行97)
                    |
                    +-- awk (strverscmpアルゴリズム)
                            |
                            +-- 比較結果: '<' / '=' / '>'
                                    |
                                    +-- '>' なら要件未達でエラー
```

### データフロー図

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

TOOL引数                  環境変数解決
(例: git)                 ├── ${TOOL^^} 変数チェック
        |                 └── PATH検索
        v                         |
MIN_VERSION引数                   v
(例: 2.0)                 バージョン取得
        |                 ├── {tool} --version 実行
        |                 └── sed でバージョン抽出
        |                         |
        v                         v
                          バージョン比較
                          ├── awk スクリプト実行
                          └── strverscmp アルゴリズム
                                  |
                                  v
                          [終了コード]
                          ├── 0: 要件を満たす
                          └── 1: 要件未達またはツール不在
                                  |
                                  v
                          [stderr]
                          エラーメッセージ（失敗時のみ）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| require_tool.sh | `tools/require_tool.sh` | ソース | ツールバージョン確認のメインスクリプト |
| install.sh | `tools/install.sh` | 関連ソース | インストール時の依存関係チェックで使用可能 |
