Enable viewing of worktrees under Repositories (#254992)

* init

* fix: correct configuration key for detecting Git worktrees

* Fixed misspelling of worktrees and populated worktree list

* exported parseGitWorktrees

* Replaced git commands with file system reader

* Removed trailing './git' from path

* Prevent errors when accessing empty worktree directory

* Enable worktree deletion

* code clean up

* Remove exposure to git extension

* labeling and minor fixes

* throw error when no worktrees created

* Error handling when getting worktrees

---------

Co-authored-by: bhavyaus <bhavyau@microsoft.com>
This commit is contained in:
Christy 😺
2025-07-14 11:27:00 -07:00
committed by GitHub
parent c068082c35
commit 4576aa4385
7 changed files with 188 additions and 5 deletions

View File

@@ -860,6 +860,11 @@ export class GitStatusParser {
}
}
export interface Worktree {
readonly name: string;
readonly path: string;
}
export interface Submodule {
name: string;
path: string;
@@ -2028,6 +2033,11 @@ export class Repository {
await this.exec(args);
}
async deleteWorktree(path: string): Promise<void> {
const args = ['worktree', 'remove', path];
await this.exec(args);
}
async deleteRemoteRef(remoteName: string, refName: string, options?: { force?: boolean }): Promise<void> {
const args = ['push', remoteName, '--delete'];
@@ -2740,6 +2750,50 @@ export class Repository {
return parseGitStashes(result.stdout.trim());
}
async getWorktrees(): Promise<Worktree[]> {
return await this.getWorktreesFS();
}
private async getWorktreesFS(): Promise<Worktree[]> {
const worktreesPath = path.join(this.repositoryRoot, '.git', 'worktrees');
try {
// List all worktree folder names
const dirents = await fs.readdir(worktreesPath, { withFileTypes: true });
const result: Worktree[] = [];
for (const dirent of dirents) {
if (!dirent.isDirectory()) {
continue;
}
const gitdirPath = path.join(worktreesPath, dirent.name, 'gitdir');
try {
const gitdirContent = (await fs.readFile(gitdirPath, 'utf8')).trim();
// Remove trailing '/.git'
const gitdirTrimmed = gitdirContent.replace(/\.git.*$/, '');
result.push({ name: dirent.name, path: gitdirTrimmed });
} catch (err) {
if (/ENOENT/.test(err.message)) {
continue;
}
throw err;
}
}
return result;
}
catch (err) {
if (/ENOENT/.test(err.message)) {
return [];
}
throw err;
}
}
async getRemotes(): Promise<Remote[]> {
const remotes: MutableRemote[] = [];