import vscode from "vscode"; import * as util from "node:util"; import { Repository } from "../../../types/git"; import { DiffManager } from "../../diff/DiffManager"; const asyncExec = util.promisify(require("child_process").exec); export class GitAction { private async _getRepo(forDirectory: vscode.Uri): Promise { // Use the native git extension to get the branch name const extension = vscode.extensions.getExtension("vscode.git"); if (typeof extension === "undefined" || !extension.isActive || typeof vscode.workspace.workspaceFolders === "undefined") { return null; } const git = extension.exports.getAPI(1); return git.getRepository(forDirectory); } async getRepo(forDirectory: vscode.Uri): Promise { let repo = await this._getRepo(forDirectory); let i = 0; while (!repo?.state?.HEAD?.name) { await new Promise((resolve) => setTimeout(resolve, 1000)); i++; if (i >= 20) { return undefined; } repo = await this._getRepo(forDirectory); } return repo; } async getGitRoot(forDirectory: string): Promise { const repo = await this.getRepo(vscode.Uri.file(forDirectory)); return repo?.rootUri?.fsPath; } async getBranch(forDirectory: vscode.Uri): Promise { let repo = await this.getRepo(forDirectory); if (repo?.state?.HEAD?.name === undefined) { try { const { stdout } = await asyncExec("git rev-parse --abbrev-ref HEAD", { cwd: forDirectory.fsPath, }); return stdout?.trim() || "NONE"; } catch (e) { return "NONE"; } } return repo?.state?.HEAD?.name || "NONE"; } async getDiff(): Promise { let diffs = []; for (const dir of this.getWorkspaceDirectories()) { const repo = await this.getRepo(vscode.Uri.file(dir)); if (!repo) { continue; } diffs.push(await this.getRepositoryChanges(repo)); } return diffs.join("\n\n"); } async getRepositoryChanges(repository: Repository): Promise { let diffResult = await repository.diff(true) || await repository.diff(); if (diffResult !== '') { return this.parseGitDiff(repository, diffResult); } else { return ""; } } async parseGitDiff(repository: Repository, diffResult: string): Promise { return DiffManager.simplifyDiff(repository, diffResult); } async getHistoryMessages(repository: Repository) { let repositoryHistories = []; let userHistories = []; let commits = await repository.log({ maxEntries: 10 }); repositoryHistories.push(...commits.map(commit => commit.message)); let userName = await repository.getConfig('user.name') ?? await repository.getGlobalConfig('user.name'); let userCommits = await repository.log({ maxEntries: 10, author: userName }); userHistories.push(...userCommits.map(commit => commit.message)); return { repositoryHistories, userHistories }; } getWorkspaceDirectories(): string[] { return ( vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath) || [] ); } }