Skip to content

Commit ba1fc4b

Browse files
authored
Rework sorting to account for parents and date (#12)
1 parent b55a29a commit ba1fc4b

File tree

4 files changed

+2653
-329
lines changed

4 files changed

+2653
-329
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@
9595
- [Update package.json](https://github.com/cjbarth/github-release-notes/commit/f2fea79abb3300381744faed0d11ef539ddf676c) - @cjbarth
9696
- [Add release-it](https://github.com/cjbarth/github-release-notes/commit/5f4b37dcf1c3bb7a02f5a69b29f989cae803757c) - @cjbarth
9797
- [Fix tests](https://github.com/cjbarth/github-release-notes/commit/ecceb7ca1d1e80a5ba88b4fbf9863dd673b05bde) - @cjbarth
98-
- [Track PRs, commits by branch, not date](https://github.com/cjbarth/github-release-notes/commit/acef232efa2f0e66bf5bdd8f28310584fc3b1e7f) - @cjbarth
9998
- [Fix tests](https://github.com/cjbarth/github-release-notes/commit/718b9aea68980bcdb49a3436414de58ae9832230) - @cjbarth
99+
- [Correctly compare dates for PR retrieval; fix tests](https://github.com/cjbarth/github-release-notes/commit/0b306da3c19adeef4781a3042488f9b53462fe3a) - @cjbarth
100+
- [Track PRs, commits by branch, not date](https://github.com/cjbarth/github-release-notes/commit/acef232efa2f0e66bf5bdd8f28310584fc3b1e7f) - @cjbarth
100101
- [Use commit date as tag date](https://github.com/cjbarth/github-release-notes/commit/ed9fc746a3e7256c8cadb02571e606d0645cb7d9) - @cjbarth
101102
- [Correctly compare dates for PR retrieval](https://github.com/cjbarth/github-release-notes/commit/e53f9e7f6aff4b32dc3f7e6ccdca1f9d767eaf1a) - @cjbarth
102-
- [Correctly compare dates for PR retrieval; fix tests](https://github.com/cjbarth/github-release-notes/commit/0b306da3c19adeef4781a3042488f9b53462fe3a) - @cjbarth
103103
- [Update supported NodeJS versions to current (#291)](https://github.com/cjbarth/github-release-notes/commit/ff0ddae3938db3cfcca5ef317d74eee034c32cc5) - @cjbarth
104104
- [docs: add viatrix as a contributor (#297)](https://github.com/cjbarth/github-release-notes/commit/8beb6f013cdfe410a0c20cd48291efe4c92a8ace) - @allcontributors[bot]
105105
- [Return exit code 1 on error for gren changelog (#294)](https://github.com/cjbarth/github-release-notes/commit/69b77665dddb1135a81ce856a7c8edb1003dbc45) - @viatrix

lib/src/Gren.js

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,63 +1288,71 @@ class Gren {
12881288
}));
12891289
}
12901290

1291-
commits = commits.filter((commit) => branchCommitShas.includes(commit.sha));
1292-
commits = this._sortCommitsByParent(commits);
1293-
releaseRange.push(commits);
1291+
const filteredCommits = commits.filter((commit) => branchCommitShas.includes(commit.sha));
1292+
const sortedCommits = this._sortCommitsByParent(filteredCommits);
1293+
releaseRange.push(sortedCommits);
12941294
}
12951295
loadedCommits("Commits acquired");
12961296

12971297
return dataSource[this.options.dataSource](releaseRanges);
12981298
}
12991299

13001300
_sortCommitsByParent(commits, dateOrder = "desc") {
1301-
// 1) Map SHAs -> commit object for O(1) lookups
1301+
// 1) Map sha -> commit
13021302
const commitMap = new Map(commits.map((c) => [c.sha, c]));
13031303

1304-
// 2) Build parent -> [children] adjacency
1305-
const childrenMap = new Map();
1306-
for (const commit of commits) {
1307-
// find the first parent in our set (if any)
1308-
const parentSha = (commit.parents || []).map((p) => p.sha).find((sha) => commitMap.has(sha));
1309-
if (parentSha) {
1310-
if (!childrenMap.has(parentSha)) childrenMap.set(parentSha, []);
1311-
childrenMap.get(parentSha).push(commit);
1304+
// 2) Compute parents for each commit
1305+
const parentMap = new Map();
1306+
for (const c of commits) {
1307+
const parentList = (c.parents || []).map((p) => p.sha).filter((sha) => commitMap.has(sha));
1308+
parentMap.set(c.sha, parentList);
1309+
}
1310+
1311+
// 3) Compute which SHAs appear as a parent -> those that have children
1312+
const hasChild = new Set();
1313+
for (const parents of parentMap.values()) {
1314+
for (const p of parents) {
1315+
hasChild.add(p);
13121316
}
13131317
}
13141318

1315-
// 3) Identify "roots": commits whose first parent is not in our list
1316-
const roots = commits.filter(
1317-
(c) => !(c.parents || []).map((p) => p.sha).some((sha) => commitMap.has(sha)),
1318-
);
1319+
// 4) Heads = commits that never appear as anyone's parent
1320+
const heads = commits.filter((c) => !hasChild.has(c.sha)).map((c) => c.sha);
13191321

1320-
// 4) Date-based comparator
1321-
const cmpDate = (a, b) => {
1322-
const da = new Date(a.committer.date);
1323-
const db = new Date(b.committer.date);
1324-
return dateOrder === "asc" ? da - db : db - da;
1322+
// 5) A helper to compare by newest date
1323+
const compareDateDesc = (shaA, shaB) => {
1324+
const da = new Date(
1325+
commitMap.get(shaA).commit.committer.date || commitMap.get(shaA).commit.author.date,
1326+
);
1327+
const db = new Date(
1328+
commitMap.get(shaB).commit.committer.date || commitMap.get(shaB).commit.author.date,
1329+
);
1330+
return db - da;
13251331
};
13261332

1327-
// 5) Sort roots by date
1328-
roots.sort(cmpDate);
1329-
1330-
// 6) DFS-like traversal to produce the final list
1333+
// 6) Candidate pool & result
13311334
const result = [];
1332-
const visit = (commit) => {
1333-
result.push(commit);
1334-
const kids = childrenMap.get(commit.sha) || [];
1335-
// within the same parent, sort by date too
1336-
kids.sort(cmpDate);
1337-
for (const child of kids) {
1338-
visit(child);
1339-
}
1340-
};
1335+
const seen = new Set();
1336+
const pool = [...heads];
1337+
1338+
while (pool.length) {
1339+
// pick the newest SHA
1340+
pool.sort((a, b) => compareDateDesc(a, b));
1341+
const sha = pool.shift();
13411342

1342-
for (const root of roots) {
1343-
visit(root);
1343+
if (seen.has(sha)) continue;
1344+
seen.add(sha);
1345+
1346+
// emit that commit
1347+
result.push(commitMap.get(sha));
1348+
1349+
// add its parents to the pool
1350+
for (const p of parentMap.get(sha) || []) {
1351+
if (!seen.has(p)) pool.push(p);
1352+
}
13441353
}
13451354

1346-
// This was done parent first, we want the child at the top
1347-
return result.reverse();
1355+
return result;
13481356
}
13491357

13501358
_transformTagsIntoReleaseObjects(tags) {

0 commit comments

Comments
 (0)