# 機能設計書 14-リポジトリ閲覧

## 概要

本ドキュメントは、GitLabにおけるリポジトリ閲覧機能の設計仕様を定義する。Gitリポジトリのファイル、ディレクトリ、ブランチ、タグの閲覧機能について、処理フロー、入出力仕様、ビジネスルールを記載する。

### 本機能の処理概要

リポジトリ閲覧機能は、GitLabプロジェクトのGitリポジトリ内のファイルツリーを閲覧する機能である。ユーザーはブランチやタグを選択し、任意の時点でのリポジトリ内容を確認できる。

**業務上の目的・背景**：開発者がソースコードやプロジェクトファイルを確認・理解するための基本機能。コードレビュー、ドキュメント参照、設定ファイル確認など、日常的な開発業務において必須の機能である。

**機能の利用シーン**：
- プロジェクトのディレクトリ構造を確認する場合
- 特定のブランチやタグのコードを閲覧する場合
- ファイルを編集する前に現在の内容を確認する場合
- コミット履歴と合わせてファイル変更を追跡する場合
- READMEやドキュメントを確認する場合

**主要な処理内容**：
1. リポジトリへのアクセス権限確認
2. 指定されたref（ブランチ/タグ/コミットSHA）の解決
3. 指定パスのツリー（ディレクトリ）またはBlobの取得
4. ファイル/ディレクトリ一覧の表示
5. 各エントリのコミット情報の取得（オプション）
6. シンタックスハイライト対応のファイル表示

**関連システム・外部連携**：
- Gitalyサーバーとの連携（Gitオブジェクト取得）
- LFS（Large File Storage）との連携

**権限による制御**：
- プロジェクトのread_code権限が必要
- プライベートプロジェクトはメンバーのみ閲覧可能
- 内部プロジェクトはログインユーザーのみ閲覧可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 30 | ファイルツリー | 主画面 | リポジトリのファイルツリー表示 |
| 31 | ファイル表示 | 遷移先画面 | 個別ファイルの内容表示 |

## 機能種別

参照操作（Read）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| namespace_id | String | Yes | 名前空間パス | 存在する名前空間 |
| project_id | String | Yes | プロジェクトパス | 存在するプロジェクト |
| id | String | No | ref/パス（例: main/src） | 有効なref |
| ref_type | String | No | refの種類（heads/tags） | heads/tags/nil |

### 入力データソース

- URLパラメータ：プロジェクト識別子、ref、パス
- セッション：認証ユーザー情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| tree | Gitlab::Git::Tree | ディレクトリエントリのコレクション |
| entries | Array | ファイル/ディレクトリの一覧 |
| commit | Gitlab::Git::Commit | 現在のコミット情報 |
| ref | String | 現在のref（ブランチ/タグ名） |

### 出力先

- 画面表示：ファイルツリーUI
- JSON API：ツリー情報のJSON

## 処理フロー

### 処理シーケンス

```
1. リクエスト受付
   └─ Projects::TreeController#showが呼び出される

2. 認証・認可チェック
   └─ authorize_read_code!で閲覧権限を確認

3. refとパスの抽出
   └─ ExtractsPath#assign_ref_varsでid（パス）からrefとパスを分離

4. コミットの取得
   └─ @repository.commit(@ref)で指定refのコミットを取得

5. ツリーの取得
   └─ @repository.tree(@commit.id, @path)でツリーを取得

6. レスポンス生成
   ├─ ツリーが空の場合
   │   ├─ Blobとして存在する場合 → blob_pathにリダイレクト
   │   └─ パスが無効な場合 → tree_rootにリダイレクト
   └─ ツリーが存在する場合 → ツリー表示
```

### フローチャート

```mermaid
flowchart TD
    A[リポジトリ閲覧リクエスト] --> B{プロジェクト存在?}
    B -->|No| C[404エラー]
    B -->|Yes| D{閲覧権限?}
    D -->|No| E[403エラー]
    D -->|Yes| F{空リポジトリ?}
    F -->|Yes| G[空リポジトリ表示]
    F -->|No| H[ref解決]
    H --> I{コミット存在?}
    I -->|No| C
    I -->|Yes| J[ツリー取得]
    J --> K{ツリー空?}
    K -->|Yes| L{Blob存在?}
    L -->|Yes| M[Blob表示へリダイレクト]
    L -->|No| N[ツリーrootへリダイレクト]
    K -->|No| O[ファイルツリー表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 閲覧権限 | read_code権限が必要 | 常時 |
| BR-02 | デフォルトブランチ | refが指定されない場合はデフォルトブランチを使用 | ref未指定時 |
| BR-03 | 曖昧なref解決 | ブランチとタグで同名がある場合はref_typeで区別 | 同名存在時 |
| BR-04 | パス解決 | 指定パスがディレクトリでなければBlobとして処理 | パス指定時 |
| BR-05 | 認証要求 | 非デフォルトブランチは認証要求される場合がある | 設定依存 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| プロジェクト取得 | projects | SELECT | プロジェクト情報の取得 |

### テーブル別操作詳細

#### Gitalyへのリクエスト

| 操作 | 内容 | 備考 |
|-----|------|------|
| FindCommit | 指定refのコミット取得 | - |
| GetTreeEntries | ツリーエントリ一覧取得 | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Not Found | プロジェクト/ref/パスが存在しない | 正しいURLを確認 |
| 403 | Forbidden | 閲覧権限がない | 権限を確認 |
| 503 | Service Unavailable | Gitalyサーバーエラー | 再試行 |

### リトライ仕様

- Gitalyサーバーエラー時、ユーザーに再試行を促す
- 自動リトライは行わない

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

- 読み取り専用操作のため、トランザクション管理は不要

## パフォーマンス要件

- allow_gitaly_ref_name_cachingによるキャッシュ有効化
- 大量ファイルを含むディレクトリでもレスポンス時間を維持
- コミット情報の遅延読み込み

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

- read_code権限の厳格なチェック
- パス トラバーサル攻撃の防止
- プライベートリポジトリの情報漏洩防止

## 備考

- LFSファイルは別途LFSサーバーから取得される
- 大きなファイルは表示制限がある場合がある

---

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

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

### 推奨読解順序

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

GitのツリーとBlobオブジェクトを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | tree.rb | `lib/gitlab/git/tree.rb` | Gitツリーオブジェクトの構造 |
| 1-2 | blob.rb | `lib/gitlab/git/blob.rb` | Gitブロブオブジェクトの構造 |

**読解のコツ**: Gitのツリーはディレクトリに相当し、Blobはファイル内容に相当する。

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

コントローラーのツリー表示処理を確認する。

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

**主要処理フロー**:
1. **11行目**: allow_gitaly_ref_name_cachingでキャッシュ有効化
2. **13-18行目**: before_actionでの認可・変数設定
3. **29-48行目**: showアクション、ツリー取得とリダイレクト処理
4. **68-70行目**: treeメソッド、リポジトリからツリー取得

#### Step 3: ref解決ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | extracts_path.rb | `app/controllers/concerns/extracts_path.rb` | refとパスの分離ロジック |

**主要処理フロー**:
- idパラメータからrefとパスを分離
- ブランチ/タグの曖昧さ解決
- @ref, @commit, @pathの設定

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

```
Projects::TreeController#show
    │
    ├─ authorize_read_code! (権限チェック)
    │
    ├─ assign_ref_vars (ExtractsPath)
    │      ├─ extract_ref (refとパスの分離)
    │      └─ @commit = @repository.commit(@ref)
    │
    └─ tree (ツリー取得)
           └─ @repository.tree(@commit.id, @path)
                  └─ Gitlab::Git::Repository#tree
                         └─ Gitaly::TreeService#get_tree_entries
```

### データフロー図

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

URL (ref/path) ───▶ TreeController ───▶ HTML/JSON
                          │
                          ▼
                    ExtractsPath
                    (ref解決)
                          │
                          ▼
                    Repository#tree
                          │
                          ▼
                    Gitaly RPC ───▶ ツリーエントリ
                          │
                          ▼
                    ファイルツリー表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tree_controller.rb | `app/controllers/projects/tree_controller.rb` | コントローラー | ツリー表示のエントリーポイント |
| extracts_path.rb | `app/controllers/concerns/extracts_path.rb` | Concern | refとパスの抽出 |
| repository.rb | `app/models/repository.rb` | モデル | リポジトリ操作のラッパー |
| tree.rb | `lib/gitlab/git/tree.rb` | Lib | Gitツリーオブジェクト |
| blob.rb | `lib/gitlab/git/blob.rb` | Lib | Gitブロブオブジェクト |
| tree_service.rb | `lib/gitlab/gitaly_client/tree_service.rb` | Lib | Gitalyクライアント |
