6807f449b7
- Create git file utilities (list_tree, get_file_content, list_branches, commit_file) - Add file browsing API endpoints (list, content, branches, update) - Create RepoWorkspace page with sidebar + main content layout - Add FileTree component with directory navigation - Add FileViewer component for viewing file contents - Update project list to link to workspace - Add workspace CSS styles - Update router with workspace route Quality gates: ruff ✓, mypy ✓, typecheck ✓, build ✓
214 lines
4.7 KiB
Markdown
214 lines
4.7 KiB
Markdown
# Git History Visualization Specification
|
|
|
|
## Requirements
|
|
|
|
### Functional Requirements
|
|
|
|
1. **View Commit History**: Display all commits in a repository
|
|
2. **Graph Visualization**: Show commits as nodes with branch/merge lines
|
|
3. **List View**: Alternative linear view of commits
|
|
4. **Commit Details**: Click to view full commit info and diff
|
|
5. **Branch Display**: Show branch names on commits
|
|
6. **Tag Display**: Show tags on commits
|
|
7. **View Toggle**: Switch between graph and list views
|
|
|
|
### Non-Functional Requirements
|
|
|
|
1. **Performance**: Load first 100 commits in < 2 seconds
|
|
2. **Responsiveness**: Graph should render smoothly up to 500 commits
|
|
3. **Compatibility**: Work with bare repositories and mirror clones
|
|
4. **Read-only**: No write operations to repository
|
|
|
|
## API Specification
|
|
|
|
### GET /projects/{project_id}/repositories/{repo_id}/history
|
|
|
|
Retrieve commit history for a repository.
|
|
|
|
**Query Parameters:**
|
|
| Parameter | Type | Default | Description |
|
|
|-----------|------|---------|-------------|
|
|
| view | string | "graph" | "graph" or "list" |
|
|
| branch | string | null | Filter by branch name |
|
|
| limit | integer | 100 | Max commits to return |
|
|
| offset | integer | 0 | Skip first N commits |
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"commits": [
|
|
{
|
|
"hash": "full-sha-hash",
|
|
"short_hash": "abc1234",
|
|
"parents": ["parent-hash-1", "parent-hash-2"],
|
|
"author": "John Doe",
|
|
"email": "john@example.com",
|
|
"date": "2026-05-19",
|
|
"timestamp": 1716123456,
|
|
"message": "feat: add new feature",
|
|
"branches": ["main"],
|
|
"tags": []
|
|
}
|
|
],
|
|
"branches": ["main", "develop", "feature/x"],
|
|
"total_commits": 250,
|
|
"graph_data": {
|
|
"nodes": [
|
|
{
|
|
"hash": "abc1234",
|
|
"x": 0,
|
|
"y": 0,
|
|
"column": 0
|
|
}
|
|
],
|
|
"edges": [
|
|
{
|
|
"from_hash": "abc1234",
|
|
"to_hash": "def5678",
|
|
"type": "parent"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### GET /projects/{project_id}/repositories/{repo_id}/commits/{commit_hash}
|
|
|
|
Get detailed information about a specific commit.
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"hash": "full-sha-hash",
|
|
"short_hash": "abc1234",
|
|
"parents": ["parent-hash"],
|
|
"author": "John Doe",
|
|
"email": "john@example.com",
|
|
"date": "2026-05-19",
|
|
"timestamp": 1716123456,
|
|
"message": "feat: add new feature",
|
|
"body": "Detailed description here",
|
|
"stats": {
|
|
"files_changed": 3,
|
|
"insertions": 45,
|
|
"deletions": 12
|
|
},
|
|
"files": [
|
|
{
|
|
"path": "src/main.py",
|
|
"change_type": "modified",
|
|
"insertions": 20,
|
|
"deletions": 5,
|
|
"diff": "diff content here"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Frontend Components
|
|
|
|
### GitHistoryPage
|
|
Main page component that orchestrates the view.
|
|
|
|
### GraphView
|
|
SVG-based commit graph visualization.
|
|
|
|
**Props:**
|
|
- `commits`: Commit[]
|
|
- `graphData`: GraphData
|
|
- `selectedCommit`: string | null
|
|
- `onCommitSelect`: (hash: string) => void
|
|
|
|
### ListView
|
|
Linear commit list.
|
|
|
|
**Props:**
|
|
- `commits`: Commit[]
|
|
- `selectedCommit`: string | null
|
|
- `onCommitSelect`: (hash: string) => void
|
|
|
|
### CommitDetails
|
|
Panel showing commit details and diff.
|
|
|
|
**Props:**
|
|
- `commit`: CommitDetail | null
|
|
|
|
### DiffViewer
|
|
Component to display git diff with syntax highlighting.
|
|
|
|
**Props:**
|
|
- `files`: FileChange[]
|
|
|
|
## Data Models
|
|
|
|
### Commit
|
|
```typescript
|
|
interface Commit {
|
|
hash: string;
|
|
short_hash: string;
|
|
parents: string[];
|
|
author: string;
|
|
email: string;
|
|
date: string;
|
|
timestamp: number;
|
|
message: string;
|
|
branches: string[];
|
|
tags: string[];
|
|
}
|
|
```
|
|
|
|
### CommitDetail
|
|
```typescript
|
|
interface CommitDetail extends Commit {
|
|
body: string;
|
|
stats: {
|
|
files_changed: number;
|
|
insertions: number;
|
|
deletions: number;
|
|
};
|
|
files: FileChange[];
|
|
}
|
|
```
|
|
|
|
### FileChange
|
|
```typescript
|
|
interface FileChange {
|
|
path: string;
|
|
change_type: "added" | "modified" | "deleted" | "renamed";
|
|
insertions: number;
|
|
deletions: number;
|
|
diff: string;
|
|
}
|
|
```
|
|
|
|
## URL Structure
|
|
|
|
```
|
|
/projects/:projectId/repositories/:repoId/history
|
|
```
|
|
|
|
## Error Codes
|
|
|
|
| Error Code | Description | User Message |
|
|
|------------|-------------|--------------|
|
|
| REPO_EMPTY | Repository has no commits | "This repository has no commits yet" |
|
|
| GIT_ERROR | Git command failed | "Failed to load repository history" |
|
|
| COMMIT_NOT_FOUND | Commit hash not found | "Commit not found" |
|
|
| INVALID_BRANCH | Branch doesn't exist | "Branch not found" |
|
|
|
|
## Testing Strategy
|
|
|
|
### Backend Tests
|
|
- Test git log parsing with various repo structures
|
|
- Test commit detail extraction
|
|
- Test error handling for empty repos
|
|
|
|
### Frontend Tests
|
|
- Test graph rendering with sample data
|
|
- Test list view rendering
|
|
- Test commit selection and details display
|
|
- Test view toggle
|
|
|
|
### Integration Tests
|
|
- End-to-end flow: load history → select commit → view details
|