feat(git): add ignore and untrack paths commands

The changes introduce server-side commands to manage gitignore
 rules and to untrack paths without deleting local files.
 A new GitIgnoreKind enum and helper functions normalize targets
 and build proper ignore patterns, and UI code was wired to use
 these commands.

- add_to_gitignore command and related helpers
- untrack_paths command to remove paths from the index
- UI wiring to expose ignore and untrack actions in explorer
This commit is contained in:
Christoph Brandau
2026-08-18 13:09:33 +02:00
parent a4936ba790
commit e4697c74b6
11 changed files with 608 additions and 53 deletions
+26
View File
@@ -36,6 +36,7 @@
import UpdateToast from "./lib/components/UpdateToast.svelte";
import {
addToGitignore,
amendCommit,
addRemote,
addWorktree,
@@ -137,6 +138,7 @@
undoLastCommit,
unlockWorktree,
untrackGitLfsPattern,
untrackPaths,
unstageFiles,
} from "./lib/git";
@@ -161,6 +163,7 @@
GitCommitComparison,
GitDiffFile,
GitFileStatus,
GitIgnoreKind,
GitLfsStatus,
GitRepositoryFile,
GitRemote,
@@ -3947,6 +3950,25 @@
});
}
async function ignoreStatusTarget(target: string, kind: GitIgnoreKind) {
if (!activeRepoPath || !target) return;
const description = kind === "folder" ? "folder" : kind === "extension" ? "file extension" : "file";
await runOperation(`Ignoring ${description}`, async () => {
applyStatus(await addToGitignore(activeRepoPath, target, kind));
await refreshExplorerFiles(activeRepoPath);
trackEvent("gitignore_rule_added", { kind });
});
}
async function stopTrackingTarget(target: string, kind: "file" | "folder") {
if (!activeRepoPath || !target) return;
await runOperation(`Stopping tracking for ${kind}`, async () => {
applyStatus(await untrackPaths(activeRepoPath, [target]));
await refreshExplorerFiles(activeRepoPath);
trackEvent("git_paths_untracked", { kind });
});
}
function discardFiles(files: GitFileStatus[], staged: boolean) {
if (!activeRepoPath || isBusy || files.length === 0) return;
pendingDiscard = { kind: "file", files, staged };
@@ -5309,6 +5331,8 @@
onExternalDiff={compareExplorerFileExternally}
onFileHistory={openFileHistoryDialog}
onBlame={openBlame}
onIgnore={ignoreStatusTarget}
onStopTracking={stopTrackingTarget}
collapsed={explorerPanelCollapsed}
onToggleCollapsed={toggleExplorerPanelCollapsed}
/>
@@ -5378,6 +5402,8 @@
onDiscard={discardFiles}
onDiscardMany={discardChanges}
onStash={stashStatusFiles}
onIgnore={ignoreStatusTarget}
onStopTracking={stopTrackingTarget}
onPatch={openPreferredFileDiff}
onStageAll={stageAllFiles}
onUnstageAll={unstageAllFiles}