# 機能設計書 120-Artifacts

## 概要

本ドキュメントは、Julia標準ライブラリ `Artifacts` モジュールの機能設計を記述する。パッケージバイナリアーティファクトの管理・取得機能を提供するモジュールである。

### 本機能の処理概要

**業務上の目的・背景**：Juliaのパッケージエコシステムでは、プラットフォーム固有のバイナリライブラリ、データセット、その他のファイルを「アーティファクト」として管理する仕組みが必要である。Artifactsモジュールは、`Artifacts.toml`ファイルに基づいてアーティファクトのメタデータを管理し、gitツリーハッシュ（SHA1）による内容アドレッシングでアーティファクトの存在確認・パス解決を行う。BinaryBuilderで生成されたJLLパッケージのバイナリ配布基盤として重要な役割を果たす。

**機能の利用シーン**：JLLパッケージでのバイナリライブラリの配置パス取得（@artifact_str）、Artifacts.tomlの解析とメタデータ取得（artifact_meta）、アーティファクトの存在確認（artifact_exists）、プラットフォームに応じたアーティファクト選択、遅延アーティファクト（lazy artifacts）のオンデマンドダウンロード、Overrides.tomlによるアーティファクト配置の上書き。

**主要な処理内容**：
1. Artifacts.tomlの解析とロード（load_artifacts_toml, parse_toml）
2. アーティファクトメタデータの取得（artifact_meta）
3. アーティファクトハッシュの取得（artifact_hash）
4. アーティファクトパスの解決（artifact_path, artifact_paths）
5. アーティファクト存在確認（artifact_exists）
6. プラットフォーム選択（unpack_platform, select_platform）
7. Overrides.tomlによるオーバーライド管理（load_overrides, query_override, process_overrides）
8. @artifact_strマクロによる便利なパスアクセス（スラッシュインデックス対応）
9. ダウンロード可能アーティファクトの選択（select_downloadable_artifacts）
10. Artifacts.toml検索（find_artifacts_toml）

**関連システム・外部連携**：Base.TOML（TOML解析）、Base.BinaryPlatforms（プラットフォーム検出・選択）、LazyArtifacts/Pkg（遅延ダウンロード）、depotパス（~/.julia等）。

**権限による制御**：特になし。アーティファクトのインストールパスはdepotパスの権限に依存。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | REPL / パッケージビルド | 参照画面 | @artifact_strの使用、artifact_meta等のAPI呼び出し |

## 機能種別

パッケージ管理 / アーティファクト管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | アーティファクト名 | Artifacts.toml内に存在すること |
| artifacts_toml | String | Yes | Artifacts.tomlファイルパス | 有効なファイルパス |
| platform | AbstractPlatform | No | ターゲットプラットフォーム。デフォルト=HostPlatform() | Platform型 |
| pkg_uuid | UUID | No | パッケージUUID（オーバーライド解決用） | 有効なUUID |
| hash | SHA1 | Yes (パスAPI) | アーティファクトのgitツリーハッシュ | 40文字の16進文字列 |
| honor_overrides | Bool | No | Overrides.tomlを尊重するか。デフォルト=true | - |
| include_lazy | Bool | No | 遅延アーティファクトを含むか。デフォルト=false | - |

### 入力データソース

- Artifacts.tomlファイル（パッケージに同梱）
- Overrides.toml（depotディレクトリ内）
- ファイルシステム（depotパス内のアーティファクトディレクトリ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| meta | Dict{String,Any} | アーティファクトのメタデータ辞書（git-tree-sha1, download, lazy等） |
| hash | SHA1 | アーティファクトのgitツリーハッシュ。見つからない場合はnothing |
| path | String | アーティファクトのインストールパス |
| exists | Bool | アーティファクトがディスク上に存在するか |
| artifacts | Dict{String,Any} | ダウンロード可能なアーティファクト辞書 |
| toml_path | String | 見つかったArtifacts.tomlのパス。見つからない場合はnothing |

### 出力先

- 戻り値として辞書/文字列/ハッシュ/Bool等を返却
- ファイルシステム（アーティファクトのインストールディレクトリ）

## 処理フロー

### 処理シーケンス

```
1. @artifact_str "name" マクロ呼び出し
   └─ find_artifacts_toml()でArtifacts.tomlを検索
   └─ load_artifacts_toml()で解析
   └─ artifact_slash_lookup()で名前とパスを分離
   └─ _artifact_str()でパスを解決
       └─ artifact_paths()で候補パスを取得
       └─ 存在するパスを返却
       └─ 存在しない場合、lazy artifactならensure_artifact_installed()

2. artifact_meta(name, artifacts_toml) 呼び出し
   └─ load_artifacts_toml()でTOML読み込み
   └─ プラットフォーム固有の場合、select_platform()で選択
   └─ git-tree-sha1の存在を検証
   └─ メタデータ辞書を返却

3. load_overrides() 呼び出し
   └─ 全depotのOverrides.tomlを逆順で読み込み
   └─ UUID/名前ベースとハッシュベースのオーバーライドを構築
   └─ ARTIFACT_OVERRIDESにキャッシュ
```

### フローチャート

```mermaid
flowchart TD
    A['@artifact_str "name"'] --> B["find_artifacts_toml()"]
    B --> C{"Artifacts.toml発見?"}
    C -->|No| D["エラー"]
    C -->|Yes| E["load_artifacts_toml()"]
    E --> F["artifact_slash_lookup()"]
    F --> G["artifact_paths(hash)"]
    G --> H{"ディスク上に存在?"}
    H -->|Yes| I["パスを返却"]
    H -->|No| J{"lazy artifact?"}
    J -->|Yes| K["ensure_artifact_installed()"]
    J -->|No| L["エラー: artifact not found"]
    K --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-120-01 | 内容アドレッシング | アーティファクトはgit-tree-sha1ハッシュで一意に識別される | 全操作 |
| BR-120-02 | プラットフォーム選択 | Artifacts.toml内の配列エントリからHostPlatformに最適なものを選択 | プラットフォーム固有アーティファクト |
| BR-120-03 | オーバーライド優先 | Overrides.tomlのエントリはArtifacts.tomlより優先される | honor_overrides=true時 |
| BR-120-04 | depotパス検索順 | Base.DEPOT_PATHの順序で候補パスを検索し、最初に存在するものを返す | artifact_path時 |
| BR-120-05 | 遅延アーティファクト | lazy=trueのアーティファクトは@artifact_str初回アクセス時にダウンロード | LazyArtifactsがusingされている場合 |
| BR-120-06 | スラッシュインデックス | "FFMPEG/bin/ffmpeg"のようにアーティファクト名の後にパスを指定可能 | @artifact_str使用時（Julia 1.6+） |
| BR-120-07 | Artifacts.toml検索 | ソースファイルから親ディレクトリを辿ってArtifacts.tomlを検索 | @artifact_str使用時 |

### 計算ロジック

- アーティファクトパス: `joinpath(depot, "artifacts", bytes2hex(hash.bytes))`
- スラッシュ分割: `split(name, r"(/|\\)")` でアーティファクト名とサブパスを分離

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| error | Artifacts.toml未発見 | find_artifacts_toml()がnothingを返す | パッケージ内にArtifacts.tomlを配置 |
| error | アーティファクト未発見 | 指定名のアーティファクトが存在しない | Artifacts.toml内の名前を確認 |
| error | 遅延アーティファクト未設定 | lazy=trueだがLazyArtifactsが未using | `using LazyArtifacts`を追加 |
| @error | git-tree-sha1未定義 | メタデータにgit-tree-sha1がない | Artifacts.tomlを修正 |
| @error | プラットフォーム情報不足 | os/archキーが欠落 | Artifacts.tomlにos/archを追加 |

### リトライ仕様

リトライ不要。遅延アーティファクトのダウンロード失敗はPkgモジュール側で処理。

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

該当なし。

## パフォーマンス要件

- Artifacts.tomlの解析結果はBase.parsed_toml()でキャッシュされる
- ARTIFACT_OVERRIDESもキャッシュされ、force=trueで再読み込み可能
- @artifact_strはコンパイル時にArtifacts.tomlを解析し、実行時オーバーヘッドを最小化
- _artifacts_world_ageによるキャッシュ世代管理

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

- git-tree-sha1はアーティファクトの内容整合性を保証するハッシュ
- Overrides.tomlでローカルパスにリダイレクトする場合、そのパスの信頼性を確認すること
- ダウンロードURLの信頼性はArtifacts.tomlの管理者に依存

## 備考

- artifact_names定数は("JuliaArtifacts.toml", "Artifacts.toml")の2つを検索
- Base.include_dependency()でArtifacts.tomlの変更追跡を登録（JITファイル無効化）
- Pkg.Artifactsとの互換性のため、LazyArtifactsモジュールの検出ロジックが含まれる
- プリコンパイル対応のためのprecompileヒントが末尾に定義されている

---

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

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

### 推奨読解順序

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

Artifacts.tomlの構造とオーバーライド辞書を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **37行目**: artifact_names定数 -- 検索するTOMLファイル名 |
| 1-2 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **39行目**: ARTIFACTS_DIR_OVERRIDE -- ディレクトリオーバーライド |
| 1-3 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **111行目**: ARTIFACT_OVERRIDES -- オーバーライド辞書（UUID/hashベース） |

**読解のコツ**: Artifactsモジュールは3つの主要な辞書を管理する。(1) Artifacts.tomlの解析結果、(2) Overrides.tomlの解析結果（UUID/hash別）、(3) プラットフォーム選択結果。

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

@artifact_strマクロがメインの利用エントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **689-742行目**: @artifact_strマクロ。コンパイル時にArtifacts.tomlを解析し、実行時は_artifact_str()を呼び出す |
| 2-2 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **560-603行目**: __artifact_str()の実装。パス解決、lazy artifact対応、エラーメッセージ生成 |

**主要処理フロー**:
1. **691行目**: `__source__.file`からソースファイルパスを取得
2. **696行目**: `find_artifacts_toml(srcfile)`でArtifacts.toml検索
3. **709行目**: `load_artifacts_toml(artifacts_toml)`でコンパイル時解析
4. **712行目**: `Base.include_dependency(artifacts_toml, track_content=true)`で変更追跡
5. **731行目**: `artifact_slash_lookup()`で名前とサブパスを分離し、ハッシュを取得

#### Step 3: オーバーライド機構を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **112-193行目**: load_overrides()の実装。全depotのOverrides.tomlを読み込みキャッシュ |
| 3-2 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **206-216行目**: query_override()。ハッシュベースおよびUUID/名前ベースのオーバーライド検索 |
| 3-3 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **341-372行目**: process_overrides()。UUID/名前オーバーライドをハッシュオーバーライドに変換 |

#### Step 4: プラットフォーム選択を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **280-304行目**: unpack_platform()。Artifacts.tomlエントリからPlatformオブジェクトを構築 |
| 4-2 | Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | **401-433行目**: artifact_meta()。配列エントリの場合select_platform()でプラットフォーム選択 |

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

```
@artifact_str "name"
    |
    +-- find_artifacts_toml(srcfile)          # Artifacts.toml検索
    +-- load_artifacts_toml(artifacts_toml)   # TOML解析
    +-- artifact_slash_lookup(name, ...)      # 名前/パス分離
    |   +-- split_artifact_slash(name)
    |   +-- artifact_meta(name, ..., platform)
    |       +-- select_platform(dl_dict, platform)
    |
    +-- _artifact_str(module, toml, name, tail, dict, hash, platform, LazyArtifacts)
        +-- artifact_paths(hash)              # 候補パス生成
        |   +-- query_override(hash)          # オーバーライド確認
        |   +-- artifacts_dirs(hex_hash)      # depotパス生成
        |
        +-- [見つからない場合]
            +-- LazyArtifacts.ensure_artifact_installed()  # 遅延DL
```

### データフロー図

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

Artifacts.toml  ───▶  load_artifacts_toml()    ───▶  Dict{String,Any}
                      parse_toml + overrides          (メタデータ辞書)

名前+Platform   ───▶  artifact_meta()          ───▶  Dict{String,Any}
                      プラットフォーム選択             (メタデータ)

SHA1ハッシュ    ───▶  artifact_path()           ───▶  String
                      depotパス検索                    (インストールパス)

Overrides.toml  ───▶  load_overrides()         ───▶  Dict{Symbol,Any}
                      UUID/hashオーバーライド          (UUID/hash辞書)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Artifacts.jl | `stdlib/Artifacts/src/Artifacts.jl` | ソース | 全実装を含む単一ファイル。@artifact_str, artifact_meta, load_overrides等 |
| Project.toml | `stdlib/Artifacts/Project.toml` | 設定 | パッケージ依存関係定義 |
| runtests.jl | `stdlib/Artifacts/test/runtests.jl` | テスト | ユニットテスト |
