From 502bce76c07cc59f317192715f3b42a22a8c2d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=98=88=EC=A7=84?= Date: Sat, 3 Sep 2022 17:02:21 +0900 Subject: [PATCH 1/7] feat: implement Stem --- packages/analysis-engine/src/commit.util.ts | 19 ++++ packages/analysis-engine/src/dag.ts | 27 ------ packages/analysis-engine/src/queue.ts | 24 +++++ packages/analysis-engine/src/stem.spec.ts | 93 ++++++++++++++++++- packages/analysis-engine/src/stem.ts | 88 +++++++++++++++++- .../analysis-engine/src/types/CommitNode.ts | 8 ++ packages/analysis-engine/src/types/Stem.ts | 8 ++ 7 files changed, 236 insertions(+), 31 deletions(-) create mode 100644 packages/analysis-engine/src/commit.util.ts delete mode 100644 packages/analysis-engine/src/dag.ts create mode 100644 packages/analysis-engine/src/queue.ts create mode 100644 packages/analysis-engine/src/types/CommitNode.ts create mode 100644 packages/analysis-engine/src/types/Stem.ts diff --git a/packages/analysis-engine/src/commit.util.ts b/packages/analysis-engine/src/commit.util.ts new file mode 100644 index 00000000..9e7282b8 --- /dev/null +++ b/packages/analysis-engine/src/commit.util.ts @@ -0,0 +1,19 @@ +import { CommitNode } from "./types/CommitNode"; +import { CommitRaw } from "./types/CommitRaw"; + +type CommitDict = Map; + +export function generateCommitNodeDict(commits: CommitRaw[]): CommitDict { + return new Map( + commits.map( + (commit) => [commit.id, { traversed: false, commit } as CommitNode], + [] + ) + ); +} + +export function getLeafNodes(commitDict: CommitDict): CommitNode[] { + const leafs: CommitNode[] = []; + commitDict.forEach((node) => node.commit.branches.length && leafs.push(node)); + return leafs; +} diff --git a/packages/analysis-engine/src/dag.ts b/packages/analysis-engine/src/dag.ts deleted file mode 100644 index 68d65946..00000000 --- a/packages/analysis-engine/src/dag.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { CommitRaw } from "./NodeTypes.temp"; - -export interface CommitDagNode { - id: string; - parents: string[]; - commit: CommitRaw; -} - -export type CommitDag = Map; - -function generateDagNode(commit: CommitRaw): CommitDagNode { - return { - id: commit.id, - parents: commit.parents, - commit, - } as CommitDagNode; -} - -export function buildDag(commitList: CommitRaw[]): CommitDag { - const dag: CommitDag = new Map(); - - commitList - .map((commit) => generateDagNode(commit)) - .forEach((node) => dag.set(node.id, node)); - - return dag; -} diff --git a/packages/analysis-engine/src/queue.ts b/packages/analysis-engine/src/queue.ts new file mode 100644 index 00000000..dc7fdada --- /dev/null +++ b/packages/analysis-engine/src/queue.ts @@ -0,0 +1,24 @@ +export default class Queue { + private queue: Array = []; + + push(node: T): void { + this.queue.push(node); + this.queue = this.queue.sort(); + } + + pop(): T | undefined { + return this.queue.shift(); + } + + isEmpty(): boolean { + return this.queue.length === 0; + } + + pushFront(node: T): void { + this.queue.unshift(node); + } + + pushBack(node: T): void { + this.queue.push(node); + } +} diff --git a/packages/analysis-engine/src/stem.spec.ts b/packages/analysis-engine/src/stem.spec.ts index ffe091cd..4e10fc2f 100644 --- a/packages/analysis-engine/src/stem.spec.ts +++ b/packages/analysis-engine/src/stem.spec.ts @@ -1,7 +1,96 @@ -import stem from "./stem"; +import { generateCommitNodeDict, getLeafNodes } from "./commit.util"; +import { buildStemDict } from "./stem"; +import { CommitNode } from "./types/CommitNode"; +import { CommitRaw } from "./types/CommitRaw"; + +const dummy = [ + { id: "1", parents: [], branches: [] }, + { id: "2", parents: ["1"], branches: [] }, + { id: "3", parents: ["2", "8"], branches: [] }, + { id: "4", parents: ["3"], branches: [] }, + { id: "5", parents: ["4", "10"], branches: [] }, + { id: "6", parents: ["5"], branches: [] }, + { id: "7", parents: ["6"], branches: ["main"] }, + { id: "8", parents: ["1"], branches: [] }, + { id: "9", parents: ["8"], branches: [] }, + { id: "10", parents: ["9"], branches: [] }, + { id: "11", parents: ["3"], branches: [] }, + { id: "12", parents: ["11"], branches: [] }, + { id: "13", parents: ["12"], branches: [] }, + { id: "14", parents: ["13"], branches: ["dev"] }, +]; + +function createTestCommit({ + id, + parents, + branches, +}: { + id: string; + parents: string[]; + branches: string[]; +}): CommitRaw { + return { + id, + parents, + branches, + tags: [], + author: { + name: "", + email: "", + }, + authorDate: "", + committer: { + name: "", + email: "", + }, + committerDate: "", + message: "", + differenceStatistic: { + totalInsertionCount: 0, + totalDeletionCount: 0, + fileDictionary: {}, + }, + } as CommitRaw; +} describe("stem", () => { + let commits: CommitRaw[] = []; + let commitDict: Map; + + beforeEach(() => { + commits = dummy.map(createTestCommit); + commitDict = generateCommitNodeDict(commits); + }); + it("temp test", () => { - expect(stem()).toBe("stem"); + const stemDict = buildStemDict(commitDict); + expect(stemDict).toBeInstanceOf(Map); + }); + + it("should get leaf nodes", () => { + const leafNodes = getLeafNodes(commitDict); + expect(leafNodes.map((node) => node.commit.id)).toEqual(["7", "14"]); + }); + + it("should make stem", () => { + const stemDict = buildStemDict(commitDict); + expect(stemDict.get("main")?.nodes.map((node) => node.commit.id)).toEqual([ + "7", + "6", + "5", + "4", + "3", + "2", + "1", + ]); + expect( + stemDict.get("implicit")?.nodes.map((node) => node.commit.id) + ).toEqual(["10", "9", "8"]); + expect(stemDict.get("dev")?.nodes.map((node) => node.commit.id)).toEqual([ + "14", + "13", + "12", + "11", + ]); }); }); diff --git a/packages/analysis-engine/src/stem.ts b/packages/analysis-engine/src/stem.ts index 8db1fc14..fc2b02c1 100644 --- a/packages/analysis-engine/src/stem.ts +++ b/packages/analysis-engine/src/stem.ts @@ -1,3 +1,87 @@ -export const stem = () => "stem"; +import { getLeafNodes } from "./commit.util"; +import Queue from "./queue"; +import { CommitNode } from "./types/CommitNode"; +import { Stem } from "./types/Stem"; -export default stem; +function generateStem(stemNodes: CommitNode[]): Stem { + const tail = stemNodes[0]; + return { + id: tail?.stemId ?? tail?.commit.id, + headId: stemNodes[stemNodes.length - 1].commit.id, + tailId: tail?.commit.id, + nodes: stemNodes, + }; +} + +export function getStemNodes( + tailId: string, + commitDict: Map, + q: Queue +): CommitNode[] { + let now: CommitNode | undefined = commitDict.get(tailId); + const stemId: string = now?.commit.branches[0] ?? "implicit"; + const nodes: CommitNode[] = []; + while (now && !now.traversed) { + now.stemId = stemId; + now.traversed = true; + if (now.commit.parents.length > 1) { + now.commit.parents.forEach((parent, idx) => { + if (idx === 0) return; + const parentNode = commitDict.get(parent); + if (parentNode) { + q.push(parentNode); + } + }, q); + } + nodes.push(now); + now = commitDict.get(now.commit.parents?.[0]); + } + return nodes; +} + +export function buildStemDict( + commitDict: Map +): Map { + const stemDict = new Map(); + + const q = new Queue(); + q.push.bind(q); + + /** + * 처음 큐에 담기는 순서 + * 1. main + * 2. sub-branches + * 3. HEAD + */ + const leafNodes = getLeafNodes(commitDict); + const mainNode = leafNodes.find( + (node) => + node.commit.branches.includes("main") || + node.commit.branches.includes("master") + ); + const headNode = leafNodes.find((node) => + node.commit.branches.includes("HEAD") + ); + leafNodes + .filter( + (node) => + node.commit.id !== mainNode?.commit.id && + node.commit.id !== headNode?.commit.id + ) + .forEach((node) => q.push(node), q); + if (mainNode) q.pushFront(mainNode); + if (headNode) q.pushBack(headNode); + + while (!q.isEmpty()) { + const tail = q.pop(); + // eslint-disable-next-line no-continue + if (!tail) continue; + const nodes = getStemNodes(tail.commit.id, commitDict, q); + // eslint-disable-next-line no-continue + if (nodes.length === 0) continue; + const stem: Stem = generateStem(nodes); + stemDict.set(stem.id, stem); + } + + return stemDict; +} diff --git a/packages/analysis-engine/src/types/CommitNode.ts b/packages/analysis-engine/src/types/CommitNode.ts new file mode 100644 index 00000000..39476a07 --- /dev/null +++ b/packages/analysis-engine/src/types/CommitNode.ts @@ -0,0 +1,8 @@ +import { CommitRaw } from "./CommitRaw"; + +export interface CommitNode { + // 순회 이전에는 stemId가 존재하지 않음. + stemId?: string; + traversed: boolean; + commit: CommitRaw; +} diff --git a/packages/analysis-engine/src/types/Stem.ts b/packages/analysis-engine/src/types/Stem.ts new file mode 100644 index 00000000..ae5c16e0 --- /dev/null +++ b/packages/analysis-engine/src/types/Stem.ts @@ -0,0 +1,8 @@ +import { CommitNode } from "./CommitNode"; + +export interface Stem { + id: string; + headId: string; + tailId: string; + nodes: CommitNode[]; +} From 8bf268aabf215999bebd8bc04ce1915f5c96d944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=98=88=EC=A7=84?= Date: Sat, 3 Sep 2022 17:13:46 +0900 Subject: [PATCH 2/7] feat: change implicit branch stem naming --- packages/analysis-engine/src/stem.spec.ts | 2 +- packages/analysis-engine/src/stem.ts | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/analysis-engine/src/stem.spec.ts b/packages/analysis-engine/src/stem.spec.ts index 4e10fc2f..ebf51b89 100644 --- a/packages/analysis-engine/src/stem.spec.ts +++ b/packages/analysis-engine/src/stem.spec.ts @@ -84,7 +84,7 @@ describe("stem", () => { "1", ]); expect( - stemDict.get("implicit")?.nodes.map((node) => node.commit.id) + stemDict.get("implicit-1")?.nodes.map((node) => node.commit.id) ).toEqual(["10", "9", "8"]); expect(stemDict.get("dev")?.nodes.map((node) => node.commit.id)).toEqual([ "14", diff --git a/packages/analysis-engine/src/stem.ts b/packages/analysis-engine/src/stem.ts index fc2b02c1..cfdef26c 100644 --- a/packages/analysis-engine/src/stem.ts +++ b/packages/analysis-engine/src/stem.ts @@ -16,10 +16,13 @@ function generateStem(stemNodes: CommitNode[]): Stem { export function getStemNodes( tailId: string, commitDict: Map, - q: Queue + q: Queue, + implicitBranchCount: number ): CommitNode[] { let now: CommitNode | undefined = commitDict.get(tailId); - const stemId: string = now?.commit.branches[0] ?? "implicit"; + const stemId: string = + now?.commit.branches[0] ?? `implicit-${implicitBranchCount}`; + const nodes: CommitNode[] = []; while (now && !now.traversed) { now.stemId = stemId; @@ -72,11 +75,21 @@ export function buildStemDict( if (mainNode) q.pushFront(mainNode); if (headNode) q.pushBack(headNode); + let implicitBranchCount = 1; + while (!q.isEmpty()) { const tail = q.pop(); // eslint-disable-next-line no-continue if (!tail) continue; - const nodes = getStemNodes(tail.commit.id, commitDict, q); + const nodes = getStemNodes( + tail.commit.id, + commitDict, + q, + implicitBranchCount + ); + if (tail.commit.branches.length === 0) { + implicitBranchCount += 1; + } // eslint-disable-next-line no-continue if (nodes.length === 0) continue; const stem: Stem = generateStem(nodes); From 9de3230e9085146ddabad876e6d575abceee2988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=98=88=EC=A7=84?= Date: Sat, 3 Sep 2022 17:18:17 +0900 Subject: [PATCH 3/7] test: add test for HEAD --- packages/analysis-engine/src/stem.spec.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/analysis-engine/src/stem.spec.ts b/packages/analysis-engine/src/stem.spec.ts index ebf51b89..53f131df 100644 --- a/packages/analysis-engine/src/stem.spec.ts +++ b/packages/analysis-engine/src/stem.spec.ts @@ -18,6 +18,8 @@ const dummy = [ { id: "12", parents: ["11"], branches: [] }, { id: "13", parents: ["12"], branches: [] }, { id: "14", parents: ["13"], branches: ["dev"] }, + { id: "15", parents: ["13", "10"], branches: [] }, + { id: "16", parents: ["15"], branches: ["HEAD"] }, ]; function createTestCommit({ @@ -69,7 +71,7 @@ describe("stem", () => { it("should get leaf nodes", () => { const leafNodes = getLeafNodes(commitDict); - expect(leafNodes.map((node) => node.commit.id)).toEqual(["7", "14"]); + expect(leafNodes.map((node) => node.commit.id)).toEqual(["7", "14", "16"]); }); it("should make stem", () => { @@ -92,5 +94,9 @@ describe("stem", () => { "12", "11", ]); + expect(stemDict.get("HEAD")?.nodes.map((node) => node.commit.id)).toEqual([ + "16", + "15", + ]); }); }); From bde4103586e055ff6a999be5cf16cc767995b3d2 Mon Sep 17 00:00:00 2001 From: ooooorobo Date: Tue, 6 Sep 2022 22:01:56 +0900 Subject: [PATCH 4/7] chore: set off the eslint no-continue rule --- packages/analysis-engine/.eslintrc.json | 3 ++- packages/analysis-engine/src/stem.ts | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/analysis-engine/.eslintrc.json b/packages/analysis-engine/.eslintrc.json index 48639701..2ee01737 100644 --- a/packages/analysis-engine/.eslintrc.json +++ b/packages/analysis-engine/.eslintrc.json @@ -31,6 +31,7 @@ "object-shorthand": "off", "class-methods-use-this": "off", "import/extensions": "off", - "import/no-unresolved": "off" + "import/no-unresolved": "off", + "no-continue": "off" } } diff --git a/packages/analysis-engine/src/stem.ts b/packages/analysis-engine/src/stem.ts index cfdef26c..07b3081b 100644 --- a/packages/analysis-engine/src/stem.ts +++ b/packages/analysis-engine/src/stem.ts @@ -79,7 +79,6 @@ export function buildStemDict( while (!q.isEmpty()) { const tail = q.pop(); - // eslint-disable-next-line no-continue if (!tail) continue; const nodes = getStemNodes( tail.commit.id, @@ -90,7 +89,6 @@ export function buildStemDict( if (tail.commit.branches.length === 0) { implicitBranchCount += 1; } - // eslint-disable-next-line no-continue if (nodes.length === 0) continue; const stem: Stem = generateStem(nodes); stemDict.set(stem.id, stem); From 4898c30c9c8badcfe4a06de86d3bfe3cf81331ef Mon Sep 17 00:00:00 2001 From: ooooorobo Date: Tue, 6 Sep 2022 22:03:38 +0900 Subject: [PATCH 5/7] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/analysis-engine/src/commit.util.ts | 13 +++--- packages/analysis-engine/src/queue.ts | 2 +- packages/analysis-engine/src/stem.spec.ts | 2 +- packages/analysis-engine/src/stem.ts | 40 +++++++------------ .../analysis-engine/src/types/CommitNode.ts | 1 - packages/analysis-engine/src/types/Stem.ts | 3 -- 6 files changed, 22 insertions(+), 39 deletions(-) diff --git a/packages/analysis-engine/src/commit.util.ts b/packages/analysis-engine/src/commit.util.ts index 9e7282b8..a1ec70b6 100644 --- a/packages/analysis-engine/src/commit.util.ts +++ b/packages/analysis-engine/src/commit.util.ts @@ -5,15 +5,14 @@ type CommitDict = Map; export function generateCommitNodeDict(commits: CommitRaw[]): CommitDict { return new Map( - commits.map( - (commit) => [commit.id, { traversed: false, commit } as CommitNode], - [] - ) + commits.map((commit) => [commit.id, { commit } as CommitNode]) ); } export function getLeafNodes(commitDict: CommitDict): CommitNode[] { - const leafs: CommitNode[] = []; - commitDict.forEach((node) => node.commit.branches.length && leafs.push(node)); - return leafs; + const leafNodes: CommitNode[] = []; + commitDict.forEach( + (node) => node.commit.branches.length && leafNodes.push(node) + ); + return leafNodes; } diff --git a/packages/analysis-engine/src/queue.ts b/packages/analysis-engine/src/queue.ts index dc7fdada..0628f95f 100644 --- a/packages/analysis-engine/src/queue.ts +++ b/packages/analysis-engine/src/queue.ts @@ -3,7 +3,7 @@ export default class Queue { push(node: T): void { this.queue.push(node); - this.queue = this.queue.sort(); + this.queue.sort(); } pop(): T | undefined { diff --git a/packages/analysis-engine/src/stem.spec.ts b/packages/analysis-engine/src/stem.spec.ts index 53f131df..4a837b29 100644 --- a/packages/analysis-engine/src/stem.spec.ts +++ b/packages/analysis-engine/src/stem.spec.ts @@ -3,7 +3,7 @@ import { buildStemDict } from "./stem"; import { CommitNode } from "./types/CommitNode"; import { CommitRaw } from "./types/CommitRaw"; -const dummy = [ +const dummy: Pick[] = [ { id: "1", parents: [], branches: [] }, { id: "2", parents: ["1"], branches: [] }, { id: "3", parents: ["2", "8"], branches: [] }, diff --git a/packages/analysis-engine/src/stem.ts b/packages/analysis-engine/src/stem.ts index 07b3081b..254fd4a5 100644 --- a/packages/analysis-engine/src/stem.ts +++ b/packages/analysis-engine/src/stem.ts @@ -3,30 +3,18 @@ import Queue from "./queue"; import { CommitNode } from "./types/CommitNode"; import { Stem } from "./types/Stem"; -function generateStem(stemNodes: CommitNode[]): Stem { - const tail = stemNodes[0]; - return { - id: tail?.stemId ?? tail?.commit.id, - headId: stemNodes[stemNodes.length - 1].commit.id, - tailId: tail?.commit.id, - nodes: stemNodes, - }; -} - export function getStemNodes( tailId: string, commitDict: Map, q: Queue, - implicitBranchCount: number + stemId: string ): CommitNode[] { - let now: CommitNode | undefined = commitDict.get(tailId); - const stemId: string = - now?.commit.branches[0] ?? `implicit-${implicitBranchCount}`; + let now = commitDict.get(tailId); + if (!now) return []; const nodes: CommitNode[] = []; - while (now && !now.traversed) { + while (now && !now.stemId) { now.stemId = stemId; - now.traversed = true; if (now.commit.parents.length > 1) { now.commit.parents.forEach((parent, idx) => { if (idx === 0) return; @@ -75,23 +63,23 @@ export function buildStemDict( if (mainNode) q.pushFront(mainNode); if (headNode) q.pushBack(headNode); - let implicitBranchCount = 1; + let implicitBranchNumber = 1; while (!q.isEmpty()) { const tail = q.pop(); if (!tail) continue; - const nodes = getStemNodes( - tail.commit.id, - commitDict, - q, - implicitBranchCount - ); + + const stemId = + tail.commit.branches[0] ?? `implicit-${implicitBranchNumber}`; if (tail.commit.branches.length === 0) { - implicitBranchCount += 1; + implicitBranchNumber += 1; } + + const nodes = getStemNodes(tail.commit.id, commitDict, q, stemId); if (nodes.length === 0) continue; - const stem: Stem = generateStem(nodes); - stemDict.set(stem.id, stem); + + const stem: Stem = { nodes }; + stemDict.set(stemId, stem); } return stemDict; diff --git a/packages/analysis-engine/src/types/CommitNode.ts b/packages/analysis-engine/src/types/CommitNode.ts index 39476a07..689a0dc5 100644 --- a/packages/analysis-engine/src/types/CommitNode.ts +++ b/packages/analysis-engine/src/types/CommitNode.ts @@ -3,6 +3,5 @@ import { CommitRaw } from "./CommitRaw"; export interface CommitNode { // 순회 이전에는 stemId가 존재하지 않음. stemId?: string; - traversed: boolean; commit: CommitRaw; } diff --git a/packages/analysis-engine/src/types/Stem.ts b/packages/analysis-engine/src/types/Stem.ts index ae5c16e0..b401ec89 100644 --- a/packages/analysis-engine/src/types/Stem.ts +++ b/packages/analysis-engine/src/types/Stem.ts @@ -1,8 +1,5 @@ import { CommitNode } from "./CommitNode"; export interface Stem { - id: string; - headId: string; - tailId: string; nodes: CommitNode[]; } From 9bc842e2f1fa1d83882c31cc41dbefc0ba300ea2 Mon Sep 17 00:00:00 2001 From: ooooorobo Date: Tue, 6 Sep 2022 23:23:19 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20queue=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C,=20constructor=EC=97=90=20=EC=A0=95=EB=A0=AC=20?= =?UTF-8?q?=EB=B9=84=EA=B5=90=20=ED=95=A8=EC=88=98=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/analysis-engine/src/queue.ts | 8 +- packages/analysis-engine/src/stem.spec.ts | 189 ++++++++++++++++------ packages/analysis-engine/src/stem.ts | 19 ++- 3 files changed, 166 insertions(+), 50 deletions(-) diff --git a/packages/analysis-engine/src/queue.ts b/packages/analysis-engine/src/queue.ts index 0628f95f..e6e46d75 100644 --- a/packages/analysis-engine/src/queue.ts +++ b/packages/analysis-engine/src/queue.ts @@ -1,9 +1,15 @@ export default class Queue { private queue: Array = []; + private readonly compareFn: (a: T, b: T) => number; + + constructor(compareFn: (a: T, b: T) => number) { + this.compareFn = compareFn; + } + push(node: T): void { this.queue.push(node); - this.queue.sort(); + this.queue.sort(this.compareFn); } pop(): T | undefined { diff --git a/packages/analysis-engine/src/stem.spec.ts b/packages/analysis-engine/src/stem.spec.ts index 4a837b29..d8701818 100644 --- a/packages/analysis-engine/src/stem.spec.ts +++ b/packages/analysis-engine/src/stem.spec.ts @@ -3,38 +3,130 @@ import { buildStemDict } from "./stem"; import { CommitNode } from "./types/CommitNode"; import { CommitRaw } from "./types/CommitRaw"; -const dummy: Pick[] = [ - { id: "1", parents: [], branches: [] }, - { id: "2", parents: ["1"], branches: [] }, - { id: "3", parents: ["2", "8"], branches: [] }, - { id: "4", parents: ["3"], branches: [] }, - { id: "5", parents: ["4", "10"], branches: [] }, - { id: "6", parents: ["5"], branches: [] }, - { id: "7", parents: ["6"], branches: ["main"] }, - { id: "8", parents: ["1"], branches: [] }, - { id: "9", parents: ["8"], branches: [] }, - { id: "10", parents: ["9"], branches: [] }, - { id: "11", parents: ["3"], branches: [] }, - { id: "12", parents: ["11"], branches: [] }, - { id: "13", parents: ["12"], branches: [] }, - { id: "14", parents: ["13"], branches: ["dev"] }, - { id: "15", parents: ["13", "10"], branches: [] }, - { id: "16", parents: ["15"], branches: ["HEAD"] }, +type FakeCommitData = Pick< + CommitRaw, + "id" | "parents" | "branches" | "committerDate" +>; + +const dummy: FakeCommitData[] = [ + // 1 + { + id: "a1a605b38df7462e14503a2a0bb8d7453df7c8ae", + parents: [], + branches: [], + committerDate: "Sat Sep 3 19:30:40 2022 +0900", + }, + // 2 + { + id: "10d086ff54073d5e9b634ffb378a3da4c15b05a9", + parents: ["a1a605b38df7462e14503a2a0bb8d7453df7c8ae"], + branches: [], + committerDate: "Sat Sep 3 19:30:58 2022 +0900", + }, + // 3 + { + id: "f72a762bd84cae2da0933e637f800a30d6a1840c", + parents: [ + "10d086ff54073d5e9b634ffb378a3da4c15b05a9", + "718352fcc051c2a8691d3d96e968d76f7bc6d846", + ], + branches: [], + committerDate: "Sat Sep 3 19:32:44 2022 +0900", + }, + // 4 + { + id: "699116bdd4e2de914e5f5df76cd5aac3e4b5babe", + parents: ["f72a762bd84cae2da0933e637f800a30d6a1840c"], + branches: [], + committerDate: "Sat Sep 3 19:32:55 2022 +0900", + }, + // 5 + { + id: "421fb1cbabae99dc314f3076ea17c0bfd16457cb", + parents: [ + "699116bdd4e2de914e5f5df76cd5aac3e4b5babe", + "704ba519d85c2d78914a1b7e5100bae19d36814b", + ], + branches: [], + committerDate: "Sat Sep 3 19:33:50 2022 +0900", + }, + // 6 + { + id: "d5fd016fac43cef3d270736cb169753495f58282", + parents: ["421fb1cbabae99dc314f3076ea17c0bfd16457cb"], + branches: ["main"], + committerDate: "Sat Sep 3 19:34:04 2022 +0900", + }, + // 8 + { + id: "718352fcc051c2a8691d3d96e968d76f7bc6d846", + parents: ["a1a605b38df7462e14503a2a0bb8d7453df7c8ae"], + branches: [], + committerDate: "Sat Sep 3 19:31:25 2022 +0900", + }, + // 9 + { + id: "e40da20d4c80677f272b6ed104c55b237ecaa601", + parents: ["718352fcc051c2a8691d3d96e968d76f7bc6d846"], + branches: [], + committerDate: "Sat Sep 3 19:33:10 2022 +0900", + }, + // 10 + { + id: "704ba519d85c2d78914a1b7e5100bae19d36814b", + parents: ["e40da20d4c80677f272b6ed104c55b237ecaa601"], + branches: [], + committerDate: "Sat Sep 3 19:33:14 2022 +0900", + }, + // 11 + { + id: "6f77d7232b08e9444791e3931acd3b1aa59abe32", + parents: ["f72a762bd84cae2da0933e637f800a30d6a1840c"], + branches: [], + committerDate: "Sat Sep 3 19:34:24 2022 +0900", + }, + // 12 + { + id: "48f1d4f2a1b7b0ac21095f3aa43f35f2cb733918", + parents: ["6f77d7232b08e9444791e3931acd3b1aa59abe32"], + branches: [], + committerDate: "Sat Sep 3 19:34:44 2022 +0900", + }, + // 13 + { + id: "0beb987c722838f5d4bfadfa631c0792cd83849b", + parents: ["48f1d4f2a1b7b0ac21095f3aa43f35f2cb733918"], + branches: [], + committerDate: "Sat Sep 3 19:34:45 2022 +0900", + }, + // 14 + { + id: "b6d5e7979c71e7e7e7b537838c0d249ec5e63375", + parents: ["0beb987c722838f5d4bfadfa631c0792cd83849b"], + branches: ["dev"], + committerDate: "Sat Sep 3 19:34:57 2022 +0900", + }, + // 15 + { + id: "dcb3b0752a99d5c9449710f7f781dc2b5bc22cd9", + parents: [ + "0beb987c722838f5d4bfadfa631c0792cd83849b", + "704ba519d85c2d78914a1b7e5100bae19d36814b", + ], + branches: [], + committerDate: "Sat Sep 3 19:37:35 2022 +0900", + }, + // 16 + { + id: "04b02e3efb9e432e3ce91f1b36bbdeb284fddcf5", + parents: ["dcb3b0752a99d5c9449710f7f781dc2b5bc22cd9"], + branches: ["HEAD"], + committerDate: "Sat Sep 3 19:37:53 2022 +0900", + }, ]; -function createTestCommit({ - id, - parents, - branches, -}: { - id: string; - parents: string[]; - branches: string[]; -}): CommitRaw { +function createTestCommit(fakeCommitData: FakeCommitData): CommitRaw { return { - id, - parents, - branches, tags: [], author: { name: "", @@ -45,13 +137,13 @@ function createTestCommit({ name: "", email: "", }, - committerDate: "", message: "", differenceStatistic: { totalInsertionCount: 0, totalDeletionCount: 0, fileDictionary: {}, }, + ...fakeCommitData, } as CommitRaw; } @@ -71,32 +163,39 @@ describe("stem", () => { it("should get leaf nodes", () => { const leafNodes = getLeafNodes(commitDict); - expect(leafNodes.map((node) => node.commit.id)).toEqual(["7", "14", "16"]); + expect(leafNodes.map((node) => node.commit.id)).toEqual([ + "d5fd016fac43cef3d270736cb169753495f58282", + "b6d5e7979c71e7e7e7b537838c0d249ec5e63375", + "04b02e3efb9e432e3ce91f1b36bbdeb284fddcf5", + ]); }); it("should make stem", () => { const stemDict = buildStemDict(commitDict); expect(stemDict.get("main")?.nodes.map((node) => node.commit.id)).toEqual([ - "7", - "6", - "5", - "4", - "3", - "2", - "1", + "d5fd016fac43cef3d270736cb169753495f58282", + "421fb1cbabae99dc314f3076ea17c0bfd16457cb", + "699116bdd4e2de914e5f5df76cd5aac3e4b5babe", + "f72a762bd84cae2da0933e637f800a30d6a1840c", + "10d086ff54073d5e9b634ffb378a3da4c15b05a9", + "a1a605b38df7462e14503a2a0bb8d7453df7c8ae", ]); expect( stemDict.get("implicit-1")?.nodes.map((node) => node.commit.id) - ).toEqual(["10", "9", "8"]); + ).toEqual([ + "704ba519d85c2d78914a1b7e5100bae19d36814b", + "e40da20d4c80677f272b6ed104c55b237ecaa601", + "718352fcc051c2a8691d3d96e968d76f7bc6d846", + ]); expect(stemDict.get("dev")?.nodes.map((node) => node.commit.id)).toEqual([ - "14", - "13", - "12", - "11", + "b6d5e7979c71e7e7e7b537838c0d249ec5e63375", + "0beb987c722838f5d4bfadfa631c0792cd83849b", + "48f1d4f2a1b7b0ac21095f3aa43f35f2cb733918", + "6f77d7232b08e9444791e3931acd3b1aa59abe32", ]); expect(stemDict.get("HEAD")?.nodes.map((node) => node.commit.id)).toEqual([ - "16", - "15", + "04b02e3efb9e432e3ce91f1b36bbdeb284fddcf5", + "dcb3b0752a99d5c9449710f7f781dc2b5bc22cd9", ]); }); }); diff --git a/packages/analysis-engine/src/stem.ts b/packages/analysis-engine/src/stem.ts index 254fd4a5..b590d222 100644 --- a/packages/analysis-engine/src/stem.ts +++ b/packages/analysis-engine/src/stem.ts @@ -30,13 +30,23 @@ export function getStemNodes( return nodes; } +function compareCommitPriority(a: CommitNode, b: CommitNode): number { + // branches 값 존재하는 노드 => leaf / main / HEAD 노드. + // 이 노드는 큐에 들어올 때 순서가 정해져 있기 때문에 순서를 바꾸지 않음. + if (a.commit.branches.length || b.commit.branches.length) { + return 0; + } + // 나중에 커밋된 것을 먼저 담기 + return ( + new Date(b.commit.committerDate).getTime() - + new Date(a.commit.committerDate).getTime() + ); +} + export function buildStemDict( commitDict: Map ): Map { - const stemDict = new Map(); - - const q = new Queue(); - q.push.bind(q); + const q = new Queue(compareCommitPriority); /** * 처음 큐에 담기는 순서 @@ -44,6 +54,7 @@ export function buildStemDict( * 2. sub-branches * 3. HEAD */ + const stemDict = new Map(); const leafNodes = getLeafNodes(commitDict); const mainNode = leafNodes.find( (node) => From 4a4d69fd798e65efd2e883d6a491ffd6ae51fa36 Mon Sep 17 00:00:00 2001 From: ooooorobo Date: Thu, 8 Sep 2022 19:49:29 +0900 Subject: [PATCH 7/7] chore: edit test name --- packages/analysis-engine/src/stem.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/analysis-engine/src/stem.spec.ts b/packages/analysis-engine/src/stem.spec.ts index d8701818..7efaa981 100644 --- a/packages/analysis-engine/src/stem.spec.ts +++ b/packages/analysis-engine/src/stem.spec.ts @@ -156,7 +156,7 @@ describe("stem", () => { commitDict = generateCommitNodeDict(commits); }); - it("temp test", () => { + it("should make instance of Map", () => { const stemDict = buildStemDict(commitDict); expect(stemDict).toBeInstanceOf(Map); });