# 機能設計書 16-doom gc

## 概要

本ドキュメントは、Doom Emacsのガベージコレクションコマンド「doom gc」の機能設計を定義する。このコマンドは、不要になったパッケージやキャッシュを削除し、ディスク使用量を最適化する。

### 本機能の処理概要

doom gcは、Doom Emacsのパッケージ管理システムにおけるガベージコレクション（不要データの削除）を実行するコマンドである。孤立したパッケージリポジトリ、古いビルドファイル、不要なELPAパッケージ、古いネイティブコンパイルバイトコードを削除する。

**業務上の目的・背景**：Doom Emacsを長期間使用していると、パッケージの追加・削除・更新によって、不要になったファイルやディレクトリが蓄積する。これらはディスク容量を消費し、場合によっては古いバージョンとの競合を引き起こす可能性がある。doom gcはこれらの不要データを安全に削除し、クリーンな環境を維持する。

**機能の利用シーン**：
- doom syncの一部として自動実行される
- ディスク容量を確保したい時
- パッケージの問題をクリーンな状態から解決したい時
- 定期的なメンテナンスとして

**主要な処理内容**：
1. 孤立したstraight buildディレクトリの削除
2. 未使用のstraight reposディレクトリの削除
3. ELPAパッケージの削除（一時的なものとして扱われる）
4. 使用中のリポジトリのregraft（圧縮）
5. 古いELN（ネイティブコンパイル）バイトコードの削除

**関連システム・外部連携**：
- straight.el: パッケージ管理
- git: リポジトリの圧縮（regraft）
- native-comp: ネイティブコンパイルキャッシュ

**権限による制御**：各処理は-b, -p, -r, -g, -eオプションで無効化可能。

## 関連画面

本機能はCLIコマンドであり、GUIの画面は持たない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ターミナル | 主画面 | コマンドライン実行、削除結果表示 |

## 機能種別

クリーンアップ処理 / ガベージコレクション / ディスク最適化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -b, --no-builds | フラグ | No | ビルドディレクトリを削除しない | - |
| -p, --no-elpa | フラグ | No | ELPAパッケージを削除しない | - |
| -r, --no-repos | フラグ | No | 未使用リポジトリを削除しない | - |
| -e, --no-eln | フラグ | No | ELNバイトコードを削除しない | - |
| -g, --no-regraft | フラグ | No | リポジトリの圧縮を行わない | - |

### 入力データソース

- straight--profile-cache: 使用中のパッケージのキャッシュ
- straight--repo-cache: 使用中のリポジトリのキャッシュ
- straight--build-dir: ビルドディレクトリ
- straight--repos-dir: リポジトリディレクトリ
- package-user-dir: ELPAパッケージディレクトリ
- doom-packages--eln-output-path: ELNキャッシュディレクトリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 削除結果 | メッセージ | 各削除処理の成功/失敗 |
| 圧縮結果 | メッセージ | regraftによるサイズ変化 |

### 出力先

- 標準出力: 処理結果メッセージ

## 処理フロー

### 処理シーケンス

```
1. パッケージ初期化
   └─ doom-initialize-packages
   └─ doom-packages--barf-if-incomplete

2. キャッシュプルーニング
   └─ straight-prune-build-cache

3. 削除対象の収集
   └─ builds-to-purge: キャッシュにないビルドディレクトリ
   └─ repos-to-purge: キャッシュにないリポジトリ
   └─ repos-to-regraft: キャッシュにあるリポジトリ

4. ビルドディレクトリ削除
   └─ doom-gc--builds
   └─ 各ビルドディレクトリを再帰的に削除

5. ELPAパッケージ削除
   └─ doom-gc--elpa
   └─ package-user-dir配下を削除

6. リポジトリ削除
   └─ doom-gc--repos
   └─ 各リポジトリディレクトリと.modifiedファイルを削除

7. リポジトリ圧縮（regraft）
   └─ doom-gc--regraft-repos
   └─ git replace --graft HEAD
   └─ git reflog expire --expire=all --all
   └─ git gc --prune=now

8. ELNバイトコード削除
   └─ doom-gc--eln
   └─ 現在のEmacs以外のバージョン用キャッシュを削除
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[パッケージ初期化]
    B --> C[キャッシュプルーニング]
    C --> D[削除対象収集]
    D --> E{-b?}
    E -->|No| F[ビルド削除]
    E -->|Yes| G[スキップ]
    F --> H{-p?}
    G --> H
    H -->|No| I[ELPA削除]
    H -->|Yes| J[スキップ]
    I --> K{-r?}
    J --> K
    K -->|No| L[リポジトリ削除]
    K -->|Yes| M[スキップ]
    L --> N{-g?}
    M --> N
    N -->|No| O[リポジトリ圧縮]
    N -->|Yes| P[スキップ]
    O --> Q{-e?}
    P --> Q
    Q -->|No| R[ELN削除]
    Q -->|Yes| S[スキップ]
    R --> T[終了]
    S --> T
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | キャッシュベース判定 | straight--profile-cacheにないビルドは孤立とみなす | ビルド削除時 |
| BR-02 | ELPAは一時的 | ELPAパッケージはすべて削除対象 | ELPA削除時 |
| BR-03 | ローカルリポジトリ保護 | straight-base-dir配下以外のリポジトリはregraftしない | regraft時 |
| BR-04 | 現行バージョン保護 | 現在のEmacsバージョン用ELNは削除しない | ELN削除時 |

### 計算ロジック

**ビルド孤立判定**:
```elisp
(seq-filter #'file-directory-p
            (seq-remove (doom-rpartial #'gethash straight--profile-cache)
                        (straight--directory-files default-directory nil nil 'sort)))
```

**リポジトリ孤立判定**:
```elisp
(seq-remove (doom-rpartial #'straight--checkhash straight--repo-cache)
            rdirs)
```

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

本機能はデータベースを使用しない。ファイルシステムとstraightのキャッシュを操作。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 削除失敗 | パーミッションエラー | 手動で削除 |
| - | regraft失敗 | gitリポジトリが壊れている | リポジトリを削除して再取得 |

### リトライ仕様

特になし。削除に失敗した場合はエラーメッセージを表示して続行。

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

各削除操作は独立して実行され、一部が失敗しても他の処理は続行される。

## パフォーマンス要件

- ベンチマーク有効（:benchmark t）
- リポジトリ数に応じて処理時間が増加
- regraft処理は特に時間がかかる

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

- 削除対象のディレクトリがstraight管理下であることを確認
- ローカルリポジトリは保護される

## 備考

- doom sync --gcで呼び出し可能
- regraftはgitの履歴を圧縮するため、元に戻すことはできない

---

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

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

### 推奨読解順序

#### Step 1: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | gc.el | `lisp/cli/gc.el` | 17-126行目のヘルパー関数群 |

**主要処理フロー**:
- **17-23行目**: doom-gc--build - 単一ビルドの削除
- **25-32行目**: doom-gc--builds - 複数ビルドの削除
- **34-50行目**: doom-gc--elpa - ELPAパッケージの削除
- **52-60行目**: doom-gc--repo - 単一リポジトリの削除
- **62-69行目**: doom-gc--repos - 複数リポジトリの削除
- **71-86行目**: doom-gc--eln - ELNキャッシュの削除
- **88-111行目**: doom-gc--regraft-repo - 単一リポジトリの圧縮
- **113-125行目**: doom-gc--regraft-repos - 複数リポジトリの圧縮

#### Step 2: regraftロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | gc.el | `lisp/cli/gc.el` | 88-111行目のregraft処理 |

**読解のコツ**: regraftはgitの履歴を圧縮する処理。`git replace --graft HEAD`でHEADの親を切り離し、`git gc --prune=now`で不要なオブジェクトを削除する。

**主要処理フロー**:
- **93-98行目**: .gitの存在確認、ローカルリポジトリのスキップ
- **100-101行目**: git reset --hard, git clean -ffd
- **102-105行目**: git replace --graft HEAD, git reflog expire, git gc

#### Step 3: メインコマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | gc.el | `lisp/cli/gc.el` | 130-185行目のdefcli!定義 |

**主要処理フロー**:
- **130-135行目**: コマンド定義と引数パース
- **147-148行目**: パッケージ初期化
- **150行目**: straight-prune-build-cache呼び出し
- **151-165行目**: 削除対象の収集
- **166-184行目**: 各削除処理の実行

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

```
doom gc (defcli!)
    │
    ├─ doom-initialize-packages
    │
    ├─ doom-packages--barf-if-incomplete
    │
    ├─ straight-prune-build-cache
    │
    ├─ doom-gc--builds
    │      └─ doom-gc--build
    │             └─ delete-directory
    │
    ├─ doom-gc--elpa
    │      └─ delete-directory / delete-file
    │
    ├─ doom-gc--repos
    │      └─ doom-gc--repo
    │             ├─ delete-directory
    │             └─ delete-file (modified)
    │
    ├─ doom-gc--regraft-repos
    │      └─ doom-gc--regraft-repo
    │             ├─ doom-call-process "git" "reset"
    │             ├─ doom-call-process "git" "clean"
    │             ├─ doom-call-process "git" "replace"
    │             ├─ doom-call-process "git" "reflog"
    │             └─ doom-call-process "git" "gc"
    │
    └─ doom-gc--eln
           └─ delete-directory
```

### データフロー図

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

straight--profile-cache ───▶  孤立ビルド   ───▶  削除
                               検出
straight--repo-cache    ───▶  孤立リポジトリ ───▶  削除
                               検出
package-user-dir        ───▶  ELPA削除     ───▶  削除

straight--repos-dir     ───▶  regraft      ───▶  圧縮済み
                               処理             リポジトリ

doom-packages--eln-     ───▶  古いELN      ───▶  削除
output-path                   検出
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| gc.el | `lisp/cli/gc.el` | ソース | gcコマンドの主実装 |
| packages.el | `lisp/lib/packages.el` | ソース | パッケージ管理ライブラリ |
| doom-cli.el | `lisp/doom-cli.el` | ソース | CLIフレームワーク |
| sync.el | `lisp/cli/sync.el` | ソース | doom sync時のgc呼び出し |
