# 機能設計書 16-ファイル編集

## 概要

本ドキュメントは、GitLabにおけるファイル編集機能の設計仕様を定義する。Web UIからリポジトリ内のファイルを編集する機能について、処理フロー、入出力仕様、ビジネスルールを記載する。

### 本機能の処理概要

ファイル編集機能は、GitリポジトリのファイルをWeb UI上で直接編集し、コミットする機能である。開発者はローカル環境を使わずに、軽微な修正やドキュメント更新を行うことができる。

**業務上の目的・背景**：ローカル環境のセットアップなしに、ブラウザから直接ファイルを編集できる利便性を提供。ドキュメント修正、設定ファイルの微調整、緊急のバグ修正などに活用される。

**機能の利用シーン**：
- README.mdやドキュメントの更新
- 設定ファイルの微調整
- コードレビュー時に発見した軽微な修正
- 緊急のホットフィックス適用
- 新しいブランチへの直接編集

**主要な処理内容**：
1. 編集権限の確認
2. ファイル内容の読み込みと編集UI表示
3. コンフリクト検出（last_commit_shaによる）
4. 編集内容のコミット作成
5. LFSファイルの変換（必要に応じて）

**関連システム・外部連携**：
- Gitalyサーバーとの連携（コミット作成）
- LFS（Large File Storage）との連携

**権限による制御**：
- プロジェクトへの書き込み権限（push_code）が必要
- 保護ブランチの場合は追加の権限チェック
- フォークプロジェクトへの編集（別ブランチへのコミット）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | ファイル編集 | 主画面 | ファイル内容の編集・コミット |
| 31 | ファイル表示 | 遷移元画面 | 編集画面への遷移 |

## 機能種別

CRUD操作（Update）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| namespace_id | String | Yes | 名前空間パス | 存在する名前空間 |
| project_id | String | Yes | プロジェクトパス | 存在するプロジェクト |
| id | String | Yes | ref/ファイルパス | 有効なref、存在するファイル |
| content | String | Yes | 編集後のファイル内容 | - |
| commit_message | String | Yes | コミットメッセージ | 空でないこと |
| branch_name | String | Yes | コミット先ブランチ | 有効なブランチ名 |
| last_commit_sha | String | No | 最終コミットSHA | コンフリクト検出用 |
| file_path | String | No | 新しいファイルパス | リネーム時 |

### 入力データソース

- 画面入力：ファイル内容、コミットメッセージ
- URLパラメータ：プロジェクト識別子、ref、ファイルパス

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| success | Boolean | 更新成功/失敗 |
| commit | Gitlab::Git::Commit | 作成されたコミット情報 |

### 出力先

- 画面表示：更新完了後、ファイル表示画面にリダイレクト
- Gitリポジトリ：新しいコミットの作成

## 処理フロー

### 処理シーケンス

```
1. 編集画面表示（editアクション）
   └─ BlobController#editが呼び出される
   └─ 編集権限とファイルサイズを確認
   └─ ファイル内容を読み込み、編集UIを表示

2. 更新リクエスト（updateアクション）
   └─ BlobController#updateが呼び出される

3. 権限チェック
   └─ authorize_edit_tree!で編集権限を確認

4. 変更検出
   └─ file_has_changed?で他のユーザーによる変更を検出

5. コミット作成
   └─ Files::UpdateService#execute
      └─ LFSファイル変換（必要時）
      └─ repository.update_file

6. 結果処理
   ├─ 成功: ファイル表示画面にリダイレクト
   └─ コンフリクト: 編集画面にエラー表示
```

### フローチャート

```mermaid
flowchart TD
    A[ファイル編集リクエスト] --> B{編集権限?}
    B -->|No| C[403エラー]
    B -->|Yes| D{ファイルサイズ?}
    D -->|> 10MB| E[ローカル編集を促す]
    D -->|<= 10MB| F[編集UI表示]
    F --> G[ユーザー編集]
    G --> H[コミットリクエスト]
    H --> I{コンフリクト検出?}
    I -->|Yes| J[コンフリクトエラー表示]
    I -->|No| K[コミット作成]
    K --> L{LFSファイル?}
    L -->|Yes| M[LFS変換]
    L -->|No| N[ファイル更新]
    M --> N
    N --> O[成功画面へリダイレクト]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 編集権限 | push_code権限が必要 | 常時 |
| BR-02 | ファイルサイズ制限 | 10MBを超えるファイルはWeb編集不可 | 常時 |
| BR-03 | コンフリクト検出 | 編集開始時と異なるコミットがある場合はエラー | 更新時 |
| BR-04 | コミットメッセージ必須 | コミットメッセージは必須 | 常時 |
| BR-05 | ブランチ指定必須 | コミット先ブランチは必須 | 常時 |
| BR-06 | LFS自動変換 | LFS対象ファイルは自動的にLFSに変換 | LFS対象時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 該当なし | - | - | Gitリポジトリへの直接操作 |

### Gitalyへのリクエスト

| 操作 | 内容 | 備考 |
|-----|------|------|
| GetBlob | ファイル内容取得 | 編集画面表示時 |
| UserCommitFiles | ファイル更新コミット | 更新時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 編集権限がない | 権限を確認 |
| - | コンフリクト | 他ユーザーが編集 | 最新内容を確認して再編集 |
| - | バリデーションエラー | コミットメッセージ空 | メッセージを入力 |
| - | サイズエラー | ファイルサイズ超過 | ローカルで編集 |

### リトライ仕様

- コンフリクト時は最新内容を取得して再編集

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

- Gitへのコミット作成は原子的に実行

## パフォーマンス要件

- ファイル読み込みは即時
- コミット作成は数秒以内

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

- 編集権限の厳格なチェック
- 保護ブランチへの書き込み制御
- コンフリクト検出による整合性確保

## 備考

- Web IDEを使用した編集も可能
- 複数ファイルの同時編集はWeb IDEを使用

---

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

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

### 推奨読解順序

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

コミットパラメータの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | base_service.rb | `app/services/files/base_service.rb` | ファイル操作の基本パラメータ |

**読解のコツ**: @file_path, @file_content, @commit_message等のインスタンス変数がコミットパラメータとなる。

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

コントローラーの編集処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | blob_controller.rb | `app/controllers/projects/blob_controller.rb` | edit/updateアクションの処理フロー |

**主要処理フロー**:
1. **87-98行目**: editアクション、権限とサイズチェック
2. **100-113行目**: updateアクション、Files::UpdateServiceの呼び出し
3. **294-297行目**: set_last_commit_sha、コンフリクト検出用

#### Step 3: ファイル更新サービスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | update_service.rb | `app/services/files/update_service.rb` | ファイル更新ロジック |

**主要処理フロー**:
- **5-11行目**: create_commit!、repository.update_fileの呼び出し
- **31-36行目**: validate!、コンフリクト検出

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

```
Projects::BlobController#edit
    │
    ├─ authorize_edit_tree! (権限チェック)
    │
    ├─ blob.raw_size > MAX_EDIT_SIZE? (サイズチェック)
    │
    └─ blob.load_all_data! (ファイル内容読み込み)

Projects::BlobController#update
    │
    ├─ authorize_edit_tree! (権限チェック)
    │
    └─ create_commit (CreatesCommit concern)
           └─ Files::UpdateService#execute
                  ├─ validate! (コンフリクト検出)
                  ├─ Lfs::FileTransformer#new_file (LFS変換)
                  └─ repository.update_file (ファイル更新)
```

### データフロー図

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

ファイル内容 ───▶ BlobController ───▶ 更新結果
コミットメッセージ      │
ブランチ名             ▼
               Files::UpdateService
                      │
                      ▼
               Lfs::FileTransformer
                      │
                      ▼
               Repository#update_file
                      │
                      ▼
               Gitaly RPC ───▶ 新コミット
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| blob_controller.rb | `app/controllers/projects/blob_controller.rb` | コントローラー | 編集のエントリーポイント |
| creates_commit.rb | `app/controllers/concerns/creates_commit.rb` | Concern | コミット作成処理 |
| update_service.rb | `app/services/files/update_service.rb` | サービス | ファイル更新処理 |
| base_service.rb | `app/services/files/base_service.rb` | サービス | ファイル操作基底クラス |
| file_transformer.rb | `app/services/lfs/file_transformer.rb` | サービス | LFSファイル変換 |
| repository.rb | `app/models/repository.rb` | モデル | リポジトリ操作 |
