Skip to content

Commit 5f98a52

Browse files
[Fix] Get branchname using rev-parse instead of filesystem based approach (#118)
* [Fix] Get branchname using rev-parse instead of filesystem based approach * Update Node.js version to 22.x in CI workflow
1 parent e83b069 commit 5f98a52

File tree

3 files changed

+22
-38
lines changed

3 files changed

+22
-38
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515

1616
- uses: actions/setup-node@v4
1717
with:
18-
node-version: 18.x
18+
node-version: 22.x
1919

2020
- run: npm install
2121

src/gitHelper.ts

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -89,32 +89,19 @@ export async function getDefaultBranch(repo: Repository, head: Ref): Promise<str
8989
}
9090
}
9191

92-
export async function getBranchCommit(absGitCommonDir: string, branchName: string): Promise<string> {
92+
export async function getBranchCommit(branchName: string, repo: Repository): Promise<string> {
9393
// a cheaper alternative to repo.getBranch()
94-
const refPathUnpacked = path.join(absGitCommonDir, 'refs', 'heads', branchName);
94+
// Uses git rev-parse which works with all ref storage formats (traditional, packed-refs, reftable)
9595
try {
96-
const commit = (await fs.readFile(refPathUnpacked, 'utf8')).trim();
97-
return commit;
98-
} catch (e) {
99-
const refs = await readPackedRefs(absGitCommonDir);
100-
const ref = `refs/heads/${branchName}`;
101-
const commit = refs.get(ref);
102-
if (commit === undefined) {
103-
throw new Error(`Could not determine commit for "${branchName}"`);
96+
const result = await repo.exec(['rev-parse', `refs/heads/${branchName}`]);
97+
const commit = result.stdout.trim();
98+
if (commit) {
99+
return commit;
104100
}
105-
return commit;
101+
} catch (e) {
102+
// Branch doesn't exist or other error
106103
}
107-
}
108-
109-
async function readPackedRefs(absGitCommonDir: string): Promise<Map<string,string>> {
110-
// see https://git-scm.com/docs/git-pack-refs
111-
const packedRefsPath = path.join(absGitCommonDir, 'packed-refs');
112-
const content = await fs.readFile(packedRefsPath, 'utf8');
113-
const regex = /^([0-9a-f]+) (.+)$/;
114-
return new Map((content.split('\n')
115-
.map(line => regex.exec(line))
116-
.filter(g => !!g) as RegExpExecArray[])
117-
.map((groups: RegExpExecArray) => [groups[2], groups[1]] as [string, string]));
104+
throw new Error(`Could not determine commit for "${branchName}"`);
118105
}
119106

120107
export async function getHeadModificationDate(absGitDir: string): Promise<Date> {
@@ -229,14 +216,14 @@ export async function diffIndex(repo: Repository, ref: string, refreshIndex: boo
229216
const untrackedStatuses: IDiffStatus[] = untrackedResult.stdout.split('\0')
230217
.slice(0, -1)
231218
.map(line => new DiffStatus(repoRoot, 'U' as 'U', line, undefined, MODE_EMPTY, MODE_REGULAR_FILE));
232-
219+
233220
const untrackedAbsPaths = new Set(untrackedStatuses.map(status => status.dstAbsPath))
234221

235222
// If a file was removed (D in diff-index) but was then re-introduced and not committed yet,
236223
// then that file also appears as untracked (in ls-files). We need to decide which status to keep.
237224
// Since the untracked status is newer it gets precedence.
238225
const filteredDiffIndexStatuses = diffIndexStatuses.filter(status => !untrackedAbsPaths.has(status.srcAbsPath));
239-
226+
240227
const statuses = filteredDiffIndexStatuses.concat(untrackedStatuses);
241228
statuses.sort((s1, s2) => s1.dstAbsPath.localeCompare(s2.dstAbsPath))
242229
return statuses;

src/treeProvider.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { Repository, Git } from './git/git'
1111
import { Ref, RefType } from './git/api/git'
1212
import { anyEvent, filterEvent, eventToPromise } from './git/util'
1313
import { getDefaultBranch, getHeadModificationDate, getBranchCommit,
14-
diffIndex, IDiffStatus, StatusCode, getAbsGitDir, getAbsGitCommonDir,
14+
diffIndex, IDiffStatus, StatusCode, getAbsGitDir,
1515
getWorkspaceFolders, getGitRepositoryFolders, hasUncommittedChanges, rmFile } from './gitHelper'
1616
import { debounce, throttle } from './git/decorators'
1717
import { normalizePath } from './fsUtils';
@@ -24,7 +24,7 @@ class FileElement implements IDiffStatus {
2424
public dstRelPath: string,
2525
public status: StatusCode,
2626
public isSubmodule: boolean) {}
27-
27+
2828
get label(): string {
2929
return path.basename(this.dstAbsPath)
3030
}
@@ -109,11 +109,10 @@ export class GitTreeCompareProvider implements TreeDataProvider<Element>, Dispos
109109
private repository: Repository | undefined;
110110
private baseRef: string;
111111
private viewAsList = false;
112-
112+
113113
// Static state of repository
114114
private workspaceFolder: string;
115115
private absGitDir: string;
116-
private absGitCommonDir: string;
117116
private repoRoot: FolderAbsPath;
118117

119118
// Dynamic state of repository
@@ -127,7 +126,7 @@ export class GitTreeCompareProvider implements TreeDataProvider<Element>, Dispos
127126
// Diff results
128127
private filesInsideTreeRoot: Map<FolderAbsPath, IDiffStatus[]>;
129128
private filesOutsideTreeRoot: Map<FolderAbsPath, IDiffStatus[]>;
130-
129+
131130
// UI parameters, derived
132131
private treeRoot: FolderAbsPath;
133132

@@ -193,7 +192,6 @@ export class GitTreeCompareProvider implements TreeDataProvider<Element>, Dispos
193192
const dotGit = await this.git.getRepositoryDotGit(repositoryRoot);
194193
const repository = this.git.open(repositoryRoot, dotGit);
195194
const absGitDir = await getAbsGitDir(repository);
196-
const absGitCommonDir = await getAbsGitCommonDir(repository);
197195
const repoRoot = normalizePath(repository.root);
198196

199197
const workspaceFolders = getWorkspaceFolders(repoRoot);
@@ -202,7 +200,6 @@ export class GitTreeCompareProvider implements TreeDataProvider<Element>, Dispos
202200
}
203201

204202
this.repository = repository;
205-
this.absGitCommonDir = absGitCommonDir;
206203
this.absGitDir = absGitDir;
207204
this.repoRoot = repoRoot;
208205

@@ -431,7 +428,7 @@ export class GitTreeCompareProvider implements TreeDataProvider<Element>, Dispos
431428
const HEAD = await this.repository!.getHEAD();
432429
// if detached HEAD, then .commit exists, otherwise only .name
433430
const headName = HEAD.name;
434-
const headCommit = HEAD.commit || await getBranchCommit(this.absGitCommonDir, HEAD.name!);
431+
const headCommit = HEAD.commit || await getBranchCommit(HEAD.name!, this.repository!);
435432
if (baseRef) {
436433
const exists = await this.isRefExisting(baseRef) || await this.isCommitExisting(baseRef);
437434
if (!exists) {
@@ -440,7 +437,7 @@ export class GitTreeCompareProvider implements TreeDataProvider<Element>, Dispos
440437
}
441438
}
442439
if (!baseRef) {
443-
baseRef = await this.getStoredBaseRef();
440+
baseRef = await this.getStoredBaseRef();
444441
}
445442
if (!baseRef) {
446443
baseRef = await getDefaultBranch(this.repository!, HEAD);
@@ -602,7 +599,7 @@ export class GitTreeCompareProvider implements TreeDataProvider<Element>, Dispos
602599
// If HEAD is not detached, check if the symbolic ref resolves to a different commit.
603600
if (this.headName) {
604601
// this.repository.getBranch() is not used here to avoid git invocation overhead
605-
const headCommit = await getBranchCommit(this.absGitCommonDir, this.headName);
602+
const headCommit = await getBranchCommit(this.headName, this.repository!);
606603
if (this.headCommit !== headCommit) {
607604
return true;
608605
}
@@ -688,8 +685,8 @@ export class GitTreeCompareProvider implements TreeDataProvider<Element>, Dispos
688685
if (oldTreeRootIsRepo != this.treeRootIsRepo) {
689686
this.updateTreeRootFolder();
690687
}
691-
692-
if (oldFullDiff != this.fullDiff ||
688+
689+
if (oldFullDiff != this.fullDiff ||
693690
oldFindRenames != this.findRenames ||
694691
oldRenameThreshold != this.renameThreshold ||
695692
oldTreeRoot != this.treeRoot ||
@@ -1039,7 +1036,7 @@ export class GitTreeCompareProvider implements TreeDataProvider<Element>, Dispos
10391036
} else {
10401037
throw new Error("unsupported item type");
10411038
}
1042-
1039+
10431040
if (this.baseRef === baseRef) {
10441041
return;
10451042
}

0 commit comments

Comments
 (0)