diff --git a/packages/reg-keygen-git-hash-plugin/src/commit-explorer.test.ts b/packages/reg-keygen-git-hash-plugin/src/commit-explorer.test.ts index 971c2a1e..4f2e5622 100644 --- a/packages/reg-keygen-git-hash-plugin/src/commit-explorer.test.ts +++ b/packages/reg-keygen-git-hash-plugin/src/commit-explorer.test.ts @@ -4,6 +4,8 @@ import { CommitExplorer } from "./commit-explorer"; import process from "process"; import path from "path"; +const GIT_LOG_COUNT_PER_PAGE_FOR_TEST = 2; + const rimraf = require("rimraf"); process.chdir("./test"); @@ -21,12 +23,12 @@ const copyGitFiles = (name: string) => { // assert.equal issue will be fixed in version using git-tiny-walker // test.serial("no commit", () => { // copyGitFiles("no-commit"); -// t.throws(() => new CommitExplorer().getCurrentCommitHash()); +// t.throws(() => new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getCurrentCommitHash()); // }); test("detached head", () => { copyGitFiles("detached-head"); - expect(() => new CommitExplorer().getCurrentBranchName()).toThrowError(); + expect(() => new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getCurrentBranchName()).toThrowError(); }); /* @@ -34,7 +36,7 @@ test("detached head", () => { */ test("initial commit", () => { copyGitFiles("initial-commit"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); assert.equal(null, baseHash); }); @@ -44,7 +46,7 @@ test("initial commit", () => { */ test("master two commits", () => { copyGitFiles("master-two-commits"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); assert.equal(null, baseHash); }); @@ -54,7 +56,7 @@ test("master two commits", () => { */ test("after create new branch", () => { copyGitFiles("after-create-new-branch"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); assert.equal(null, baseHash); }); @@ -65,7 +67,7 @@ test("after create new branch", () => { */ test("commit after create new branch", () => { copyGitFiles("commit-new-branch"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = execSync("git rev-parse expected", { encoding: "utf8" }).trim(); assert.equal(expected, baseHash); }); @@ -78,7 +80,7 @@ test("commit after create new branch", () => { */ test("two commits after create new branch", () => { copyGitFiles("two-commit-new-branch"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = execSync("git rev-parse expected", { encoding: "utf8" }).trim(); assert.equal(expected, baseHash); }); @@ -95,7 +97,7 @@ test("two commits after create new branch", () => { */ test("after catch up master merge", () => { copyGitFiles("after-catch-up-master"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = execSync("git rev-parse expected", { encoding: "utf8" }).trim(); assert.equal(expected, baseHash); }); @@ -113,7 +115,7 @@ test("after catch up master merge", () => { */ test("commit after merge", () => { copyGitFiles("commit-after-merge"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = execSync("git rev-parse expected", { encoding: "utf8" }).trim(); assert.equal(expected, baseHash); }); @@ -131,7 +133,7 @@ test("commit after merge", () => { test("master to catch up branch", () => { copyGitFiles("master-to-catch-up-branch"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = execSync("git rev-parse expected", { encoding: "utf8" }).trim(); assert.equal(expected, baseHash); }); @@ -157,7 +159,7 @@ test("master to catch up branch", () => { test("commit after catch up and merge", () => { copyGitFiles("commit-after-catch-up-and-merge"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = execSync("git rev-parse expected", { encoding: "utf8" }).trim(); assert.equal(expected, baseHash); }); @@ -175,7 +177,7 @@ test("commit after catch up and merge", () => { // * first commit test("after merge catch up", () => { copyGitFiles("after-merge-catch-up"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = execSync("git rev-parse expected", { encoding: "utf8" }).trim(); assert.equal(expected, baseHash); }); @@ -195,7 +197,7 @@ test("after merge catch up", () => { // * first commit test("merge catch up and commit", () => { copyGitFiles("merge-catch-up-then-commit"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = execSync("git rev-parse expected", { encoding: "utf8" }).trim(); assert.equal(expected, baseHash); }); @@ -213,14 +215,14 @@ test("merge catch up and commit", () => { // * (tag: expected) init import test("merge multipe commit three", () => { copyGitFiles("merge-multipe-commit-three"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = execSync("git rev-parse expected", { encoding: "utf8" }).trim(); assert.equal(expected, baseHash); }); test("error patter found in reg-suit repository", () => { copyGitFiles("reg-suit-error-pattern"); - const baseHash = new CommitExplorer().getBaseCommitHash(); + const baseHash = new CommitExplorer(GIT_LOG_COUNT_PER_PAGE_FOR_TEST).getBaseCommitHash(); const expected = "49d38a929ae3675a1c79216709c35884f0b78900"; assert.equal(expected, baseHash); }); diff --git a/packages/reg-keygen-git-hash-plugin/src/commit-explorer.ts b/packages/reg-keygen-git-hash-plugin/src/commit-explorer.ts index c15d820d..dea1cc16 100644 --- a/packages/reg-keygen-git-hash-plugin/src/commit-explorer.ts +++ b/packages/reg-keygen-git-hash-plugin/src/commit-explorer.ts @@ -4,17 +4,23 @@ export type CommitNode = string[]; export class CommitExplorer { private _gitCmdClient = new GitCmdClient(); - private _commitNodes!: CommitNode[]; private _branchName!: string; + private _commitHash!: string; + private _branchHash!: string; private _branchNameCache: { [hash: string]: string[] } = {}; + constructor(private _gitLogCountPerPage = 10) {} + /* * e.g. return `[["a38df15", "8e1ac3a"], ["8e1ac3a", "7ba8507"]]`. * The first element of node means commit hash, rest elements means parent commit hashes. */ - getCommitNodes(): CommitNode[] { + getCommitNodes(skip: number): CommitNode[] { return this._gitCmdClient - .logGraph() + .logGraph({ + number: this._gitLogCountPerPage, + skip, + }) .split("\n") .map((hashes: string) => hashes @@ -95,11 +101,11 @@ export class CommitExplorer { .map(b => b.hash)[0]; } - getCandidateHashes(): string[] { - const mergedBranches = this.getBranchNames(this._commitNodes[0][0]).filter( + getCandidateHashes(commitNotes: ReadonlyArray<CommitNode>): string[] { + const mergedBranches = this.getBranchNames(this._commitHash).filter( b => !b.endsWith("/" + this._branchName) && b !== this._branchName, ); - return this._commitNodes + return commitNotes .map(c => c[0]) .filter(c => { const branches = this.getBranchNames(c); @@ -125,15 +131,31 @@ export class CommitExplorer { return target; } + getBaseCommitHashRec(cursor: number = 0): string | null { + const commitNotes = this.getCommitNodes(cursor); + if (commitNotes.length === 0) return null; + + const candidateHashes = this.getCandidateHashes(commitNotes); + const baseHash = this.findBaseCommitHash(candidateHashes, this._branchHash); + if (!baseHash) { + const lastCommitNode = commitNotes.at(-1)!; + if (lastCommitNode.length === 1) return null; + const nextCursor = cursor + this._gitLogCountPerPage; + if (nextCursor === 300) return null; + return this.getBaseCommitHashRec(nextCursor); + } + + const result = this._gitCmdClient.revParse(baseHash).replace("\n", ""); + return result ? result : null; + } + getBaseCommitHash(): string | null { this._branchName = this.getCurrentBranchName(); - this._commitNodes = this.getCommitNodes(); - const candidateHashes = this.getCandidateHashes(); + this._commitHash = this.getCurrentCommitHash(); const branchHash = this.getBranchHash(); - if (!branchHash) return null; - const baseHash = this.findBaseCommitHash(candidateHashes, branchHash); - if (!baseHash) return null; - const result = this._gitCmdClient.revParse(baseHash).replace("\n", ""); - return result ? result : null; + if (branchHash === undefined) return null; + this._branchHash = branchHash; + + return this.getBaseCommitHashRec(); } } diff --git a/packages/reg-keygen-git-hash-plugin/src/git-cmd-client.ts b/packages/reg-keygen-git-hash-plugin/src/git-cmd-client.ts index ff6d80aa..cf96858b 100644 --- a/packages/reg-keygen-git-hash-plugin/src/git-cmd-client.ts +++ b/packages/reg-keygen-git-hash-plugin/src/git-cmd-client.ts @@ -31,8 +31,26 @@ export class GitCmdClient { return execSync(shellEscape(["git", "log", "--oneline", `${a}..${b}`]), { encoding: "utf8" }); } - logGraph() { - return execSync('git log -n 300 --graph --pretty=format:"%h %p"', { encoding: "utf8" }); + logGraph( + options?: Partial<{ + number: number; + skip: number; + }>, + ) { + const { number = 300, skip = 0 } = options ?? {}; + return execSync( + shellEscape([ + "git", + "log", + "-n", + number.toString(), + "--skip", + skip.toString(), + "--graph", + "--pretty=format:%h %p", + ]), + { encoding: "utf8" }, + ); } mergeBase(a: string, b: string) {