# 機能設計書 41-パス操作

## 概要

Julia Base ライブラリにおけるファイルシステムパスの構成・分解・正規化を提供する機能の設計書である。

### 本機能の処理概要

**業務上の目的・背景**：OS やファイルシステムによってパスの区切り文字や構造規則が異なるため、プラットフォーム非依存でパス操作を行うための統一 API が必要である。Julia プログラムがファイル I/O を行う際、パスの結合・分解・正規化は最も基本的かつ頻繁に使用される操作であり、OS 間の差異を吸収する抽象レイヤーとして本機能が存在する。

**機能の利用シーン**：スクリプトやパッケージがファイルを読み書きする前段階でパスを組み立てる場面、既存パスからディレクトリ名やファイル名・拡張子を抽出する場面、シンボリックリンクを解決して実際のファイルパスを得る場面など、あらゆるファイル操作の前処理として利用される。

**主要な処理内容**：
1. `joinpath` によるパス結合（可変長引数・Tuple 対応）
2. `splitpath` によるパス要素への分解
3. `splitdir` / `dirname` / `basename` によるディレクトリとファイル名の分離
4. `splitext` による拡張子の分離
5. `splitdrive` によるドライブレターの分離（Windows 対応）
6. `normpath` によるパスの正規化（`.` / `..` の解決）
7. `abspath` / `realpath` による絶対パス・実パスへの変換
8. `expanduser` による `~` の展開
9. `homedir` / `contractuser` によるホームディレクトリの取得・パスの短縮

**関連システム・外部連携**：OS のファイルシステム API（`libuv` 経由の `realpath` など）と連携する。Windows / Unix で条件コンパイルにより分岐するプラットフォーム依存コードを含む。

**権限による制御**：パス操作自体には権限制御はない。ただし `realpath` はファイルシステム上に実在するパスが必要であり、アクセス権限がないパスに対してはエラーが発生する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI / REPL | 主画面 | パス操作関数の対話的実行 |

## 機能種別

文字列操作 / ユーティリティ / プラットフォーム抽象化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | AbstractString | Yes | 操作対象のファイルパス文字列 | 空文字列も許容 |
| paths... | AbstractString | No | joinpath 等で結合する複数パス | 各要素が文字列であること |

### 入力データソース

ユーザーコードから文字列リテラルまたは変数として直接渡される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| path | String | 結合・正規化済みパス文字列 |
| (head, tail) | Tuple{String,String} | splitdir / splitext / splitdrive の分解結果 |
| parts | Vector{String} | splitpath による分解結果 |

### 出力先

関数の戻り値としてユーザーコードに返される。

## 処理フロー

### 処理シーケンス

```
1. パス文字列の受け取り
   └─ AbstractString として引数を受け取る
2. プラットフォーム判定
   └─ Sys.iswindows() に基づいて path_separator 等の定数を使い分け
3. パス操作の実行
   └─ 各関数ごとに文字列操作（findlast, SubString 等）を実施
4. 結果の返却
   └─ String または Tuple として返却
```

### フローチャート

```mermaid
flowchart TD
    A[パス文字列入力] --> B{joinpath?}
    B -->|Yes| C[path_separator で結合]
    B -->|No| D{splitdir/basename/dirname?}
    D -->|Yes| E[最後のセパレータ位置で分割]
    D -->|No| F{normpath?}
    F -->|Yes| G[./.. を解決して正規化]
    F -->|No| H{abspath/realpath?}
    H -->|Yes| I[pwd 付加 / libuv realpath 呼出]
    H -->|No| J[その他の操作]
    C --> K[結果返却]
    E --> K
    G --> K
    I --> K
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-41-01 | セパレータ正規化 | Windows では `/` と `\` の両方をセパレータとして扱う | Sys.iswindows() == true |
| BR-41-02 | 絶対パス判定 | 先頭が `/` (Unix) または `X:\` 等 (Windows) で始まるパスを絶対パスと判定 | isabspath 呼出時 |
| BR-41-03 | joinpath 末尾セパレータ | 前方パスの末尾にセパレータがある場合は重複させない | joinpath 呼出時 |
| BR-41-04 | normpath の `..` 解決 | ルート(`/`)より上に `..` で遡ることはできない | normpath 呼出時 |
| BR-41-05 | expanduser の `~` | `~` をホームディレクトリに展開する。`~user` はユーザーホームに展開 | expanduser 呼出時 |

### 計算ロジック

パス結合ではセパレータの重複回避のため、結合前に末尾・先頭のセパレータを確認し、必要に応じて挿入または省略する。normpath では `split` したパス要素をスタック的に処理し、`.` は無視、`..` は直前の要素を除去する。

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

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

該当なし。パス操作はインメモリの文字列操作であり、データベース操作を伴わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IOError | SystemError | realpath で存在しないパスを指定 | パスの存在確認後に呼び出す |
| ArgumentError | ArgumentError | homedir で HOME 環境変数が未設定 | HOME を設定するか引数でパスを指定 |

### リトライ仕様

パス操作は決定的な文字列操作であるため、リトライは不要。

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

該当なし。

## パフォーマンス要件

パス操作はすべてインメモリの文字列操作（realpath を除く）であり、O(n) の計算量（n はパス文字列長）で完了する。realpath のみファイルシステムアクセスを伴う。

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

- `realpath` はシンボリックリンクを解決するため、意図しないディレクトリへのアクセスを引き起こす可能性がある
- `expanduser` はホームディレクトリのパスを文字列として暴露するが、これは環境変数 HOME と同じ情報である

## 備考

- `path_separator` は OS 依存の定数として定義されている（Unix: `/`, Windows: `\`）
- `path_separator_re` は正規表現としてセパレータのマッチングに使用される
- `path_dir_splitter` はディレクトリ分割用の正規表現で、末尾セパレータの扱いも考慮されている

---

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

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

### 推奨読解順序

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

パス操作は主に文字列と正規表現で構成されるため、まず定数定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | path.jl | `base/path.jl` | **1-33行目**: `path_separator`, `path_separator_re`, `path_dir_splitter` 等のプラットフォーム依存定数を理解する |

**読解のコツ**: `@static if Sys.iswindows()` によるコンパイル時分岐が多用されている。Windows / Unix で正規表現パターンが異なる点に注意。

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

パス操作の主要な公開関数は `joinpath`, `splitpath`, `splitdir`, `basename`, `dirname`, `splitext`, `normpath`, `abspath`, `realpath`, `expanduser` である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | path.jl | `base/path.jl` | **35-55行目**: `splitdrive` - ドライブレター分離。Windows で複雑なロジック |
| 2-2 | path.jl | `base/path.jl` | **57-80行目**: `homedir` - ホームディレクトリ取得。libuv の `uv_os_homedir` を呼び出す |
| 2-3 | path.jl | `base/path.jl` | **82-116行目**: `isabspath` - 絶対パス判定 |

**主要処理フロー**:
1. **117-134行目**: `splitdir` がパス分割の基盤関数として動作
2. **136-144行目**: `dirname` / `basename` は `splitdir` のラッパー
3. **146-177行目**: `splitext` は最後の `.` で拡張子を分離
4. **179-256行目**: `joinpath` はセパレータを考慮してパスを結合
5. **258-310行目**: `normpath` は `..` や `.` を解決して正規化
6. **312-344行目**: `abspath` は `pwd()` を前置して絶対パス化
7. **346-366行目**: `realpath` は libuv 経由でシンボリックリンク解決

#### Step 3: ユーティリティ関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | path.jl | `base/path.jl` | **368-420行目**: `expanduser` - `~` 展開。Unix では `getpwnam` を使用 |
| 3-2 | path.jl | `base/path.jl` | **422-440行目**: `contractuser` - パスの `~` 短縮 |
| 3-3 | path.jl | `base/path.jl` | **442-480行目**: `splitpath` - パスを全要素に分解 |

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

```
joinpath(a, b)
    ├─ splitdrive(a)  ... ドライブレター判定
    ├─ isabspath(b)    ... 第2引数が絶対パスか判定
    └─ 文字列連結     ... path_separator を挟んで結合

normpath(path)
    ├─ splitdrive(path)
    ├─ split(path, path_separator_re)  ... 要素分割
    └─ join(parts, path_separator)     ... 再結合

abspath(path)
    ├─ isabspath(path)
    └─ joinpath(pwd(), path)

realpath(path)
    └─ ccall(:uv_fs_realpath, ...)     ... libuv 呼び出し

splitdir(path)
    ├─ splitdrive(path)
    └─ 正規表現マッチ(path_dir_splitter)

dirname(path)  ─── splitdir(path)[1]
basename(path) ─── splitdir(path)[2]
```

### データフロー図

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

パス文字列 ──────▶ splitdrive                  ──────▶ (drive, path)
パス文字列 ──────▶ splitdir                    ──────▶ (dir, base)
パス文字列 ──────▶ splitext                    ──────▶ (root, ext)
パス文字列 ──────▶ splitpath                   ──────▶ [parts...]
複数パス   ──────▶ joinpath ─▶ isabspath 判定  ──────▶ 結合済みパス
パス文字列 ──────▶ normpath ─▶ split ─▶ stack  ──────▶ 正規化パス
パス文字列 ──────▶ abspath ─▶ pwd() + joinpath ─────▶ 絶対パス
パス文字列 ──────▶ realpath ─▶ libuv           ──────▶ 実パス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| path.jl | `base/path.jl` | ソース | パス操作の全関数を定義 |
| file.jl | `base/file.jl` | ソース | パス操作の結果を使ったファイル操作 |
| stat.jl | `base/stat.jl` | ソース | パスからファイル情報を取得する機能 |
| sysimg.jl | `base/sysimg.jl` | ソース | path.jl の読み込み順序を制御 |
