# Pull Request Files API Reference

## List Changed Files in a PR

```
GET /repos/{owner}/{repo}/pulls/{index}/files
```

**Parameters:**

| Parameter  | Type   | Description                                          |
|------------|--------|------------------------------------------------------|
| skip-to    | string | Skip to a specific file path (for large diffs)       |
| whitespace | string | Whitespace handling: `ignore-all`, `ignore-change`, `ignore-eol`, `show-all` |
| page       | int    | Page number (1-based)                                |
| limit      | int    | Page size                                            |

```bash
# List all changed files
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/files"

# With pagination
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/files?page=1&limit=50"

# Ignore whitespace changes
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/files?whitespace=ignore-all"

# Skip to a specific file
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/files?skip-to=src/main.go"
```

### ChangedFile Response Fields

| Field             | Type   | Description                                           |
|-------------------|--------|-------------------------------------------------------|
| filename          | string | File path relative to repo root                       |
| status            | string | Change type: `added`, `modified`, `deleted`, `renamed` |
| additions         | int    | Lines added in this file                              |
| deletions         | int    | Lines deleted in this file                            |
| changes           | int    | Total lines changed (additions + deletions)           |
| previous_filename | string | Previous file path (only for renames)                 |
| contents_url      | string | API URL to fetch file contents                        |

**Example response:**

```json
[
  {
    "filename": "src/auth/handler.go",
    "status": "modified",
    "additions": 45,
    "deletions": 12,
    "changes": 57,
    "contents_url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/contents/src/auth/handler.go?ref={branch}"
  },
  {
    "filename": "src/auth/middleware.go",
    "status": "added",
    "additions": 80,
    "deletions": 0,
    "changes": 80,
    "contents_url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/contents/src/auth/middleware.go?ref={branch}"
  },
  {
    "filename": "src/old_auth.go",
    "status": "deleted",
    "additions": 0,
    "deletions": 150,
    "changes": 150,
    "contents_url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/contents/src/old_auth.go?ref={branch}"
  },
  {
    "filename": "src/auth/utils.go",
    "previous_filename": "src/helpers/auth_utils.go",
    "status": "renamed",
    "additions": 5,
    "deletions": 2,
    "changes": 7,
    "contents_url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/contents/src/auth/utils.go?ref={branch}"
  }
]
```

---

## List Commits in a PR

```
GET /repos/{owner}/{repo}/pulls/{index}/commits
```

**Parameters:**

| Parameter | Type | Description           |
|-----------|------|-----------------------|
| page      | int  | Page number (1-based) |
| limit     | int  | Page size             |

```bash
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/commits"

# With pagination
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/commits?page=1&limit=30"
```

Each commit in the response includes:

| Field                | Type   | Description                       |
|----------------------|--------|-----------------------------------|
| sha                  | string | Commit SHA                        |
| commit.message       | string | Commit message                    |
| commit.author.name   | string | Author name                       |
| commit.author.email  | string | Author email                      |
| commit.author.date   | string | Author date (ISO 8601)            |
| commit.committer     | object | Committer info (same structure)   |
| html_url             | string | Web URL for the commit            |
| parents              | array  | Parent commit SHAs                |

```bash
# Get commit messages for a PR
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/commits" | \
  jq '.[] | {sha: .sha[0:8], message: .commit.message | split("\n")[0], author: .commit.author.name}'
```

---

## Get Raw Diff

```
GET /repos/{owner}/{repo}/pulls/{index}.diff
```

Returns the raw unified diff as plain text (not JSON).

```bash
# Get raw diff
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}.diff"

# Save diff to a file
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}.diff" > pr-42.diff

# Count changed files from diff
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}.diff" | \
  grep -c '^diff --git'
```

---

## Get Patch Format

```
GET /repos/{owner}/{repo}/pulls/{index}.patch
```

Returns the patch in git-am compatible format (plain text, not JSON). Includes commit metadata (author, date, message) alongside the diff.

```bash
# Get patch
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}.patch"

# Save and apply patch locally
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}.patch" > pr-42.patch

git am pr-42.patch
```

---

## Compare Two Refs

```
GET /repos/{owner}/{repo}/compare/{basehead}
```

The `basehead` parameter uses the format `base...head` where each can be a branch name, tag, or commit SHA.

```bash
# Compare two branches
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/compare/{base}...{head}"

# Compare two commits
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/compare/{sha1}...{sha2}"

# Compare a tag with a branch
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/compare/v1.0.0...main"
```

The compare response includes:

| Field        | Type           | Description                          |
|--------------|----------------|--------------------------------------|
| commits      | array[Commit]  | List of commits between the two refs |
| total_commits | int           | Total number of commits              |

---

## Practical Examples

### Summarize PR Changes

```bash
#!/bin/bash
OWNER="{owner}"
REPO="{repo}"
PR_INDEX="{index}"

# Get changed files
FILES=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/${OWNER}/${REPO}/pulls/${PR_INDEX}/files")

echo "Changed files in PR #${PR_INDEX}:"
echo "$FILES" | jq -r '.[] | "\(.status | ascii_upcase)\t+\(.additions) -\(.deletions)\t\(.filename)"'

# Summary stats
echo ""
echo "--- Summary ---"
echo "Files changed: $(echo "$FILES" | jq 'length')"
echo "Total additions: $(echo "$FILES" | jq '[.[].additions] | add')"
echo "Total deletions: $(echo "$FILES" | jq '[.[].deletions] | add')"

# Breakdown by status
echo ""
echo "--- By status ---"
echo "Added:    $(echo "$FILES" | jq '[.[] | select(.status == "added")] | length')"
echo "Modified: $(echo "$FILES" | jq '[.[] | select(.status == "modified")] | length')"
echo "Deleted:  $(echo "$FILES" | jq '[.[] | select(.status == "deleted")] | length')"
echo "Renamed:  $(echo "$FILES" | jq '[.[] | select(.status == "renamed")] | length')"
```

### List Renames

```bash
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/files" | \
  jq '.[] | select(.status == "renamed") | "\(.previous_filename) -> \(.filename)"'
```

### Fetch Content of a Specific Changed File

```bash
# Get the contents_url from the changed file, then fetch it
CONTENTS_URL=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/pulls/{index}/files" | \
  jq -r '.[] | select(.filename == "src/main.go") | .contents_url')

# Fetch the file content (base64 encoded)
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "$CONTENTS_URL" | jq -r '.content' | base64 -d
```

### Check What Changed Between Base and PR Without a PR Object

```bash
# Useful for pre-PR analysis or comparing arbitrary refs
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/compare/{base}...{head}" | \
  jq '{
    total_commits: .total_commits,
    commits: [.commits[] | {sha: .sha[0:8], message: .commit.message | split("\n")[0]}]
  }'
```
