# 画面設計書 27-パッケージ取得画面

## 概要

本ドキュメントは、Zigコンパイラの `zig fetch` コマンドによるパッケージ取得画面の設計仕様を定義する。この画面は、外部パッケージをグローバルキャッシュにダウンロード・保存し、そのハッシュ値を出力する機能を提供する。

### 本画面の処理概要

パッケージ取得画面は、Zigのパッケージ管理システムにおいて依存関係をダウンロードするためのコマンドラインインターフェースである。URLまたはローカルパスからパッケージを取得し、グローバルキャッシュに保存するとともに、build.zig.zonへの登録もサポートする。

**業務上の目的・背景**：Zigのパッケージマネージャーは、外部ライブラリの依存関係管理を簡素化する。この画面は、新しい依存関係の追加、既存依存関係の更新、パッケージハッシュの取得など、パッケージ管理の中核機能を提供する。Gitリポジトリ、tarballアーカイブ、ローカルファイルシステムからのパッケージ取得をサポートし、再現可能なビルドのためのハッシュベースの依存管理を実現する。

**画面へのアクセス方法**：ターミナルから `zig fetch [options] <url|path>` コマンドを実行する。URLまたはパスは必須引数で、オプションで `--save` を指定するとbuild.zig.zonに自動登録される。

**主要な操作・処理内容**：
1. コマンドライン引数をパース
2. HTTPクライアントを初期化（必要に応じてプロキシ設定）
3. グローバルキャッシュディレクトリを準備
4. パッケージをダウンロード・解凍
5. パッケージハッシュを計算
6. --save オプション時はbuild.zig.zonを更新
7. パッケージハッシュを標準出力に出力

**画面遷移**：本コマンドは独立したパッケージ管理機能であり、他の画面への直接遷移は発生しない。ただし、取得したパッケージは後続の `zig build` で使用される。

**権限による表示制御**：特に権限による制御は行われない。ネットワークアクセスとファイルシステム書き込み権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | fetch | 主機能 | パッケージをグローバルキャッシュにコピーしハッシュを出力する処理 |
| 75 | 依存関係解決 | 補助機能 | パッケージ依存関係の解決処理 |

## 画面種別

パッケージ管理（CLI）

## URL/ルーティング

コマンド: `zig fetch [options] <url|path>`

## 入出力項目

### 入力項目（コマンドライン引数）

| No | 項目名 | オプション | 型 | 必須 | 説明 |
|----|--------|-----------|-----|------|------|
| 1 | ヘルプ | -h, --help | - | × | ヘルプメッセージを表示 |
| 2 | キャッシュディレクトリ | --global-cache-dir [path] | パス | × | グローバルキャッシュディレクトリを上書き |
| 3 | デバッグハッシュ | --debug-hash | - | × | 詳細なハッシュ情報を表示 |
| 4 | 保存 | --save | - | × | パッケージをbuild.zig.zonに追加 |
| 5 | 名前付き保存 | --save=[name] | 文字列 | × | 指定名でbuild.zig.zonに追加 |
| 6 | 正確なURL保存 | --save-exact | - | × | URLを正確に保存（refを解決しない） |
| 7 | 名前付き正確保存 | --save-exact=[name] | 文字列 | × | 指定名でURLを正確に保存 |
| 8 | URL/パス | <url\|path> | 文字列 | ○ | パッケージの場所（URLまたはローカルパス） |

### サポートされるURL形式

| 形式 | 説明 | 例 |
|------|------|-----|
| git+https:// | GitリポジトリのHTTPS URL | git+https://github.com/user/repo.git |
| git+http:// | GitリポジトリのHTTP URL | git+http://example.com/repo.git |
| https:// | HTTPSでアクセス可能なtarball | https://example.com/package.tar.gz |
| http:// | HTTPでアクセス可能なtarball | http://example.com/package.tar.gz |
| ローカルパス | ファイルシステム上のパス | /path/to/package |

## 表示項目

| No | 項目名 | 条件 | 説明 |
|----|--------|------|------|
| 1 | パッケージハッシュ | 常時 | 取得したパッケージのSHA256ハッシュ |
| 2 | 解決されたコミット | Gitリポジトリの場合 | refが解決されたコミットSHA |
| 3 | 進捗表示 | ダウンロード中 | フェッチ進捗状況 |

### 出力例

```
12345678901234567890123456789012345678901234567890123456789012345678
```

## イベント仕様

### 1-パッケージダウンロード

ユーザーが `zig fetch <url>` を実行すると:

1. コマンドライン引数をパース
2. HTTPクライアントを初期化
3. プロキシ設定を適用
4. グローバルキャッシュディレクトリを開く/作成
5. Package.Fetchを初期化
6. fetch.run() でパッケージをダウンロード
7. パッケージハッシュを計算
8. ハッシュを標準出力に出力

### 2-build.zig.zon更新（--save時）

`--save` オプションが指定された場合:

1. ビルドルートディレクトリを検索
2. 既存のbuild.zig.zonをロード（なければ作成）
3. AST fixupsを使用して依存関係を追加
4. 更新されたbuild.zig.zonを書き戻し

### 3-Git refの解決

Gitリポジトリからフェッチ時:

1. 指定されたref（ブランチ名、タグ）を解決
2. 最新コミットSHAを取得
3. --save時はコミットSHAでURLを更新
4. 解決されたコミット情報をログ出力

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

本機能はデータベースを使用しない。ただし、以下のファイルを更新する可能性がある:

| 操作 | 対象ファイル | 説明 |
|------|-------------|------|
| 作成/更新 | グローバルキャッシュ内 | ダウンロードしたパッケージファイル |
| 更新 | build.zig.zon | --save時に依存関係を追加 |

## メッセージ仕様

| 種別 | メッセージ | 発生条件 |
|------|----------|----------|
| 情報 | "resolved ref '{s}' to commit {s}" | Gitリポジトリでrefを解決した場合 |
| 情報 | "resolved to commit {s}" | refなしでコミットを解決した場合 |
| エラー | "expected argument after '{s}'" | オプション引数が不足 |
| エラー | "unrecognized parameter: '{s}'" | 不明なオプション |
| エラー | "unexpected extra parameter: '{s}'" | 余分な引数 |
| エラー | "missing url or path parameter" | URLまたはパスが未指定 |
| エラー | "unable to determine name; fetched package has no build.zig.zon file" | --save時にパッケージ名を決定できない |

## 例外処理

| エラー種別 | 説明 | 対処 |
|-----------|------|------|
| ネットワークエラー | URLへのアクセスに失敗 | エラーバンドルを出力してexit(1) |
| パースエラー | パッケージ形式が不正 | エラーバンドルを出力してexit(1) |
| ファイルシステムエラー | キャッシュへの書き込みに失敗 | エラーを伝播 |
| メモリ不足 | 大きなパッケージでメモリ枯渇 | OutOfMemoryを伝播 |

## 備考

- btrfsファイルシステムのバグ回避のため `ZIG_BTRFS_WORKAROUND` 環境変数をサポート
- Gitリポジトリのフラグメント部分（#ref）でブランチ/タグを指定可能
- --save使用時、refはコミットSHAに解決される（再現可能性のため）
- 元のrefはクエリパラメータ（?ref=...）として保存される

---

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

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

### 推奨読解順序

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

Package.Fetchとジョブキューの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Package.Fetch | 標準ライブラリ | フェッチ処理の状態管理構造体 |
| 1-2 | Package.Fetch.JobQueue | 標準ライブラリ | 非同期フェッチのジョブ管理 |

**読解のコツ**: `Package.Fetch` はパッケージのダウンロード、解凍、ハッシュ計算を管理する。

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

main.zigでのコマンドディスパッチを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | main.zig | `src/main.zig` | `zig fetch` コマンドの分岐処理（326-327行目） |

**主要処理フロー**:
1. **326行目**: `mem.eql(u8, cmd, "fetch")` でコマンド名を判定
2. **327行目**: `cmdFetch` 関数を呼び出し

#### Step 3: fetchコマンドの実装を理解する

cmdFetch関数の詳細を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | main.zig | `src/main.zig` | `cmdFetch` 関数（6931-7150行目） |

**主要処理フロー**:
- **6940-6942行目**: btrfs回避設定
- **6952-6983行目**: 引数パース
- **6987-6990行目**: HTTPクライアント初期化
- **6997-7004行目**: グローバルキャッシュディレクトリ準備
- **7006-7016行目**: JobQueue設定
- **7018-7046行目**: Package.Fetch初期化
- **7048-7057行目**: フェッチ実行とエラー処理
- **7059-7060行目**: ハッシュ計算
- **7065-7097行目**: --save処理

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

```
main() [src/main.zig:171]
    │
    └─ cmdFetch() [src/main.zig:6931]
           │
           ├─ 引数パース [6952-6983行目]
           │
           ├─ std.http.Client 初期化 [6987行目]
           │
           ├─ http_client.initDefaultProxies() [6990行目]
           │
           ├─ グローバルキャッシュディレクトリ準備 [6997-7004行目]
           │
           ├─ Package.Fetch.JobQueue 初期化 [7006-7016行目]
           │
           ├─ Package.Fetch 初期化 [7018-7046行目]
           │
           ├─ fetch.run() [7048行目]
           │      │
           │      └─ パッケージダウンロード・解凍・ハッシュ計算
           │
           ├─ fetch.computedPackageHash() [7059行目]
           │
           └─ (--save時) build.zig.zon更新 [7065-7149行目]
                  │
                  ├─ findBuildRoot() [7082行目]
                  │
                  ├─ loadManifest() [7089行目]
                  │
                  └─ AST fixupsで依存関係追加 [7099-7149行目]
```

### データフロー図

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

コマンドライン引数
 --save ─────────────┐
 --global-cache ─────┤
 <url|path> ─────────┤
                     │
                     ▼
              cmdFetch() ───┬──▶ 標準出力
                            │    (パッケージハッシュ)
                            │
                            │
URLからダウンロード ─────────┤
                            │
                            ▼
              Package.Fetch ───┬──▶ グローバルキャッシュ
                               │    (パッケージファイル)
                               │
                               │
                               └──▶ build.zig.zon (--save時)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| main.zig | `src/main.zig` | ソース | エントリーポイント、cmdFetch関数 |
| Package.Fetch | 標準ライブラリ | ソース | パッケージフェッチ処理の実装 |
| Package.Manifest | 標準ライブラリ | ソース | build.zig.zonのパース・生成 |
| std.http.Client | 標準ライブラリ | ソース | HTTPクライアント |
| introspect.zig | `src/introspect.zig` | ソース | キャッシュディレクトリ解決 |
