# 機能設計書 17-ファイル作成

## 概要

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

### 本機能の処理概要

ファイル作成機能は、GitリポジトリにWeb UI上で新しいファイルを作成し、コミットする機能である。開発者はローカル環境を使わずに、新規ファイルの追加を行うことができる。

**業務上の目的・背景**：ローカル環境のセットアップなしに、ブラウザから直接新規ファイルを作成できる利便性を提供。README追加、設定ファイル作成、ドキュメント追加などに活用される。

**機能の利用シーン**：
- 新規プロジェクトにREADME.mdを追加する場合
- 設定ファイル（.gitignore、.gitlab-ci.yml等）を追加する場合
- 新しいドキュメントファイルを作成する場合
- テンプレートから新規ファイルを作成する場合

**主要な処理内容**：
1. 作成権限の確認
2. 新規ファイル作成UIの表示
3. ファイル内容の入力
4. コミット作成
5. LFSファイルの変換（必要に応じて）

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

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 32 | ファイル新規作成 | 主画面 | 新規ファイルの作成・コミット |
| 30 | ファイルツリー | 遷移元画面 | 作成画面への遷移 |

## 機能種別

CRUD操作（Create）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| namespace_id | String | Yes | 名前空間パス | 存在する名前空間 |
| project_id | String | Yes | プロジェクトパス | 存在するプロジェクト |
| file_name | String | Yes | ファイル名 | 有効なファイル名 |
| content | String | Yes | ファイル内容 | - |
| commit_message | String | Yes | コミットメッセージ | 空でないこと |
| branch_name | String | Yes | コミット先ブランチ | 有効なブランチ名 |
| file / file_path | String | No | ファイルパス（ディレクトリ含む） | 有効なパス |

### 入力データソース

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

## 出力仕様

### 出力データ

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

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 新規作成画面表示（newアクション）
   └─ BlobController#newが呼び出される
   └─ 作成権限を確認
   └─ 新規作成UIを表示

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

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

4. ファイルパス検証
   └─ file_pathの組み立て（ディレクトリ + ファイル名）

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

6. 結果処理
   ├─ 成功: ファイル表示画面にリダイレクト
   └─ 失敗: 新規作成画面にエラー表示
```

### フローチャート

```mermaid
flowchart TD
    A[ファイル作成リクエスト] --> B{作成権限?}
    B -->|No| C[403エラー]
    B -->|Yes| D[新規作成UI表示]
    D --> E[ユーザー入力]
    E --> F[コミットリクエスト]
    F --> G{ファイルパス有効?}
    G -->|No| H[バリデーションエラー]
    G -->|Yes| I{コミットメッセージ有効?}
    I -->|No| H
    I -->|Yes| J[コミット作成]
    J --> K{LFSファイル?}
    K -->|Yes| L[LFS変換]
    K -->|No| M[ファイル作成]
    L --> M
    M --> N[成功画面へリダイレクト]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 作成権限 | push_code権限が必要 | 常時 |
| BR-02 | ファイルパス必須 | ファイルパスは必須 | 常時 |
| BR-03 | コミットメッセージ必須 | コミットメッセージは必須 | 常時 |
| BR-04 | ブランチ指定必須 | コミット先ブランチは必須 | 常時 |
| BR-05 | LFS自動変換 | LFS対象ファイルは自動的にLFSに変換 | LFS対象時 |
| BR-06 | 重複ファイル禁止 | 同一パスにファイルが存在する場合はエラー | 常時 |

### 計算ロジック

該当なし

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

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

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

### Gitalyへのリクエスト

| 操作 | 内容 | 備考 |
|-----|------|------|
| UserCommitFiles | ファイル作成コミット | 作成時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 作成権限がない | 権限を確認 |
| - | バリデーションエラー | ファイルパス不正 | パスを修正 |
| - | バリデーションエラー | コミットメッセージ空 | メッセージを入力 |
| - | 重複エラー | ファイルが既に存在 | 別のパスを指定 |

### リトライ仕様

- エラー時は入力内容を修正して再試行

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

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

## パフォーマンス要件

- コミット作成は数秒以内

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

- 作成権限の厳格なチェック
- 保護ブランチへの書き込み制御
- パス トラバーサル攻撃の防止

## 備考

- 空リポジトリの場合、最初のファイル作成でデフォルトブランチが作成される
- ファイルアップロード機能と統合されている

---

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

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

### 推奨読解順序

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

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

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

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

コントローラーの作成処理を確認する。

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

**主要処理フロー**:
1. **57-59行目**: newアクション、作成UI表示
2. **61-69行目**: createアクション、Files::CreateServiceの呼び出し

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

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

**主要処理フロー**:
- **5-11行目**: create_commit!、repository.create_fileの呼び出し
- **15-18行目**: validate!、ファイルパス検証

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

```
Projects::BlobController#new
    │
    ├─ authorize_edit_tree! (権限チェック)
    │
    └─ 新規作成UI表示

Projects::BlobController#create
    │
    ├─ authorize_edit_tree! (権限チェック)
    │
    └─ create_commit (CreatesCommit concern)
           └─ Files::CreateService#execute
                  ├─ validate! (パス検証)
                  ├─ Lfs::FileTransformer#new_file (LFS変換)
                  └─ repository.create_file (ファイル作成)
```

### データフロー図

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

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

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| blob_controller.rb | `app/controllers/projects/blob_controller.rb` | コントローラー | 作成のエントリーポイント |
| creates_commit.rb | `app/controllers/concerns/creates_commit.rb` | Concern | コミット作成処理 |
| create_service.rb | `app/services/files/create_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` | モデル | リポジトリ操作 |
