# 機能設計書 40-ロックファイル

## 概要

本ドキュメントは、Bunパッケージマネージャーにおけるロックファイル（Lockfile）機能の設計仕様を記載する。ロックファイルは、依存関係の解決結果を永続化し、再現性のあるインストールを保証するための機能である。

### 本機能の処理概要

ロックファイル機能は、パッケージの依存関係解決結果を記録し、将来のインストール時に同じバージョンの依存関係が使用されることを保証する。Bunはバイナリ形式（bun.lockb）とテキスト形式（bun.lock）の2種類のロックファイルをサポートしている。

**業務上の目的・背景**：チーム開発やCI/CD環境では、すべての環境で同じ依存関係が使用されることが重要である。ロックファイルにより、「自分の環境では動くが他の環境では動かない」という問題を防止する。また、バイナリ形式のロックファイルにより高速な読み書きを実現している。

**機能の利用シーン**：`bun install`実行時にロックファイルを読み込み、既存の解決結果を参照する。新しいパッケージの追加・更新時にはロックファイルを更新する。

**主要な処理内容**：
1. ロックファイルの読み込み（bun.lock/bun.lockb）
2. 依存関係解決結果の参照
3. ロックファイルへの書き込み（アトミック）
4. npm/yarn/pnpmロックファイルからの移行
5. メタハッシュによる変更検知
6. ワークスペース情報の管理

**関連システム・外部連携**：依存関係解決機能、パッケージインストール機能と連携。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | install | 主機能 | bun.lockb/bun.lockファイルの読み書きと管理 |
| 7 | add | 補助機能 | ロックファイルへの追加パッケージ記録 |
| 8 | remove | 補助機能 | ロックファイルからの削除パッケージ除去 |
| 9 | update | 補助機能 | ロックファイルのバージョン更新 |

## 機能種別

ファイルI/O / データ永続化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| lockfile | ファイル | No | 既存のロックファイル | bun.lock または bun.lockb |
| save_text_lockfile | bool | No | テキスト形式で保存するか | bunfig.toml設定 |

### 入力データソース

- 既存のロックファイル（bun.lock/bun.lockb）
- 依存関係解決結果
- package.json
- npmレジストリからのパッケージ情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ロックファイル | ファイル | bun.lock（テキスト形式）またはbun.lockb（バイナリ形式） |
| LoadResult | enum | 読み込み結果（ok/not_found/err） |

### 出力先

プロジェクトルートディレクトリ

## 処理フロー

### 処理シーケンス

```
1. ロックファイル読み込み
   ├─ bun.lockを試行
   │   └─ 存在しない場合はbun.lockbを試行
   ├─ 両方存在しない場合は他のロックファイル移行を試行
   │   └─ package-lock.json、yarn.lock、pnpm-lock.yaml
   └─ LoadResultを返却
2. 依存関係解決
   └─ ロックファイルの既存解決結果を参照
3. ロックファイル更新
   ├─ メタハッシュ計算
   ├─ パッケージ情報シリアライズ
   └─ アトミック書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[開始: ロックファイル読み込み] --> B{bun.lock存在?}
    B -->|Yes| C[テキスト形式読み込み]
    B -->|No| D{bun.lockb存在?}
    D -->|Yes| E[バイナリ形式読み込み]
    D -->|No| F{他のロックファイル存在?}
    F -->|Yes| G[移行処理]
    F -->|No| H[not_found返却]
    C --> I[JSONパース]
    I --> J[バイナリ形式に変換]
    E --> K[Serializer.load]
    G --> L{package-lock.json?}
    L -->|Yes| M[npm移行]
    L -->|No| N{yarn.lock?}
    N -->|Yes| O[yarn移行]
    N -->|No| P{pnpm-lock.yaml?}
    P -->|Yes| Q[pnpm移行]
    J --> R[LoadResult.ok]
    K --> R
    M --> R
    O --> R
    Q --> R
    R --> S[終了]
    H --> S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-40-001 | テキスト優先 | bun.lockがbun.lockbより優先して読み込まれる | 両方存在する場合 |
| BR-40-002 | フォーマット保持 | 既存のロックファイル形式を保持して保存 | 更新時 |
| BR-40-003 | 新規プロジェクトデフォルト | 新規プロジェクトではテキスト形式がデフォルト | ロックファイル未存在時 |
| BR-40-004 | 移行時テキスト | npm/yarn/pnpmから移行時はテキスト形式で保存 | 移行処理時 |
| BR-40-005 | アトミック書き込み | ロックファイル更新は一時ファイル経由でアトミックに実行 | 保存時 |

### ロックファイル形式

| 形式 | ファイル名 | 特徴 | 用途 |
|------|-----------|------|------|
| バイナリ | bun.lockb | 高速読み書き、コンパクト | パフォーマンス重視 |
| テキスト | bun.lock | 人間が読める、差分が見やすい | コードレビュー、バージョン管理 |

## データ構造

### Lockfile構造体

| フィールド | 型 | 説明 |
|-----------|-----|------|
| format | FormatVersion | ロックファイルフォーマットバージョン |
| meta_hash | MetaHash | 変更検知用ハッシュ（SHA512/256） |
| packages | Package.List | パッケージ情報リスト |
| buffers | Buffers | 文字列・依存関係バッファ |
| package_index | PackageIndex.Map | パッケージ名からIDへのマッピング |
| string_pool | StringPool | 文字列プール |
| scripts | Scripts | ライフサイクルスクリプト |
| workspace_paths | NameHashMap | ワークスペースパス |
| workspace_versions | VersionHashMap | ワークスペースバージョン |
| trusted_dependencies | TrustedDependenciesSet | 信頼済み依存関係 |
| patched_dependencies | PatchedDependenciesMap | パッチ適用依存関係 |
| overrides | OverrideMap | オーバーライド設定 |
| catalogs | CatalogMap | カタログ設定 |

### LoadResult

| 状態 | 説明 |
|------|------|
| not_found | ロックファイルが存在しない |
| err | 読み込みエラー（step, value, lockfile_path, format） |
| ok | 正常読み込み（lockfile, loaded_from_binary_lockfile, migrated, format） |

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | エラー | ファイルオープン失敗（open_file） | ファイル権限を確認 |
| - | エラー | ファイル読み込み失敗（read_file） | ディスク容量を確認 |
| - | エラー | パース失敗（parse_file） | ロックファイルを削除して再生成 |
| - | エラー | 移行失敗（migrating） | 元のロックファイル形式を確認 |

### リトライ仕様

リトライは行わない。エラー時はロックファイルを再生成する。

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

ロックファイルの更新は以下の手順でアトミックに行われる：
1. 一時ファイルに書き込み
2. 一時ファイルを本番ファイルにリネーム（アトミック操作）

## パフォーマンス要件

- バイナリ形式は高速シリアライズ/デシリアライズ
- 大規模プロジェクト（数千パッケージ）でも高速に処理
- メモリ効率のためにString Poolを使用

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

- trusted_dependenciesでpostinstallスクリプト実行を制御
- メタハッシュによる整合性検証
- パッチ適用依存関係のハッシュ検証

## 備考

- bun.lockはJSONC形式（コメント可能）
- テキストロックファイルのlockfileVersionで互換性管理
- configVersionでBunバージョン間の互換性管理

---

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

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

### 推奨読解順序

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

まず、ロックファイルで使用される主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lockfile.zig | `src/install/lockfile.zig` | Lockfile構造体、LoadResult、Scripts |

**読解のコツ**:
- **1-30行目**: Lockfile構造体のフィールド定義（format、meta_hash、packages、buffers、scripts等）
- **52行目**: default_filename = "bun.lockb"
- **54-100行目**: Scripts構造体（preinstall、install、postinstall等のライフサイクルスクリプト管理）
- **106-216行目**: LoadResult union型（not_found、err、ok）とLockfileFormat enum（text、binary）

#### Step 2: ロックファイル読み込みを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lockfile.zig | `src/install/lockfile.zig` | loadFromDir()、loadFromBytes() |

**主要処理フロー**:
- **218-226行目**: loadFromCwd()でカレントディレクトリから読み込み
- **228-370行目**: loadFromDir()でbun.lock優先、なければbun.lockb、それもなければ移行処理
- **372-400行目**: loadFromBytes()でバイナリロックファイルをデシリアライズ

#### Step 3: テキストロックファイルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | bun.lock.zig | `src/install/lockfile/bun.lock.zig` | TextLockfile.Stringifier |

**主要処理フロー**:
- **1-8行目**: Version enum（v0、v1）、current = v1
- **23-300行目以降**: Stringifier.saveFromBinary()でバイナリからテキスト形式への変換
- ワークスペース、信頼済み依存関係、パッチ適用依存関係の出力

#### Step 4: ロックファイルのクリーン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | lockfile.zig | `src/install/lockfile.zig` | clean()、cleanWithLogger() |

**主要処理フロー**:
- **555-572行目**: clean()でロックファイルの不要パッケージ削除
- **637-832行目**: cleanWithLogger()で詳細なクリーン処理（パッケージIDマッピング、Cloner使用）

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

```
bun install
    │
    ├─ Lockfile.loadFromCwd() / loadFromDir()
    │      ├─ bun.lock読み込み試行
    │      │      └─ TextLockfile.parseIntoBinaryLockfile()
    │      ├─ bun.lockb読み込み試行
    │      │      └─ Serializer.load()
    │      └─ migration.detectAndLoadOtherLockfile()
    │             ├─ npm移行
    │             ├─ yarn移行
    │             └─ pnpm移行
    │
    ├─ PackageManager.resolve()
    │      └─ ロックファイル参照
    │
    └─ Lockfile.save()
           ├─ generateMetaHash()
           ├─ Serializer.save() [binary]
           └─ TextLockfile.Stringifier.saveFromBinary() [text]
```

### データフロー図

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

bun.lock ─────────▶ JSONパース ───▶ parseIntoBinaryLockfile()
       │
       ▼
bun.lockb ────────▶ Serializer.load() ───▶ Lockfile構造体
       │
       ▼
package-lock.json ─▶ migration ───▶ Lockfile構造体
yarn.lock ─────────▶ migration ───▶ Lockfile構造体
pnpm-lock.yaml ────▶ migration ───▶ Lockfile構造体
       │
       ▼
Lockfile構造体 ────▶ 依存関係解決 ───▶ 更新済みLockfile
       │
       ▼
更新済みLockfile ──▶ generateMetaHash() ───▶ メタハッシュ
       │
       ▼
保存処理 ──────────▶ Serializer.save() ───▶ bun.lockb
                    ▶ Stringifier.saveFromBinary() ───▶ bun.lock
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lockfile.zig | `src/install/lockfile.zig` | ソース | Lockfile構造体、読み書き処理 |
| bun.lock.zig | `src/install/lockfile/bun.lock.zig` | ソース | テキストロックファイル処理 |
| Tree.zig | `src/install/lockfile/Tree.zig` | ソース | 依存関係ツリー構造 |
| migration.zig | `src/install/migration.zig` | ソース | 他形式からの移行 |
| npm.zig | `src/install/npm.zig` | ソース | npmパッケージ情報 |
| resolution.zig | `src/install/resolution.zig` | ソース | Resolution構造体 |
| dependency.zig | `src/install/dependency.zig` | ソース | Dependency構造体 |
| install.zig | `src/install/install.zig` | ソース | インストール処理本体 |
