# 機能設計書 11-doom sync

## 概要

本ドキュメントは、Doom Emacsのパッケージ同期コマンド「doom sync」の機能設計を定義する。このコマンドは、ユーザー設定とDoom Emacsの状態を同期し、パッケージのインストール・削除・再コンパイルを一括で行う中核的なCLIコマンドである。

### 本機能の処理概要

doom syncコマンドは、Doom Emacsのパッケージ管理において最も重要な同期処理を提供する。ユーザーが設定ファイルを変更した後、その変更をDoom Emacs環境に反映させるために使用される。

**業務上の目的・背景**：Doom Emacsはモジュール化された設定システムを採用しており、ユーザーがinit.elで有効化するモジュールを変更したり、packages.elでパッケージを追加・削除した場合、その変更を実際のEmacs環境に反映させる必要がある。doom syncはこの同期処理を自動化し、手動でのパッケージ管理の煩雑さを解消する。また、Emacsのバージョンアップやシステム変更時にバイトコードの互換性問題を検出し、自動的に再ビルドを促すことで、ユーザーが安定した環境を維持できるようにする。

**機能の利用シーン**：
- init.elでdoom!ブロックを変更してモジュールを追加・削除した後
- packages.elでpackage!宣言を追加・削除・変更した後
- モジュールのautoload関数を変更した後
- Doomをgit pullで手動更新した後
- Doom設定ディレクトリを別の場所に移動した後
- Emacsのバージョンをアップグレード・ダウングレードした後

**主要な処理内容**：
1. Emacsバージョンとシステムハッシュのチェック（前回sync時との差分検出）
2. 環境変数ファイル（envvar file）の再生成（オプション）
3. パッケージのインストール・削除（doom-packages-ensure）
4. パッケージの更新チェック（doom-packages-update）
5. ガベージコレクション（doom gc呼び出し）
6. プロファイルの再生成（doom-profile-generate）
7. 同期情報ファイルの更新

**関連システム・外部連携**：
- straight.el: パッケージ管理の基盤
- git: パッケージリポジトリの管理
- native-comp: ネイティブコンパイル機能（利用可能な場合）

**権限による制御**：特になし。ただし、--forceオプションでプロンプトを抑制可能。

## 関連画面

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

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

## 機能種別

バッチ処理 / パッケージ管理 / 設定同期

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -e | フラグ | No | 環境変数ファイルを再生成しない | - |
| -u | フラグ | No | インストール済みパッケージを更新する | - |
| -U | フラグ | No | パッケージを更新しない | - |
| --gc | フラグ | No | 孤立パッケージを削除しリポジトリを圧縮 | - |
| -j, --jobs | 数値 | No | ネイティブコンパイルに使用するスレッド数 | 正の整数 |
| -b, --rebuild | フラグ | No | 全パッケージを無条件に再ビルド | - |
| -B | フラグ | No | ホスト名やEmacsバージョン変更時も再ビルドしない | - |
| --aot | フラグ | No | パッケージを事前にネイティブコンパイル | - |

### 入力データソース

- `doom-sync-info-file`: 前回sync時のEmacsバージョンとシステムハッシュ
- `doom-env-file`: 環境変数ファイル
- ユーザー設定ファイル（init.el, packages.el, config.el）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 進捗メッセージ | 文字列 | 各処理ステップの状態表示 |
| 警告メッセージ | 文字列 | Emacsバージョン変更等の警告 |
| エラーメッセージ | 文字列 | 処理失敗時のエラー情報 |

### 出力先

- 標準出力: 進捗・結果メッセージ
- `doom-sync-info-file`: 同期情報（Emacsバージョン、システムハッシュ）
- `doom-env-file`: 環境変数ファイル（-eオプションなしの場合）
- プロファイルデータディレクトリ: 各種キャッシュファイル

## 処理フロー

### 処理シーケンス

```
1. プロファイル同期チェック
   └─ doom-profiles-bootloadable-pがtrueなら、profile sync --all --reloadを実行

2. before-syncフック実行
   └─ doom-before-sync-hookを実行

3. 中断警告フック登録
   └─ kill-emacs-hookにdoom-sync--abort-warning-hを追加

4. Emacsバージョン・システム変更チェック
   └─ doom-sync-info-fileから前回情報を読み取り
   └─ バージョン変更があれば警告表示
   └─ システムハッシュ変更があれば警告表示
   └─ 変更がありリビルドが必要な場合、ユーザーに確認

5. 環境変数ファイル再生成（オプション）
   └─ -eフラグがなく、doom-env-fileが存在する場合、doom envを呼び出し

6. パッケージ同期
   └─ doom-packages-ensureでパッケージのインストール・削除
   └─ doom-packages-updateでパッケージ更新チェック（-Uフラグなしの場合）

7. ガベージコレクション
   └─ doom gcコマンドを呼び出し

8. プロファイル再生成
   └─ doom-profile-generateでプロファイルを再生成
   └─ 他のEmacsプロセスが実行中なら再起動を促すメッセージ表示
   └─ doom-after-sync-hookを実行

9. 同期情報ファイル更新
   └─ 現在のEmacsバージョンとシステムハッシュを保存
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{プロファイル<br>ブータブル?}
    B -->|Yes| C[profile sync実行]
    B -->|No| D[before-syncフック]
    C --> D
    D --> E[中断警告フック登録]
    E --> F[同期情報読み込み]
    F --> G{バージョン<br>変更あり?}
    G -->|Yes| H[警告表示・リビルド確認]
    G -->|No| I{システム<br>変更あり?}
    H --> I
    I -->|Yes| J[警告表示・リビルド確認]
    I -->|No| K{envファイル<br>再生成?}
    J --> K
    K -->|Yes| L[doom env実行]
    K -->|No| M[パッケージ同期]
    L --> M
    M --> N[パッケージ更新]
    N --> O[doom gc実行]
    O --> P[プロファイル生成]
    P --> Q{他Emacs<br>実行中?}
    Q -->|Yes| R[再起動メッセージ]
    Q -->|No| S[after-syncフック]
    R --> S
    S --> T[同期情報保存]
    T --> U[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | バージョン変更時リビルド | Emacsのメジャーバージョンが変更された場合、バイトコード互換性のためパッケージの再ビルドが必要 | emacs-versionが前回syncと異なる場合 |
| BR-02 | システム変更時リビルド | システム構成が変更された場合（別マシンへの移行等）、パッケージの再ビルドが必要 | system-configurationまたはdoom-local-dirが変更された場合 |
| BR-03 | 環境変数ファイル自動再生成 | 既存のenvファイルがある場合のみ自動再生成 | doom-env-fileが存在し、-eフラグがない場合 |

### 計算ロジック

**システムハッシュ計算（doom-sync--system-hash）**:
```elisp
(secure-hash 'md5
  (mapconcat #'identity
    (list doom-local-dir system-configuration)
    ""))
```

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

本機能はデータベースを使用しない。ファイルベースでの状態管理を行う。

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 中断警告 | Ctrl+C等でスクリプトが中断された場合 | "doom sync"を再実行してDoomの状態を修復 |
| - | パッケージインストール失敗 | ネットワークエラー、依存関係エラー | エラーメッセージを確認し、ネットワーク接続を確認または手動で問題解決 |

### リトライ仕様

特になし。ユーザーが手動でdoom syncを再実行する。

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

トランザクション管理は行わない。各処理ステップは独立しており、中断した場合はdoom syncを再実行することで状態を回復できる。

## パフォーマンス要件

- --jobsオプションでネイティブコンパイルの並列度を制御可能
- デフォルトではCPUの最大スレッド数を使用
- MacOSでは遅延時間が調整される（company-idle-delay等）

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

- 環境変数ファイルには機密情報が含まれる可能性があるため、適切なファイルパーミッションで保存される
- doom-env-denyでセンシティブな環境変数を除外可能

## 備考

- sync実行中に他のEmacsプロセスが動作している場合、変更を反映させるには再起動が必要
- --aotオプションは、ネイティブコンパイルが利用可能な場合のみ効果がある

---

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

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

### 推奨読解順序

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

まず、同期処理で使用される変数と状態管理の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sync.el | `lisp/cli/sync.el` | doom-after-sync-hook, doom-before-sync-hook, doom-sync-info-fileの定義 |

**読解のコツ**: `defvar`で定義されるフック変数は、処理の拡張ポイントを示している。doom-sync-info-fileはプロファイルデータディレクトリ配下の"sync"ファイルを指す。

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

CLIコマンドの定義と引数処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sync.el | `lisp/cli/sync.el` | defcli!マクロによるsyncコマンド定義 |

**主要処理フロー**:
1. **24-33行目**: defcli!によるコマンド定義、引数パース
2. **59-63行目**: --aotと--jobsオプションの処理
3. **64-71行目**: 他のEmacsプロセスの検出
4. **72-73行目**: プロファイル同期の呼び出し
5. **74行目**: before-syncフックの実行
6. **75行目**: 中断警告フックの登録

#### Step 3: バージョン・システム変更検出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sync.el | `lisp/cli/sync.el` | 85-103行目のpcase-let処理 |

**主要処理フロー**:
- **85-87行目**: 前回sync情報の読み込み
- **88-90行目**: Emacsバージョン変更の検出
- **91-94行目**: システムハッシュ変更の検出
- **95-103行目**: リビルド確認プロンプト

#### Step 4: パッケージ同期処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sync.el | `lisp/cli/sync.el` | 104-119行目の同期処理 |
| 4-2 | packages.el | `lisp/lib/packages.el` | doom-packages-ensure, doom-packages-update関数 |

**主要処理フロー**:
- **104-106行目**: envファイル再生成
- **107行目**: doom-packages-ensureでパッケージ同期
- **108行目**: doom-packages-updateで更新チェック
- **109行目**: doom gcの呼び出し
- **110-113行目**: プロファイル生成とafter-syncフック

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sync.el | `lisp/cli/sync.el` | 125-142行目のヘルパー関数 |

**主要処理フロー**:
- **125-138行目**: doom-sync--system-hash - システム構成のハッシュ計算
- **140-142行目**: doom-sync--abort-warning-h - 中断時の警告メッセージ

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

```
doom sync (defcli!)
    │
    ├─ doom-profiles-bootloadable-p
    │      └─ call! '(profile sync "--all" "--reload")
    │
    ├─ run-hooks 'doom-before-sync-hook
    │
    ├─ doom-file-read (doom-sync-info-file)
    │
    ├─ doom-sync--system-hash
    │      └─ secure-hash 'md5
    │
    ├─ call! '(env)
    │
    ├─ doom-packages-ensure
    │      └─ straight.el API
    │
    ├─ doom-packages-update
    │      └─ straight.el API
    │
    ├─ call! '(gc ...)
    │      └─ doom-gc-* 関数群
    │
    ├─ doom-profile-generate
    │
    └─ run-hooks 'doom-after-sync-hook
```

### データフロー図

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

doom-sync-info-file   ───▶  バージョン比較  ───▶  警告メッセージ
(前回sync情報)                   │
                                 │
ユーザー設定ファイル  ───▶  パッケージ解析  ───▶  パッケージ
(init.el, packages.el)           │                インストール/削除
                                 │
straight repos        ───▶  パッケージ更新  ───▶  更新済みパッケージ
                                 │
                                 │
system-configuration  ───▶  システムハッシュ ───▶  doom-sync-info-file
doom-local-dir              計算・保存           (更新)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sync.el | `lisp/cli/sync.el` | ソース | syncコマンドの主実装 |
| packages.el | `lisp/lib/packages.el` | ソース | パッケージ管理ライブラリ |
| env.el | `lisp/cli/env.el` | ソース | 環境変数ファイル生成 |
| gc.el | `lisp/cli/gc.el` | ソース | ガベージコレクション |
| profiles.el | `lisp/lib/profiles.el` | ソース | プロファイル管理 |
| doom-cli.el | `lisp/doom-cli.el` | ソース | CLIフレームワーク（defcli!マクロ定義） |
