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
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-05-19
+273
View File
@@ -0,0 +1,273 @@
# Git Control - Design
## Architecture
```
Repository Workspace
├─ Toolbar
│ ├─ [Fetch] [Pull] [Push]
│ ├─ [Branch: main ▼] [+ New Branch]
│ └─ [Commit] [Merge ▼]
├─ Sidebar
│ ├─ Repo Selector
│ ├─ Branch Selector (with management)
│ └─ File Tree (with status icons)
│ ├─ 📄 main.py ✏️ (modified)
│ ├─ 📁 src/
│ └─ 📄 README.md ✨ (new)
└─ Main Content
├─ File Viewer (with edit/save)
└─ Commit Panel (when files modified)
├─ Changed files list
├─ Commit message input
└─ [Commit to main] button
```
## Git Operations
### Branch Operations
**Create Branch:**
```
POST /projects/{id}/repositories/{id}/branches
{
"name": "feature/new-thing",
"base_branch": "main"
}
```
**Delete Branch:**
```
DELETE /projects/{id}/repositories/{id}/branches/{name}
```
**Checkout Branch:**
```
POST /projects/{id}/repositories/{id}/checkout
{
"branch": "feature/new-thing"
}
```
### Working Directory Status
**Get Status:**
```
GET /projects/{id}/repositories/{id}/status
```
Response:
```json
{
"branch": "main",
"modified": ["src/main.py", "README.md"],
"added": ["new-file.txt"],
"deleted": ["old-file.txt"],
"untracked": ["temp.log"]
}
```
### Commit Operations
**Commit Changes:**
```
POST /projects/{id}/repositories/{id}/commits
{
"message": "Update greeting",
"author_name": "User",
"author_email": "user@example.com",
"files": ["src/main.py", "README.md"]
}
```
### Remote Operations
**Fetch:**
```
POST /projects/{id}/repositories/{id}/fetch
```
**Pull:**
```
POST /projects/{id}/repositories/{id}/pull
{
"branch": "main",
"strategy": "merge"
}
```
**Push:**
```
POST /projects/{id}/repositories/{id}/push
{
"branch": "main"
}
```
**Merge:**
```
POST /projects/{id}/repositories/{id}/merge
{
"source_branch": "feature/new-thing",
"target_branch": "main",
"commit_message": "Merge feature into main"
}
```
## Backend Implementation
### Git Command Utilities
Extend `src/utils/git_files.py` with:
- `get_status(repo_path)` - working directory status
- `create_branch(repo_path, name, base)` - create new branch
- `delete_branch(repo_path, name)` - delete branch
- `checkout_branch(repo_path, name)` - switch branch
- `commit_changes(repo_path, files, message, author)` - commit files
- `fetch(repo_path)` - fetch from remote
- `pull(repo_path, branch)` - pull updates
- `push(repo_path, branch)` - push changes
- `merge(repo_path, source, target, message)` - merge branches
### Error Handling
All git operations can fail:
- **Merge conflicts**: Return conflict details, require resolution
- **Auth failures**: Remote requires authentication
- **Dirty working tree**: Can't checkout with uncommitted changes
- **Branch exists**: Can't create duplicate branch
- **Nothing to commit**: Working tree clean
### Security
- All operations check repository ownership
- Push/pull requires valid remote URL
- Commits use authenticated user's identity
## Frontend Implementation
### Workspace Toolbar
Add git action bar above file viewer:
```
┌──────────────────────────────────────────────────────┐
│ [Fetch] [Pull] [Push] │ Branch: [main ▼] [+ New] │
│ │ [Commit ▼] [Merge ▼] │
└──────────────────────────────────────────────────────┘
```
### Branch Management
**Branch Selector Dropdown:**
- List all branches with current branch highlighted
- Create new branch option (opens dialog)
- Delete branch option (with confirmation)
**New Branch Dialog:**
```
┌──────────────────────────────┐
│ Create New Branch │
├──────────────────────────────┤
│ Name: [feature/________] │
│ Base: [main ▼] │
│ │
│ [Create] [Cancel] │
└──────────────────────────────┘
```
### Working Directory Status
**Status Indicators in File Tree:**
- ✏️ Modified file
- ✨ New file
- 🗑️ Deleted file
- ❓ Untracked file
**Commit Panel (appears when files modified):**
```
┌──────────────────────────────┐
│ Changes (3) │
├──────────────────────────────┤
│ ✏️ src/main.py │
│ ✨ new-file.txt │
│ 🗑️ old-file.txt │
├──────────────────────────────┤
│ Commit message: │
│ [____________________] │
│ │
│ [Commit to main] │
└──────────────────────────────┘
```
### Merge Dialog
```
┌──────────────────────────────┐
│ Merge Branch │
├──────────────────────────────┤
│ Source: [feature/xyz ▼] │
│ Target: main │
│ │
│ Commit message: │
│ [Merge feature/xyz into main]│
│ │
│ [Merge] [Cancel] │
└──────────────────────────────┘
```
## Implementation Order
1. **Backend git utilities** - Status, branch, commit, remote operations
2. **Backend API endpoints** - All git operation endpoints
3. **Frontend toolbar** - Git action buttons
4. **Frontend branch management** - Create/delete/checkout
5. **Frontend status display** - Modified file indicators
6. **Frontend commit panel** - Commit UI
7. **Frontend merge dialog** - Merge UI
8. **Integration** - Wire everything together
9. **Tests** - Backend + frontend tests
## State Management
### URL State
```
/projects/:projectId?repo=:repoId&branch=:branch&path=:path
```
### React State
```typescript
interface GitState {
currentBranch: string;
branches: Branch[];
status: {
modified: string[];
added: string[];
deleted: string[];
untracked: string[];
};
isLoading: boolean;
lastOperation: string | null;
}
```
## Error Handling
### User-Facing Errors
- **"Cannot checkout: uncommitted changes"** - Show commit panel
- **"Merge conflict"** - Show conflict resolution UI
- **"Push rejected: non-fast-forward"** - Suggest pull first
- **"Authentication failed"** - Show SSH key settings
- **"Nothing to commit"** - Working tree clean
### Conflict Resolution (Future)
For now, show error and abort. Later can add:
- Diff view of conflicts
- Manual resolution editor
- Accept ours/theirs buttons
## Performance Considerations
- **Status updates**: Poll every 5 seconds when viewing workspace
- **Fetch on load**: Auto-fetch when opening workspace (optional)
- **Lazy operations**: Don't fetch until user clicks fetch/pull
- **Progress indicators**: Show for long operations (clone, push, merge)
+44
View File
@@ -0,0 +1,44 @@
# Git Control Features
## Problem
The repository workspace currently provides read-only access to git repositories. Users can browse files, view history, and see branches, but cannot perform git operations like creating branches, committing changes, pushing/pulling, or merging.
## Solution
Add git control capabilities to the repository workspace, allowing users to:
1. Create and delete branches
2. Switch between branches (checkout)
3. Commit changes (for quick edits)
4. Push changes to remote
5. Pull/fetch updates from remote
6. Merge branches
7. View working directory status
## Benefits
- **Complete workflow**: Users can make small changes without leaving the browser
- **Quick iterations**: Fix typos, update configs, make small adjustments
- **Branch management**: Create feature branches, merge when done
- **Remote sync**: Keep repositories up to date
- **No external tools needed**: Everything in the browser
## Scope
### What stays:
- Existing file browser and viewer
- Git history visualization
- Repository management (create/delete)
### What's new:
- Branch CRUD operations
- Working directory status (modified files)
- Commit operations
- Push/pull/fetch
- Merge capabilities
- Git action toolbar in workspace
### What changes:
- Workspace toolbar gets git action buttons
- File viewer gets "modified" indicators
- Branch selector gets management options
+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
+142
View File
@@ -0,0 +1,142 @@
# Git Control - Tasks
## Phase 1: Backend Git Utilities
- [x] **Task 1.1**: Extend git utilities
- Add to `src/utils/git_control.py`:
- `get_status(repo_path)` - working directory status
- `create_branch(repo_path, name, base)` - create branch
- `delete_branch(repo_path, name)` - delete branch
- `checkout_branch(repo_path, name)` - switch branch
- `commit_changes(repo_path, message, author)` - commit
- Add tests
- [x] **Task 1.2**: Add remote operations
- Add to `src/utils/git_control.py`:
- `fetch(repo_path)` - fetch from remote
- `pull(repo_path, branch)` - pull updates
- `push(repo_path, branch)` - push changes
- `merge(repo_path, source, target, message)` - merge
- Handle errors (conflicts, auth, etc.)
- Add tests
## Phase 2: Backend API Endpoints
- [x] **Task 2.1**: Branch management endpoints
- POST `/projects/{id}/repositories/{id}/branches` - create
- DELETE `/projects/{id}/repositories/{id}/branches/{name}` - delete
- POST `/projects/{id}/repositories/{id}/checkout` - checkout
- Add to `src/api/git_repositories.py`
- [x] **Task 2.2**: Status endpoint
- GET `/projects/{id}/repositories/{id}/status`
- Returns working directory status
- [x] **Task 2.3**: Commit endpoint
- POST `/projects/{id}/repositories/{id}/commits`
- Commits all staged changes
- [x] **Task 2.4**: Remote operation endpoints
- POST `/projects/{id}/repositories/{id}/fetch`
- POST `/projects/{id}/repositories/{id}/pull`
- POST `/projects/{id}/repositories/{id}/push`
- [x] **Task 2.5**: Merge endpoint
- POST `/projects/{id}/repositories/{id}/merge`
- Handle conflict responses
## Phase 3: Frontend Git Toolbar
- [ ] **Task 3.1**: Create GitToolbar component
- Fetch, Pull, Push buttons
- Branch selector with count badges
- Commit button
- Merge button
- Add to workspace layout
- [ ] **Task 3.2**: Add status polling
- Poll status every 5 seconds
- Update toolbar badges (ahead/behind)
- Show commit button when changes exist
## Phase 4: Branch Management
- [ ] **Task 4.1**: Enhance BranchSelector
- Add "Create new branch" option
- Add delete option with confirmation
- Show current branch
- Call branch API endpoints
- [ ] **Task 4.2**: Create NewBranchDialog
- Branch name input
- Base branch selector
- Create/Cancel buttons
## Phase 5: Commit Workflow
- [ ] **Task 5.1**: Create CommitPanel component
- Shows when files are modified
- Lists changed files
- Commit message input
- Commit button
- Success/error feedback
- [ ] **Task 5.2**: Add status indicators to FileTree
- Modified icon (✏️)
- New file icon (✨)
- Deleted icon (🗑️)
- Untracked icon (❓)
## Phase 6: Remote Operations
- [ ] **Task 6.1**: Implement fetch/pull/push
- Wire toolbar buttons to API
- Show progress indicators
- Handle errors (auth, conflicts, etc.)
- Update status after operations
- [ ] **Task 6.2**: Create MergeDialog
- Source branch selector
- Target branch display
- Commit message input
- Merge/Cancel buttons
- Handle conflicts
## Phase 7: Integration & Polish
- [ ] **Task 7.1**: Wire everything together
- Connect toolbar to all APIs
- Update workspace state after operations
- Refresh file tree on branch switch
- [ ] **Task 7.2**: Add error handling
- Show toast notifications for operations
- Handle all error cases gracefully
- Provide recovery options
- [ ] **Task 7.3**: Add CSS styles
- Toolbar layout
- Status indicators
- Commit panel
- Dialogs
- [ ] **Task 7.4**: Run quality gates
- Backend: ruff, mypy, pytest
- Frontend: typecheck, lint, build
## Phase 8: Testing
- [ ] **Task 8.1**: Backend tests
- Test all git operations
- Test error cases
- Test auth failures
- [ ] **Task 8.2**: Frontend tests
- Test toolbar interactions
- Test branch management
- Test commit workflow
- [ ] **Task 8.3**: Manual testing
- Create branch → edit → commit → push → merge workflow
- Test error scenarios
- Test with multiple repos