Skip to content

Git feature#7

Merged
anirudhisonline merged 5 commits into
mainfrom
git-good
May 14, 2026
Merged

Git feature#7
anirudhisonline merged 5 commits into
mainfrom
git-good

Conversation

@anirudhisonline
Copy link
Copy Markdown
Contributor

@anirudhisonline anirudhisonline commented May 13, 2026

Summary by CodeRabbit

  • New Features

    • Full Git integration in-app: status, staging/unstaging, commits, logs, branch ops, push/pull, file diffs (text & image), commit viewer, and a Git panel with Changes/History views
    • Filesystem watcher with project watch/unwatch and automatic refresh events
  • Stores / State

    • Per-file change ticks and a git refresh tick added to workspace store
  • Configuration

    • Added local tool settings files
  • Style

    • Reduced dark-theme border radius
  • Documentation

    • Project header updated to "takerest.dev"

Review Change Stack

git is now available in takerest.dev now
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8e2f1e9f-bf75-435e-8739-0a562ae9c8e6

📥 Commits

Reviewing files that changed from the base of the PR and between 99b36c1 and dbd8e26.

📒 Files selected for processing (1)
  • src-tauri/src/commands/watcher.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src-tauri/src/commands/watcher.rs

📝 Walkthrough

Walkthrough

Comprehensive Git integration: Rust Tauri commands/types and watcher, Tauri invoke wiring, JS wrapper APIs, workspace tick propagation, and Svelte UI panels for status, staging, branches, history, and diff viewing.

Changes

Git Integration Feature

Layer / File(s) Summary
Rust backend foundation and error handling
src-tauri/Cargo.toml, src-tauri/src/error.rs, src-tauri/src/commands/mod.rs, src-tauri/src/lib.rs
Adds gix, imara-diff, base64, notify-debouncer-full; registers WatcherState and many commands::git::* and watcher handlers; adds AppError::Git.
Git operations, data models, and helpers
src-tauri/src/commands/git.rs
Defines serializable Git types and implements many Tauri commands for status, diffs, log, branches, blob reads, staging, commit, checkout, fetch/pull/push, stash, and commit-file diffs plus unified-diff helpers and binary/image short-circuits.
Project detection & worktree support
src-tauri/src/commands/project.rs
Extends GitInfo with is_worktree and worktree_name; updates detect_git to resolve .git file pointers and identify linked worktrees.
Filesystem watcher backend
src-tauri/src/commands/watcher.rs
Adds WatcherState, debounced notify watcher, path normalization, and watch_project/unwatch_project commands that emit "fs:changed" payloads.
JavaScript API wrappers
src/lib/commands/git.js, src/lib/commands/watcher.js
Adds async wrappers for all git and watcher backend commands and JSDoc typedefs for response shapes.
Git status and staging UI
src/lib/components/panels/GitChanges.svelte, src/lib/components/panels/GitFileTree.svelte
New GitChanges panel: loads status, builds tree, optimistic stage/unstage (single/all), commit dialog, merge-abort; GitFileTree renders recursive tree rows with stage toggles and conflict markers.
History and commit detail UI
src/lib/components/panels/GitHistory.svelte, src/lib/components/workspace/CommitTab.svelte
GitHistory lists commits (up to 200) with formatted times; CommitTab shows per-commit file list and virtualized unified/split diff viewer for selected file.
Diff viewing components (text & image)
src/lib/components/workspace/DiffTab.svelte, src/lib/components/workspace/ImageDiffTab.svelte
DiffTab implements virtualized unified/split viewers with pagination and split-sync; ImageDiffTab fetches before/after blobs and renders added/deleted/modified layouts.
Git orchestrator and layout integration
src/lib/components/panels/GitPanel.svelte, src/routes/app/+layout.svelte, src/lib/stores/workspace.svelte.js
GitPanel manages branches, remote status, fetch/pull/push/publish, checkout with stash/force options, and new-branch flows; layout wires GitPanel into sidebar, adds tab types git-diff/git-commit, and starts/stops project watcher events to bump workspace ticks.
Project metadata and styling
.claude/settings.local.json, .claude/settings.json, README.md, src/routes/layout.css
Updates Claude permissions to allow certain Bash/Cargo/Bun commands, adds a settings file, updates README header to takerest.dev, and reduces .dark theme --radius from 1rem0.75rem.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • takerestdev/takerest#5: Prior Git/Tauri scaffolding and AppError/module groundwork related to this change.
  • takerestdev/takerest#1: Earlier edits touching theme tokens and src/routes/layout.css that overlap style changes.

"I nibble diffs beneath the moon's soft glow,
I stash my carrots where the branches grow,
From staged to pushed, my hops are quick and neat,
Commits and hunks and histories to eat,
A rabbit's merge — now everything's in tow." 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title "Git feature" is vague and generic, using non-descriptive language that does not convey meaningful information about the extensive changeset. Consider a more descriptive title that captures the main accomplishment, such as "Add comprehensive Git operations backend and UI" or "Implement Git status, diff, commit, and branch management."
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch git-good

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
src-tauri/src/commands/git.rs (3)

143-145: 💤 Low value

Consider using iter().any() for binary detection.

The contains() method on slices can be less efficient than using an iterator. For better performance on large buffers:

⚡ Optional performance improvement
 fn sniff_binary(data: &[u8]) -> bool {
-    data[..data.len().min(8192)].contains(&0u8)
+    data[..data.len().min(8192)].iter().any(|&b| b == 0)
 }

Or for even better performance, consider the memchr crate which provides SIMD-optimized byte searching.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/commands/git.rs` around lines 143 - 145, The binary sniffing in
function sniff_binary currently uses slice.contains(&0u8); replace it with an
iterator-based check like data.iter().take(8192.min(data.len())).any(|&b| b ==
0) to avoid creating a full subslice and improve performance; optionally, for
even faster scans, use memchr::memchr on the limited prefix instead of the
iterator.

370-396: ⚡ Quick win

Consider improving readability of nested Option handling.

The use of flatten() on nested Option<Option<T>> works but reduces clarity. Consider extracting the blob-loading logic into a helper function.

📖 Suggested refactor for clarity
fn read_blob_from_tree(repo: &gix::Repository, tree: &gix::Tree, rel_path: &str) -> Vec<u8> {
    let mut entries = BTreeMap::new();
    if collect_tree_entries(repo, tree, "", &mut entries).is_err() {
        return vec![];
    }
    entries.get(rel_path)
        .and_then(|&oid| repo.find_object(oid).ok())
        .map(|o| o.data.to_vec())
        .unwrap_or_default()
}

fn read_blob_from_index(repo: &gix::Repository, index: &gix::index::File, rel_path: &str) -> Vec<u8> {
    index.entries().iter()
        .find(|e| e.path(index).to_str().ok().as_deref() == Some(rel_path))
        .and_then(|e| repo.find_object(e.id).ok())
        .map(|o| o.data.to_vec())
        .unwrap_or_default()
}

Then simplify lines 370-396:

let (old_bytes, new_bytes): (Vec<u8>, Vec<u8>) = if staged {
    let old = repo.head_commit().ok()
        .and_then(|c| c.tree().ok())
        .map(|tree| read_blob_from_tree(&repo, &tree, &rel_path))
        .unwrap_or_default();
    let new = read_blob_from_index(&repo, &index, &rel_path);
    (old, new)
} else {
    let old = read_blob_from_index(&repo, &index, &rel_path);
    let new = std::fs::read(workdir.join(&rel_path)).unwrap_or_default();
    (old, new)
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/commands/git.rs` around lines 370 - 396, The nested Option
handling around loading blobs should be refactored into helpers to improve
clarity: add functions like read_blob_from_tree(repo, tree, rel_path) which
calls collect_tree_entries and returns Vec<u8> (empty on error) and
read_blob_from_index(repo, index, rel_path) which scans index.entries() and
returns the blob bytes or empty; then replace the inline nested logic in the
staged branch (which currently uses repo.head_commit(), .tree(),
.map(...).flatten()) with calls to read_blob_from_tree and read_blob_from_index,
and in the non-staged branch use read_blob_from_index for old_bytes and
std::fs::read(workdir.join(&rel_path)) for new_bytes. Ensure the helpers use
repo.find_object(e.id).ok() and .map(|o| o.data.to_vec()).unwrap_or_default() so
behavior is unchanged.

616-620: 💤 Low value

Consider renaming git_checkout_force for clarity.

The function uses git checkout -m which attempts to merge uncommitted changes to the new branch, not force checkout. The name git_checkout_force suggests it would discard changes (-f), but it actually tries to preserve them.

Consider renaming to git_checkout_with_changes or git_checkout_merge to better reflect the behavior, or update the docstring to clarify the merge behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/commands/git.rs` around lines 616 - 620, The function
git_checkout_force currently calls run_git(&project_path, &["checkout", "-m",
&branch]) but its name implies a destructive force checkout; rename
git_checkout_force to git_checkout_with_changes or git_checkout_merge (or update
the docstring) to reflect that it merges/uncommitted-changes behavior, and
update all call sites and the function's docstring to describe that it runs "git
checkout -m" to preserve/merge local changes rather than discarding them.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/settings.local.json:
- Around line 6-8: The allow-list entries "Bash(bun run *)" and "Bash(bun add
*)" are overly broad and allow arbitrary package/script execution; replace them
with least-privilege entries that enumerate only the required commands or fixed
patterns. Specifically, remove or replace "Bash(bun add *)" with explicit
package add commands you actually need (e.g., "Bash(bun add <package-name>)" for
each package) and narrow "Bash(bun run *)" to exact scripts used (e.g.,
"Bash(bun run build)" and "Bash(bun run test)"), or use more restrictive
patterns that exclude arbitrary arguments; keep "Bash(cargo check *)" only if
necessary or similarly restrict it to specific cargo subcommands. Ensure the
updated entries reference the exact command names used by CI/dev workflows so no
wildcard remains that would permit arbitrary execution.

In `@src-tauri/src/commands/project.rs`:
- Around line 279-283: The current check for linked worktrees uses
resolved_path.components().any(...) which matches any ancestor named
"worktrees"; change it to inspect only the immediate parent directory of the
gitdir admin dir by using resolved_path.parent() (or walk up one level) and
comparing that parent.file_name() == "worktrees" so is_linked is true only when
the gitdir's direct parent is "worktrees" (update any logic that derives
worktreeName from resolved_path to rely on that immediate parent match).

In `@src/lib/commands/git.js`:
- Line 150: The JSDoc BranchInfo typedef in src/lib/commands/git.js is out of
sync with the backend Rust struct; update the typedef to match the backend by
removing the upstream field and ensuring the remaining fields match names/types
(keep name: string and isRemote: boolean to reflect Rust's is_remote), i.e.,
delete the upstream: string|null entry and confirm the typedef is exactly {{
name: string, isRemote: boolean }} for BranchInfo.

In `@src/lib/components/panels/GitHistory.svelte`:
- Around line 13-22: The async gitLog call can return out of order and overwrite
newer state; in the $effect that watches refreshTick/projectPath, create and
capture a per-request identifier (e.g., incrementing requestId or a local token)
before calling gitLog(projectPath, 200) and only apply the .then/.catch/.finally
results if the captured id matches the latest request id; update commits, error
and loading inside that guarded check so stale responses are ignored (use the
symbols $effect, refreshTick, projectPath, gitLog, commits, error, loading and a
module-scoped requestId/token).

In `@src/lib/components/workspace/ImageDiffTab.svelte`:
- Around line 17-40: The code currently calls dataUrl(...) for
beforeBlob/afterBlob even when those blobs can be null after failed reads;
update the rendering logic in ImageDiffTab.svelte to guard any calls to dataUrl
and any image rendering behind null checks (e.g., only call dataUrl(beforeBlob)
when beforeBlob !== null and dataUrl(afterBlob) when afterBlob !== null), and
for the added/deleted branches (the alternate rendering block around the current
dataUrl usage and the similar block referenced at lines ~65-77) render a safe
placeholder or skip the image when the corresponding blob is null; ensure no
code path assumes non-null beforeBlob/afterBlob so that
gitReadBlobHead/gitReadBlobWorktree failures cannot cause a crash.

---

Nitpick comments:
In `@src-tauri/src/commands/git.rs`:
- Around line 143-145: The binary sniffing in function sniff_binary currently
uses slice.contains(&0u8); replace it with an iterator-based check like
data.iter().take(8192.min(data.len())).any(|&b| b == 0) to avoid creating a full
subslice and improve performance; optionally, for even faster scans, use
memchr::memchr on the limited prefix instead of the iterator.
- Around line 370-396: The nested Option handling around loading blobs should be
refactored into helpers to improve clarity: add functions like
read_blob_from_tree(repo, tree, rel_path) which calls collect_tree_entries and
returns Vec<u8> (empty on error) and read_blob_from_index(repo, index, rel_path)
which scans index.entries() and returns the blob bytes or empty; then replace
the inline nested logic in the staged branch (which currently uses
repo.head_commit(), .tree(), .map(...).flatten()) with calls to
read_blob_from_tree and read_blob_from_index, and in the non-staged branch use
read_blob_from_index for old_bytes and std::fs::read(workdir.join(&rel_path))
for new_bytes. Ensure the helpers use repo.find_object(e.id).ok() and .map(|o|
o.data.to_vec()).unwrap_or_default() so behavior is unchanged.
- Around line 616-620: The function git_checkout_force currently calls
run_git(&project_path, &["checkout", "-m", &branch]) but its name implies a
destructive force checkout; rename git_checkout_force to
git_checkout_with_changes or git_checkout_merge (or update the docstring) to
reflect that it merges/uncommitted-changes behavior, and update all call sites
and the function's docstring to describe that it runs "git checkout -m" to
preserve/merge local changes rather than discarding them.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b12b36ee-5fc8-4de1-a91d-236d899456e8

📥 Commits

Reviewing files that changed from the base of the PR and between ee38239 and b01aab4.

⛔ Files ignored due to path filters (1)
  • src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (18)
  • .claude/settings.local.json
  • README.md
  • src-tauri/Cargo.toml
  • src-tauri/src/commands/git.rs
  • src-tauri/src/commands/mod.rs
  • src-tauri/src/commands/project.rs
  • src-tauri/src/error.rs
  • src-tauri/src/lib.rs
  • src/lib/commands/git.js
  • src/lib/components/panels/GitChanges.svelte
  • src/lib/components/panels/GitFileTree.svelte
  • src/lib/components/panels/GitHistory.svelte
  • src/lib/components/panels/GitPanel.svelte
  • src/lib/components/workspace/CommitTab.svelte
  • src/lib/components/workspace/DiffTab.svelte
  • src/lib/components/workspace/ImageDiffTab.svelte
  • src/routes/app/+layout.svelte
  • src/routes/layout.css

Comment thread .claude/settings.local.json Outdated
Comment thread src-tauri/src/commands/project.rs Outdated
Comment thread src/lib/commands/git.js Outdated
Comment thread src/lib/components/panels/GitHistory.svelte
Comment thread src/lib/components/workspace/ImageDiffTab.svelte
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
.claude/settings.local.json (1)

7-7: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove the remaining wildcard from the Cargo allow-list.

Line 7 still permits arbitrary --manifest-path values, which weakens the least-privilege boundary and reintroduces the broad command-execution risk previously flagged on this file. Replace * with the exact manifest path(s) this repo needs, or drop the entry if Line 6 already covers the intended workflow.

#!/bin/bash
set -euo pipefail

printf '== Cargo manifests in repo ==\n'
fd -H '^Cargo\.toml$'

printf '\n== package.json scripts mentioning cargo/tauri/check ==\n'
fd -H '^package\.json$' -x sh -c '
  printf "\n-- %s --\n" "$1"
  rg -n -C2 "\"(scripts|check|tauri|dev|build|preview)\"" "$1" || true
' sh {}

printf '\n== Current permission allow-list ==\n'
sed -n '1,40p' .claude/settings.local.json

Expected result: this should show the concrete Cargo manifest path(s) actually used by the repo so the wildcard can be replaced with explicit entries.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/settings.local.json at line 7, Replace the wildcard in the
allow-list entry "Bash(cargo check --manifest-path *)" with the explicit Cargo
manifest path(s) this repo actually uses (e.g., the concrete relative path(s) to
the Cargo.toml files reported by your repo scan) or remove the entry entirely if
the previous allow-list line already covers the intended workflow; ensure the
final entry contains exact manifest filenames instead of a glob to restore
least-privilege.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/commands/watcher.rs`:
- Around line 15-16: WatcherState currently stores a single global Debouncer
(WatcherState(pub Mutex<Option<Debouncer<RecommendedWatcher, FileIdMap>>>))
which allows watch_project to replace and unwatch_project to clear the watcher
for the entire app, causing cross-window interference; change the design to
maintain per-window watcher instances (e.g., map watchers by a unique window ID
or handle) instead of a single Option—modify WatcherState to hold a
HashMap<WindowId, Debouncer<RecommendedWatcher, FileIdMap>> (or similar) and
update watch_project and unwatch_project to create, replace, and remove the
Debouncer entry keyed by the caller’s window ID, ensuring locking, lifecycle
cleanup, and error handling operate on the specific entry rather than a global
one.
- Around line 31-33: The watcher currently ignores `.git/index` (see the
conditional checking s == ".git/index"), which suppresses staging/unstaging
signals; remove that equality check so `.git/index` is no longer filtered
out—leave the other ignores (e.g., s.ends_with(".lock") and
s.starts_with(".git/objects/")) intact. Locate the ignore logic in watcher.rs
(the conditional using s.ends_with, s == ".git/index", s.starts_with) and delete
the `.git/index` branch or adjust the condition to exclude only lock files and
.git/objects paths so changes to `.git/index` will trigger refreshes.

---

Duplicate comments:
In @.claude/settings.local.json:
- Line 7: Replace the wildcard in the allow-list entry "Bash(cargo check
--manifest-path *)" with the explicit Cargo manifest path(s) this repo actually
uses (e.g., the concrete relative path(s) to the Cargo.toml files reported by
your repo scan) or remove the entry entirely if the previous allow-list line
already covers the intended workflow; ensure the final entry contains exact
manifest filenames instead of a glob to restore least-privilege.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 238468e0-dbba-44f2-9e16-7dc41cecfac4

📥 Commits

Reviewing files that changed from the base of the PR and between b01aab4 and 99b36c1.

⛔ Files ignored due to path filters (1)
  • src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • .claude/settings.json
  • .claude/settings.local.json
  • src-tauri/Cargo.toml
  • src-tauri/src/commands/mod.rs
  • src-tauri/src/commands/project.rs
  • src-tauri/src/commands/watcher.rs
  • src-tauri/src/lib.rs
  • src/lib/commands/git.js
  • src/lib/commands/watcher.js
  • src/lib/components/panels/GitChanges.svelte
  • src/lib/components/panels/GitHistory.svelte
  • src/lib/components/panels/GitPanel.svelte
  • src/lib/components/workspace/CommitTab.svelte
  • src/lib/components/workspace/DiffTab.svelte
  • src/lib/components/workspace/EnvTab.svelte
  • src/lib/components/workspace/ImageDiffTab.svelte
  • src/lib/components/workspace/ReadmeTab.svelte
  • src/lib/stores/workspace.svelte.js
  • src/routes/app/+layout.svelte
✅ Files skipped from review due to trivial changes (3)
  • .claude/settings.json
  • src/lib/components/workspace/ReadmeTab.svelte
  • src/lib/components/workspace/EnvTab.svelte
🚧 Files skipped from review as they are similar to previous changes (11)
  • src-tauri/src/commands/mod.rs
  • src-tauri/Cargo.toml
  • src-tauri/src/lib.rs
  • src/lib/components/workspace/ImageDiffTab.svelte
  • src/lib/components/panels/GitHistory.svelte
  • src-tauri/src/commands/project.rs
  • src/lib/commands/git.js
  • src/lib/components/workspace/CommitTab.svelte
  • src/lib/components/workspace/DiffTab.svelte
  • src/lib/components/panels/GitPanel.svelte
  • src/lib/components/panels/GitChanges.svelte

Comment thread src-tauri/src/commands/watcher.rs
Comment thread src-tauri/src/commands/watcher.rs
@anirudhisonline anirudhisonline merged commit fb287af into main May 14, 2026
1 check passed
@anirudhisonline anirudhisonline deleted the git-good branch May 14, 2026 04:51
This was referenced May 14, 2026
This was referenced May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant