feat: add commit panel and file status indicators to repo workspace

- Add CommitPanel component for viewing changed files and committing
- Show file status indicators (M/A/D/?) in file tree
- Integrate git status with workspace for real-time updates
- Add CSS styles for commit panel and status badges

Part of git-control change implementation.
This commit is contained in:
Fusion
2026-05-19 15:00:25 +02:00
parent 762e0de44c
commit 875594d66d
21 changed files with 2242 additions and 73 deletions
+296
View File
@@ -0,0 +1,296 @@
# Git Control Specification
## Requirements
### Functional Requirements
1. **Branch Management**: Create, delete, list, and switch branches
2. **Working Directory**: View modified, added, deleted, and untracked files
3. **Commit Changes**: Stage and commit file changes with message
4. **Remote Sync**: Fetch, pull, and push to remote repositories
5. **Merge Branches**: Merge one branch into another
6. **Status Indicators**: Show file modification status in file tree
### Non-Functional Requirements
1. **Performance**: Git operations complete in < 3 seconds
2. **Feedback**: Show progress for long operations (push, pull, merge)
3. **Error Handling**: Clear error messages for all git failures
4. **Safety**: Confirm destructive operations (delete branch, force push)
## API Specification
### Branch Operations
#### POST /projects/{project_id}/repositories/{repo_id}/branches
Create a new branch.
**Request:**
```json
{
"name": "feature/new-thing",
"base_branch": "main"
}
```
**Response 201:**
```json
{
"name": "feature/new-thing",
"base_commit": "abc123"
}
```
**Response 400:** Branch already exists
#### DELETE /projects/{project_id}/repositories/{repo_id}/branches/{branch_name}
Delete a branch.
**Response 204:** Success
**Response 400:** Cannot delete current branch
#### POST /projects/{project_id}/repositories/{repo_id}/checkout
Checkout a branch.
**Request:**
```json
{
"branch": "feature/new-thing"
}
```
**Response 200:**
```json
{
"branch": "feature/new-thing",
"commit": "abc123"
}
```
**Response 400:** Uncommitted changes
### Status Operations
#### GET /projects/{project_id}/repositories/{repo_id}/status
Get working directory status.
**Response 200:**
```json
{
"branch": "main",
"ahead": 2,
"behind": 1,
"modified": ["src/main.py"],
"added": ["new-file.txt"],
"deleted": [],
"untracked": ["temp.log"],
"renamed": []
}
```
### Commit Operations
#### POST /projects/{project_id}/repositories/{repo_id}/commits
Commit staged changes.
**Request:**
```json
{
"message": "Update greeting",
"author_name": "User",
"author_email": "user@example.com"
}
```
**Response 201:**
```json
{
"hash": "def789",
"message": "Update greeting",
"branch": "main"
}
```
**Response 400:** Nothing to commit
### Remote Operations
#### POST /projects/{project_id}/repositories/{repo_id}/fetch
Fetch from remote.
**Response 200:**
```json
{
"success": true,
"fetched_branches": ["origin/main", "origin/develop"]
}
```
#### POST /projects/{project_id}/repositories/{repo_id}/pull
Pull updates from remote.
**Request:**
```json
{
"branch": "main"
}
```
**Response 200:**
```json
{
"success": true,
"commits": 3,
"files_changed": ["src/main.py", "README.md"]
}
```
**Response 409:** Merge conflict
#### POST /projects/{project_id}/repositories/{repo_id}/push
Push to remote.
**Request:**
```json
{
"branch": "main"
}
```
**Response 200:**
```json
{
"success": true,
"pushed_commits": 2
}
```
**Response 400:** Non-fast-forward
### Merge Operations
#### POST /projects/{project_id}/repositories/{repo_id}/merge
Merge branches.
**Request:**
```json
{
"source_branch": "feature/new-thing",
"target_branch": "main",
"commit_message": "Merge feature into main"
}
```
**Response 200:**
```json
{
"success": true,
"commit_hash": "abc789",
"files_changed": 5
}
```
**Response 409:** Merge conflict
## Data Model
### GitStatus
```typescript
interface GitStatus {
branch: string;
ahead: number;
behind: number;
modified: string[];
added: string[];
deleted: string[];
untracked: string[];
renamed: Array<{from: string, to: string}>;
}
```
### CommitInfo
```typescript
interface CommitInfo {
hash: string;
message: string;
branch: string;
author_name: string;
author_email: string;
date: string;
}
```
## Frontend Specification
### Components
**GitToolbar:**
- Fetch button
- Pull button (with behind count badge)
- Push button (with ahead count badge)
- Branch selector (with create/delete)
- Commit button (enabled when changes exist)
- Merge button
**BranchSelector:**
- Dropdown with all branches
- Current branch highlighted
- "Create new branch" option
- Delete option (with confirmation)
**CommitPanel:**
- Shows when files are modified
- Lists changed files with checkboxes
- Commit message input
- Commit button
**StatusIndicator:**
- Small badge on file tree items
- Shows modification type
### State Management
```typescript
interface GitControlState {
status: GitStatus | null;
isLoading: boolean;
operations: Array<{
type: string;
status: 'pending' | 'success' | 'error';
message: string;
}>;
}
```
## Error Handling
| Error Code | Description | User Action |
|------------|-------------|-------------|
| DIRTY_WORKING_TREE | Uncommitted changes | Commit or stash changes |
| MERGE_CONFLICT | Merge failed with conflicts | Resolve conflicts manually |
| NON_FAST_FORWARD | Push rejected | Pull first |
| AUTH_FAILED | Remote auth failed | Check SSH keys |
| BRANCH_EXISTS | Branch already exists | Choose different name |
| NOTHING_TO_COMMIT | Working tree clean | N/A |
| CANNOT_DELETE_CURRENT | Can't delete checked out branch | Switch branches first |
## Testing Strategy
### Backend Tests
- Test branch creation/deletion
- Test checkout with/without changes
- Test commit operations
- Test fetch/pull/push
- Test merge (fast-forward and conflict)
- Test error cases
### Frontend Tests
- Test toolbar buttons
- Test branch selector
- Test commit panel
- Test status indicators
- Test error handling
### Integration Tests
- Full workflow: create branch → edit file → commit → push → merge