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:
@@ -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
|
||||
Reference in New Issue
Block a user