refactor(services): extract Git operations into dedicated service with multi-repo support

This commit is contained in:
2026-08-27 15:55:20 +02:00
parent 019dfa96a0
commit a0f5508dc6
4 changed files with 111 additions and 84 deletions
+44 -32
View File
@@ -1,24 +1,24 @@
import * as vscode from "vscode";
interface GitExtension {
export interface GitExtension {
getAPI(version: number): GitAPI;
}
interface GitAPI {
export interface GitAPI {
repositories: Repository[];
}
interface Repository {
export interface Repository {
root: string;
rootUri: vscode.Uri;
state: RepositoryState;
inputBox: { value: string };
diffWithHEAD(path?: string): Promise<string>;
diffIndexWithHEAD(path?: string): Promise<string>;
diffWithHEAD(path?: string): Promise<string>;
status(): Promise<void>;
}
interface RepositoryState {
export interface RepositoryState {
indexChanges: Change[];
workingTreeChanges: Change[];
}
@@ -34,12 +34,9 @@ export interface GitChange {
diff?: string;
}
export async function getGitChanges(): Promise<GitChange[]> {
const repository = await getActiveGitRepository();
if (!repository) {
throw new Error("No Git repository found");
}
export async function getGitChanges(
repository: Repository,
): Promise<GitChange[]> {
const state = repository.state;
const changes: GitChange[] = [];
@@ -70,12 +67,9 @@ export async function getGitChanges(): Promise<GitChange[]> {
return changes;
}
export async function getGitDiff(): Promise<string> {
const repository = await getActiveGitRepository();
if (!repository) {
throw new Error("No Git repository found");
}
export async function getGitDiff(
repository: Repository,
): Promise<string> {
const state = repository.state;
let diffOutput = "";
@@ -123,7 +117,20 @@ export async function getGitDiff(): Promise<string> {
return diffOutput;
}
async function getActiveGitRepository(): Promise<Repository | null> {
export function getRepositoryRoot(repository: Repository): string {
if (typeof repository.root === "string") {
return repository.root;
}
return repository.rootUri.fsPath;
}
export function getRepositoryLabel(repository: Repository): string {
const root = getRepositoryRoot(repository);
const folderName = root.split("/").pop() || root;
return folderName;
}
export function getAllRepositories(): Repository[] {
const gitExtension =
vscode.extensions.getExtension<GitExtension>("vscode.git");
if (!gitExtension) {
@@ -131,10 +138,26 @@ async function getActiveGitRepository(): Promise<Repository | null> {
}
const api = gitExtension.exports.getAPI(1);
if (api.repositories.length === 0) {
return null;
return api.repositories;
}
export function findRepositoryForFile(
repositories: Repository[],
filePath: string,
): Repository | undefined {
const normalizedPath = filePath.toLowerCase();
let bestMatch: Repository | undefined;
let bestLength = 0;
for (const repo of repositories) {
const root = getRepositoryRoot(repo).toLowerCase();
if (normalizedPath.startsWith(root) && root.length > bestLength) {
bestMatch = repo;
bestLength = root.length;
}
}
return api.repositories[0];
return bestMatch;
}
function getChangeStatus(status: number): GitChange["status"] {
@@ -160,14 +183,3 @@ function getChangeStatus(status: number): GitChange["status"] {
return "modified";
}
export async function getRepositoryRoot(): Promise<string | null> {
const repository = await getActiveGitRepository();
if (!repository) {
return null;
}
if (typeof repository.root === "string") {
return repository.root;
}
return repository.rootUri.fsPath;
}