Skip to content

Commit 18994b5

Browse files
committed
fix: fix review
1 parent aedbc53 commit 18994b5

2 files changed

Lines changed: 113 additions & 5 deletions

File tree

packages/git/src/collectGitFacts.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,39 @@ export type CollectGitFactsOptions = {
99
ancestorLimit?: number;
1010
};
1111

12+
const stripRemotePrefix = (upstreamRef: string): string => {
13+
const slashIndex = upstreamRef.indexOf("/");
14+
15+
return slashIndex >= 0 ? upstreamRef.slice(slashIndex + 1) : upstreamRef;
16+
};
17+
18+
const resolveBranch = (cwd?: string): string | undefined => {
19+
const branchRaw = runGit(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
20+
21+
if (!branchRaw || branchRaw === "HEAD") {
22+
return undefined;
23+
}
24+
25+
const upstreamBranch = runGit(["rev-parse", "--abbrev-ref", "@{u}"], cwd);
26+
27+
if (upstreamBranch) {
28+
return stripRemotePrefix(upstreamBranch);
29+
}
30+
31+
return branchRaw;
32+
};
33+
1234
const collectLocalState = (cwd?: string): GitLocalState => {
1335
const statusPorcelain = runGit(["status", "--porcelain"], cwd) ?? "";
1436
const branchRaw = runGit(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
1537
const detachedHead = branchRaw === "HEAD";
38+
const headCommit = runGit(["rev-parse", "--verify", "HEAD"], cwd);
1639
const upstreamCommit = runGit(["rev-parse", "--verify", "@{u}"], cwd);
1740
const upstreamBranch = runGit(["rev-parse", "--abbrev-ref", "@{u}"], cwd);
1841

1942
return {
2043
uncommittedChanges: statusPorcelain.length > 0,
21-
unpublishedCommit: !upstreamCommit,
44+
unpublishedCommit: !upstreamCommit || headCommit !== upstreamCommit,
2245
unpublishedBranch: !upstreamBranch,
2346
detachedHead,
2447
};
@@ -37,8 +60,7 @@ export const collectGitFacts = (options: CollectGitFactsOptions = {}): GitFacts
3760
return undefined;
3861
}
3962

40-
const branchRaw = runGit(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
41-
const branch = branchRaw && branchRaw !== "HEAD" ? branchRaw : undefined;
63+
const branch = resolveBranch(cwd);
4264

4365
const revList = runGit(["rev-list", "--first-parent", commit, `--max-count=${ancestorLimit + 1}`], cwd);
4466

@@ -50,7 +72,7 @@ export const collectGitFacts = (options: CollectGitFactsOptions = {}): GitFacts
5072
.split("\n")
5173
.map((line) => line.trim())
5274
.filter(Boolean)
53-
.filter((hash) => hash !== commit);
75+
.slice(1);
5476

5577
return {
5678
commit,

packages/git/test/collectGitFacts.test.ts

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ describe("collectGitFacts", () => {
9494
firstParentAncestors: [COMMIT_B, COMMIT_A],
9595
localState: {
9696
uncommittedChanges: false,
97-
unpublishedCommit: false,
97+
unpublishedCommit: true,
9898
unpublishedBranch: false,
9999
detachedHead: false,
100100
},
@@ -169,6 +169,92 @@ describe("collectGitFacts", () => {
169169
expect(collectGitFacts()?.localState?.uncommittedChanges).toBe(true);
170170
});
171171

172+
it("marks unpublished commit when HEAD is ahead of upstream", () => {
173+
mockHappyGit();
174+
175+
expect(collectGitFacts()?.localState?.unpublishedCommit).toBe(true);
176+
});
177+
178+
it("marks published commit when HEAD matches upstream", () => {
179+
mockHappyGit();
180+
181+
runGit.mockImplementation((args: string[]) => {
182+
const key = args.join(" ");
183+
184+
if (key === "rev-parse --verify @{u}") {
185+
return COMMIT_C;
186+
}
187+
188+
if (key === "rev-parse --is-inside-work-tree") {
189+
return "true";
190+
}
191+
192+
if (key === "rev-parse HEAD" || key === "rev-parse --verify HEAD") {
193+
return COMMIT_C;
194+
}
195+
196+
if (key === "rev-parse --abbrev-ref HEAD") {
197+
return "main";
198+
}
199+
200+
if (key.startsWith("rev-list --first-parent")) {
201+
return [COMMIT_C, COMMIT_B].join("\n");
202+
}
203+
204+
if (key === "status --porcelain") {
205+
return "";
206+
}
207+
208+
if (key === "rev-parse --abbrev-ref @{u}") {
209+
return "origin/main";
210+
}
211+
212+
return undefined;
213+
});
214+
215+
expect(collectGitFacts()?.localState?.unpublishedCommit).toBe(false);
216+
});
217+
218+
it("prefers upstream branch name over local branch name", () => {
219+
mockHappyGit();
220+
221+
runGit.mockImplementation((args: string[]) => {
222+
const key = args.join(" ");
223+
224+
if (key === "rev-parse --abbrev-ref HEAD") {
225+
return "local-feature";
226+
}
227+
228+
if (key === "rev-parse --abbrev-ref @{u}") {
229+
return "origin/feature/foo";
230+
}
231+
232+
if (key === "rev-parse --is-inside-work-tree") {
233+
return "true";
234+
}
235+
236+
if (key === "rev-parse HEAD" || key === "rev-parse --verify HEAD") {
237+
return COMMIT_C;
238+
}
239+
240+
if (key.startsWith("rev-list --first-parent")) {
241+
return [COMMIT_C, COMMIT_B].join("\n");
242+
}
243+
244+
if (key === "status --porcelain") {
245+
return "";
246+
}
247+
248+
if (key === "rev-parse --verify @{u}") {
249+
return COMMIT_B;
250+
}
251+
252+
return undefined;
253+
});
254+
255+
expect(collectGitFacts()?.branch).toBe("feature/foo");
256+
});
257+
172258
it("marks unpublished commit and branch when upstream is missing", () => {
173259
mockHappyGit();
174260

0 commit comments

Comments
 (0)