Skip to content

Commit b55a29a

Browse files
authored
Sort commits by parent, then date (#11)
1 parent 84cc103 commit b55a29a

File tree

5 files changed

+896
-10
lines changed

5 files changed

+896
-10
lines changed

CHANGELOG.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## v4.2.0 (2023-09-05)
44

5+
- [Release 4.2.0](https://github.com/cjbarth/github-release-notes/commit/fa9e966b56872cee12980922be4e0ed94ae0eabb) - @cjbarth
56
- [Format using prettier (#9)](https://github.com/cjbarth/github-release-notes/commit/b8fd1b6a01ef30ba0f2458a86ebd56991a911e44) - @cjbarth
67
- [Update README (#8)](https://github.com/cjbarth/github-release-notes/commit/bb476de6b36057ef694b55002e3877b88f93b0ab) - @cjbarth
78
- [Use application version number for head of changelog (#7)](https://github.com/cjbarth/github-release-notes/commit/aaae7e0b07fa2078dec4096074a061aaf40a0439) - @cjbarth
@@ -11,11 +12,11 @@
1112

1213
## v4.1.0 (2023-07-14)
1314

15+
- [Release 4.1.0](https://github.com/cjbarth/github-release-notes/commit/c09f024a189c2a3494c21a85cce9f04e4b986995) - @cjbarth
1416
- [Add basic workflow for PR testing before merge (#5)](https://github.com/cjbarth/github-release-notes/commit/346d5ff6d90bbcde5d3a6264e63d250168daeebb) - @cjbarth
1517
- [Adjust tests to account for default branch (#4)](https://github.com/cjbarth/github-release-notes/commit/fdc118304f58692165a95b31de8fed299479f3ae) - @cjbarth
1618
- [Use current branch as default branch (#3)](https://github.com/cjbarth/github-release-notes/commit/16b30918eec4a2e73e4164880904034f9a457d50) - @cjbarth
1719
- [Move eslint `env` config to .eslintrc (#2)](https://github.com/cjbarth/github-release-notes/commit/0693fee0d7219bcf488a1adc5c97656aabdec298) - @cjbarth
18-
- [Release 4.1.0](https://github.com/cjbarth/github-release-notes/commit/c09f024a189c2a3494c21a85cce9f04e4b986995) - @cjbarth
1920

2021
---
2122

@@ -24,10 +25,10 @@
2425
- [Release 4.0.0](https://github.com/cjbarth/github-release-notes/commit/934e728b5e87e941a5f5f2bcef457e47e423f41b) - @cjbarth
2526
- [Build changelog as part of release process](https://github.com/cjbarth/github-release-notes/commit/3e87029e162fdaa1a7e542e906152e4da5ac0d7b) - @cjbarth
2627
- [Update to release-it@15](https://github.com/cjbarth/github-release-notes/commit/cb70224198557df28fb122766131bf84608dcfdc) - @cjbarth
27-
- [Update changelog to follow new standards](https://github.com/cjbarth/github-release-notes/commit/2f27d03e4441ce4243bcc956d95b8cf339a42f5c) - @cjbarth
2828
- [Update all semver-minor dependencies](https://github.com/cjbarth/github-release-notes/commit/a372f19c67bfec2993c3740f9e386771852ced73) - @cjbarth
29-
- [Update can-i-use data](https://github.com/cjbarth/github-release-notes/commit/5edb4b770b49135beaeb8e08ae9a7bd75ac434ca) - @cjbarth
29+
- [Update changelog to follow new standards](https://github.com/cjbarth/github-release-notes/commit/2f27d03e4441ce4243bcc956d95b8cf339a42f5c) - @cjbarth
3030
- [Make default template more compatible with markdown lint](https://github.com/cjbarth/github-release-notes/commit/f83261ad19b570ec28a2fff4d8d0db1ddfc97e94) - @cjbarth
31+
- [Update can-i-use data](https://github.com/cjbarth/github-release-notes/commit/5edb4b770b49135beaeb8e08ae9a7bd75ac434ca) - @cjbarth
3132
- [Make default date format ISO](https://github.com/cjbarth/github-release-notes/commit/2d5cd34fddf102dfe3a32545c9cb6dc49e3e8b75) - @cjbarth
3233

3334
---
@@ -94,11 +95,11 @@
9495
- [Update package.json](https://github.com/cjbarth/github-release-notes/commit/f2fea79abb3300381744faed0d11ef539ddf676c) - @cjbarth
9596
- [Add release-it](https://github.com/cjbarth/github-release-notes/commit/5f4b37dcf1c3bb7a02f5a69b29f989cae803757c) - @cjbarth
9697
- [Fix tests](https://github.com/cjbarth/github-release-notes/commit/ecceb7ca1d1e80a5ba88b4fbf9863dd673b05bde) - @cjbarth
97-
- [Fix tests](https://github.com/cjbarth/github-release-notes/commit/718b9aea68980bcdb49a3436414de58ae9832230) - @cjbarth
98-
- [Correctly compare dates for PR retrieval; fix tests](https://github.com/cjbarth/github-release-notes/commit/0b306da3c19adeef4781a3042488f9b53462fe3a) - @cjbarth
9998
- [Track PRs, commits by branch, not date](https://github.com/cjbarth/github-release-notes/commit/acef232efa2f0e66bf5bdd8f28310584fc3b1e7f) - @cjbarth
99+
- [Fix tests](https://github.com/cjbarth/github-release-notes/commit/718b9aea68980bcdb49a3436414de58ae9832230) - @cjbarth
100100
- [Use commit date as tag date](https://github.com/cjbarth/github-release-notes/commit/ed9fc746a3e7256c8cadb02571e606d0645cb7d9) - @cjbarth
101101
- [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
102103
- [Update supported NodeJS versions to current (#291)](https://github.com/cjbarth/github-release-notes/commit/ff0ddae3938db3cfcca5ef317d74eee034c32cc5) - @cjbarth
103104
- [docs: add viatrix as a contributor (#297)](https://github.com/cjbarth/github-release-notes/commit/8beb6f013cdfe410a0c20cd48291efe4c92a8ace) - @allcontributors[bot]
104105
- [Return exit code 1 on error for gren changelog (#294)](https://github.com/cjbarth/github-release-notes/commit/69b77665dddb1135a81ce856a7c8edb1003dbc45) - @viatrix
@@ -146,8 +147,8 @@
146147
- [docs: add phun-ky as a contributor (#236)](https://github.com/cjbarth/github-release-notes/commit/f1aa847bf93f648454a5c927e8dcfdf765aa6c87) - @allcontributors[bot]
147148
- [docs: add phun-ky as a contributor (#234)](https://github.com/cjbarth/github-release-notes/commit/a53c582fe24e1f86584490994d65a534a27c965c) - @allcontributors[bot]
148149
- [docs: add wellDan28 as a contributor (#233)](https://github.com/cjbarth/github-release-notes/commit/a3013a9a4be5b2fe3fd34a8e5ac360b5da10d88a) - @allcontributors[bot]
149-
- [docs: update README.md [skip ci]](https://github.com/cjbarth/github-release-notes/commit/8191996ff9ab25a6afadab92d397c842dd6eb4fe) - @allcontributors[bot]
150150
- [docs: create .all-contributorsrc [skip ci]](https://github.com/cjbarth/github-release-notes/commit/754ba2105677a36cbfce40bf4d89fbd0c6daeefb) - @allcontributors[bot]
151+
- [docs: update README.md [skip ci]](https://github.com/cjbarth/github-release-notes/commit/8191996ff9ab25a6afadab92d397c842dd6eb4fe) - @allcontributors[bot]
151152
- [Update CHANGELOG.md](https://github.com/cjbarth/github-release-notes/commit/998418715993d042cfb0b2bb4eb72bae105cc583) - @alexcanessa
152153

153154
---

lib/src/Gren.js

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,17 +1289,64 @@ class Gren {
12891289
}
12901290

12911291
commits = commits.filter((commit) => branchCommitShas.includes(commit.sha));
1292-
commits.sort(
1293-
(commit1, commit2) =>
1294-
new Date(commit2.commit.committer.date) - new Date(commit1.commit.committer.date),
1295-
);
1292+
commits = this._sortCommitsByParent(commits);
12961293
releaseRange.push(commits);
12971294
}
12981295
loadedCommits("Commits acquired");
12991296

13001297
return dataSource[this.options.dataSource](releaseRanges);
13011298
}
13021299

1300+
_sortCommitsByParent(commits, dateOrder = "desc") {
1301+
// 1) Map SHAs -> commit object for O(1) lookups
1302+
const commitMap = new Map(commits.map((c) => [c.sha, c]));
1303+
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);
1312+
}
1313+
}
1314+
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+
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;
1325+
};
1326+
1327+
// 5) Sort roots by date
1328+
roots.sort(cmpDate);
1329+
1330+
// 6) DFS-like traversal to produce the final list
1331+
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+
};
1341+
1342+
for (const root of roots) {
1343+
visit(root);
1344+
}
1345+
1346+
// This was done parent first, we want the child at the top
1347+
return result.reverse();
1348+
}
1349+
13031350
_transformTagsIntoReleaseObjects(tags) {
13041351
return tags.map((tag) => ({
13051352
id: tag.releaseId,

test/Gren.spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,20 @@ describe("Gren", () => {
619619
});
620620
});
621621

622+
describe("_sortCommitsByParent", function () {
623+
it("Should sort the commits by parent", function () {
624+
const unsortedCommits = JSON.parse(
625+
fs.readFileSync(process.cwd() + "/test/data/commits_unsorted.json"),
626+
);
627+
const sortedCommits = JSON.parse(
628+
fs.readFileSync(process.cwd() + "/test/data/commits_sorted.json"),
629+
);
630+
const processedCommits = gren._sortCommitsByParent(unsortedCommits);
631+
632+
assert.deepEqual(processedCommits, sortedCommits, "The commits are sorted");
633+
});
634+
});
635+
622636
describe("_checkChangelogFile", () => {
623637
before(() => {
624638
gren.options.changelogFilename = "test/.temp/CHANGELOG.md";

0 commit comments

Comments
 (0)