chore: added a plan for git syncing

This commit is contained in:
2026-02-16 06:39:12 +01:00
parent 52aed4c420
commit 2ef67194f3

343
IMPLEMENT_GIT.md Normal file
View File

@@ -0,0 +1,343 @@
# IMPLEMENT_GIT
## Goal
Implement a VS Code-like Git sidebar workflow for the current project in bDS with:
- Left sidebar rail sync icon (bottom section, directly above Settings)
- Sidebar split into upper **Open Changes** and lower **Version History**
- File click to open diff view against repository in editor tabs with transient/persistent behavior
- `Initialize Git` action when no repo exists
- Periodic status polling and remote fetch polling
- Fetch / Pull / Push actions in repo header
- Commit message input + `Commit` button (add-all + commit)
This plan is scoped to the existing Electron architecture:
- Main process business logic in `src/main/engine`
- IPC handlers in `src/main/ipc`
- Typed bridge in `src/main/preload.ts` and `src/main/shared/electronApi`
- Renderer state/UI in `src/renderer/store` and `src/renderer/components`
---
## External Requirements
## 1) Runtime Dependencies
- **Primary library**: `simple-git`
- **System requirement**: `git` CLI installed and available in PATH
- **Optional later**: fallback to bundled Git binary for users without system Git
## 2) OS / Packaging
- Support macOS, Linux, Windows path handling and quoting.
- If bundling Git later, include signing/notarization and license notices in release pipeline.
## 3) Performance Requirements
- Must handle large change sets without list jump/reflow issues.
- Polling and fetch operations must be background/non-blocking and cancellable.
## 4) Security Requirements
- Run all Git commands in main process only.
- Validate project root path before command execution.
- Never allow arbitrary command injection via renderer inputs.
---
## UX and Behavioral Requirements (from spec)
## Sidebar Rail Button
- Add a new Git sync icon button in the left sidebar rail bottom section, directly above the Settings icon.
- Clicking icon opens/closes Git sidebar view similarly to existing views.
## Sidebar Layout (Git view)
- Upper half: **Open Changes** list.
- Lower half: **Version History** list.
- Repo actions in header: **Fetch**, **Pull**, **Push** icons.
- Open Changes area includes:
- Commit message input field
- Commit button (does add-all + commit)
## No Repository State
- If current project is not a git repo:
- show `Initialize Git` button.
- action runs `git init`.
- if git executable not found, show explicit install guidance message.
## Diff Behavior
- Diff views open in tabs in the editor area.
- Single-click on a changed file opens a diff in a transient tab (reused for subsequent single-clicks), matching post transient tab behavior.
- Double-click on a changed file opens a dedicated non-transient diff tab that remains open until explicitly closed by the user.
- Dedicated diff tabs stay open even when other files are clicked in the sidebar.
- Open diff tabs are persisted in app tab state and restored on next app start, same persistence model as post tabs.
- Clicking a changed file opens diff view of working tree vs repository (HEAD/index depending file state).
- Committing changes automatically closes all open diff tabs because the compared diff baseline no longer applies.
## Polling Behavior
- Poll git status regularly (VS Code-like freshness).
- Refresh should be incremental (preserve list item identity/order strategy where possible).
- Preserve scroll position for large lists; avoid jump-to-top.
## Remote Awareness
- If remote exists, perform regular `git fetch` polling.
- Show upstream relationship in version history section:
- current local HEAD
- upstream branch tip
- ahead/behind indicators
---
## Proposed Architecture
## Main Process (new engine)
Create `src/main/engine/GitEngine.ts` with focused methods:
- `checkAvailability(): Promise<{ gitFound: boolean; version?: string }>`
- `getRepoState(projectPath): Promise<RepoState>`
- `initializeRepo(projectPath): Promise<Result>`
- `getStatus(projectPath): Promise<GitStatusDto>`
- `getDiff(projectPath, filePath): Promise<GitDiffDto>`
- `getHistory(projectPath, limit, cursor?): Promise<HistoryDto>`
- `getRemoteState(projectPath): Promise<RemoteStateDto>`
- `fetch(projectPath): Promise<Result>`
- `pull(projectPath): Promise<Result>`
- `push(projectPath): Promise<Result>`
- `commitAll(projectPath, message): Promise<Result>`
Implementation notes:
- Use `simple-git` instance rooted at active project path.
- Distinguish error classes:
- git missing
- not a repo
- auth/network/merge conflict
- detached HEAD / no upstream
- Normalize file paths to repo-relative format for renderer stability.
## IPC Layer
Add handlers in `src/main/ipc/handlers.ts` and type contracts in shared API:
- `git:checkAvailability`
- `git:getRepoState`
- `git:init`
- `git:status`
- `git:diff`
- `git:history`
- `git:remoteState`
- `git:fetch`
- `git:pull`
- `git:push`
- `git:commitAll`
Expose via `src/main/preload.ts`:
- `window.electronAPI.git.*` methods.
## Renderer State
Extend `src/renderer/store/appStore.ts` with Git slice:
- `activeView` union includes `'git'`
- `git: {`
- `availability`
- `repoState`
- `status` (files + counts)
- `history`
- `remoteState` (branch, upstream, ahead, behind, lastFetchAt)
- `selectedDiffFile`
- `commitMessage`
- `loading/action flags`
- `error`
- `}`
Store actions:
- `setGitStatus`, `mergeGitStatusIncremental`, `setGitHistory`, `setGitRemoteState`
- `setSelectedDiffFile`, `setCommitMessage`
- `setGitPollingState`
Tab behavior extensions:
- Extend `TabType` with `'git-diff'`.
- Use existing transient tab mechanics for single-click diff open.
- Add/ensure explicit pinning path for double-click diff tabs (`isTransient: false`).
- Include diff tabs in persisted tab state (`getTabState` / `restoreTabState`) so they reopen after restart.
- On successful commit action, remove all open `'git-diff'` tabs and clear selected diff state.
## Renderer Components
- Update `src/renderer/components/ActivityBar/ActivityBar.tsx` to place Git icon in the bottom rail group above Settings and wire view toggle.
- Add Git section to `src/renderer/components/Sidebar/Sidebar.tsx` render switch.
- Add dedicated presentational components:
- `src/renderer/components/GitSidebar/GitSidebar.tsx`
- `src/renderer/components/GitSidebar/OpenChangesList.tsx`
- `src/renderer/components/GitSidebar/VersionHistoryList.tsx`
- `src/renderer/components/GitSidebar/RepoActions.tsx`
- Add diff tab rendering in editor area:
- new tab type `'git-diff'`
- diff viewer component `GitDiffView`.
- single-click handler opens/reuses transient diff tab.
- double-click handler opens persistent diff tab.
---
## Polling and Update Strategy
## Status Polling (fast)
- Interval: ~2s when Git view visible, ~510s when hidden.
- Trigger immediate refresh after commit/fetch/pull/push/init.
- Use in-flight guard to avoid concurrent status calls.
## Remote Polling (slower)
- Run only when remote exists and git is available.
- Interval: ~3060s with backoff on errors.
- Use `git fetch --prune` equivalent through `simple-git`.
## Scroll/Render Stability
- Keep stable `key` = repo-relative file path.
- Preserve existing array reference for unchanged items when merging updates.
- Update only changed/added/removed entries in store (incremental diff merge).
- Use virtualization (`react-window`) if list grows beyond threshold (e.g., >300 entries).
- Preserve scrollTop by storing/restoring container position if full list replacement is unavoidable.
## Repositioning Rules
- Do not auto-sort on every tick if sort key not changed.
- Insert new items predictably (status-group + path order) to minimize movement.
- Never auto-scroll on status update.
---
## History Model (lower half)
Each history item should include:
- `commitHash`
- `author`
- `date`
- `subject`
- `isHead`
- `isRemoteHead` (where applicable)
- `refs` (branch/tag labels)
Remote awareness section:
- Show `localBranch -> upstreamBranch`
- Show `ahead N / behind M`
- Show last fetch timestamp and fetch errors (if any)
---
## Error Handling UX
## Git Missing
- Detect once on startup/opening Git view and before actions.
- Display clear CTA text: install Git and restart app.
## Not a Repo
- Show empty state with `Initialize Git` button.
- After successful init, auto-refresh status/history.
## Action Failures
- Show concise toast + inline error in Git panel section.
- Keep previous state rendered (no hard reset).
## Auth/Conflict Cases
- For pull/push conflicts/auth failures, show actionable message; do not hide current status/history.
---
## Test-First Delivery Plan (TDD)
Follow strict red-green-refactor per project rules.
## Phase 1: Contracts and engine scaffolding
1. Add failing tests for `GitEngine` availability/repo detection/status parsing.
2. Implement minimal engine methods.
3. Add IPC contract tests for new `git:*` handlers.
## Phase 2: No-repo + init workflow
1. Add renderer tests for no-repo state and `Initialize Git` button.
2. Implement init action and git-missing messaging.
3. Validate with integration-style IPC mock tests.
## Phase 3: Open changes + diff
1. Add tests for open changes list rendering and file selection.
2. Add tests for opening `git-diff` tab and loading diff.
3. Add tests for single-click transient tab reuse and double-click persistent tab behavior.
4. Implement diff component and tab behavior.
## Phase 3b: Diff tab persistence and commit cleanup
1. Add tests to verify `git-diff` tabs are persisted/restored via tab state.
2. Add tests to verify successful commit closes all open `git-diff` tabs.
3. Implement store and commit-flow wiring for cleanup behavior.
## Phase 4: Commit + repo actions
1. Add tests for commit message entry and commit action (`addAll + commit`).
2. Add tests for fetch/pull/push button wiring and disabled/loading states.
3. Implement action handlers with refresh chaining.
## Phase 5: Polling and stability
1. Add tests for polling intervals and in-flight guards (fake timers).
2. Add tests for incremental list updates preserving scroll/identity.
3. Implement merge strategy + optional virtualization threshold.
## Phase 6: Remote tracking in history
1. Add tests for ahead/behind and upstream marker rendering.
2. Implement periodic fetch + remote state projection.
3. Validate remote indicators against mocked git responses.
## Phase 7: Hardening
1. Add tests for error surfaces (git missing, auth fail, merge conflict).
2. Verify all tests pass.
3. Run full build and fix regressions.
---
## Suggested File-Level Work Breakdown
Main process:
- `src/main/engine/GitEngine.ts` (new)
- `src/main/engine/index.ts` (export)
- `src/main/ipc/handlers.ts` (new handlers)
- `src/main/shared/electronApi.ts` (API types)
- `src/main/preload.ts` (bridge methods)
Renderer:
- `src/renderer/store/appStore.ts` (Git state/actions)
- `src/renderer/components/ActivityBar/ActivityBar.tsx` (Git icon entry in bottom rail, above Settings)
- `src/renderer/components/Sidebar/Sidebar.tsx` (Git view integration)
- `src/renderer/components/GitSidebar/*` (new)
- `src/renderer/components/Editor/*` or new `GitDiffView` component
Tests:
- `tests/engine/GitEngine.test.ts` (new)
- `tests/ipc/handlers.test.ts` (extend)
- `tests/renderer/components/GitSidebar.test.tsx` (new)
- `tests/renderer/store/appStore.git.test.ts` (new)
---
## Milestones and Acceptance Criteria
## Milestone A: Basic Git UX
- Git sync icon appears in left sidebar rail bottom section above Settings.
- Git sidebar opens with no-repo empty state.
- `Initialize Git` works and transitions to repo state.
## Milestone B: Changes + Diff
- Open Changes list renders tracked/untracked/modified/deleted files.
- Single-click opens/reuses transient diff tab and renders correct patch.
- Double-click opens persistent diff tab that remains until user closes it.
- Diff tabs persist across app restarts.
## Milestone C: Commit and Repo Actions
- Commit message + Commit button performs add-all + commit.
- Successful commit closes all open diff tabs automatically.
- Fetch/Pull/Push actions execute with visible status feedback.
## Milestone D: Polling + Remote
- Status polling updates changes without scroll jump.
- Remote fetch polling updates ahead/behind and remote markers.
- History clearly shows local/remote relation.
## Milestone E: Quality Gate
- All tests pass.
- Full build passes.
- No console spam, no renderer freeze on large change sets.
---
## Implementation Order Recommendation
1. Contracts + GitEngine + IPC
2. No-repo/init UX
3. Open changes list + diff viewer
4. Commit + fetch/pull/push actions
5. Polling + incremental list merge + scroll stability
6. Remote-aware history refinement and hardening
This order minimizes risk and delivers user-visible value early while preserving room for performance optimization in later iterations.