Skip to content

Commit e3d6374

Browse files
committed
only show files that still exist in the knowledge gaps report
1 parent 813ad9c commit e3d6374

File tree

5 files changed

+79
-28
lines changed

5 files changed

+79
-28
lines changed

.eslintrc.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = {
1212
"@typescript-eslint/no-unused-vars": "error",
1313
"max-depth": ["error", 2],
1414
"max-nested-callbacks": ["error", 2],
15-
"max-lines-per-function": ["error", 60],
15+
"max-lines-per-function": ["error", 70],
1616
"max-statements": ["error", 26],
1717
"max-params": ["error", 3],
1818
},

src/git-reader/git-repository.ts

+26-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
import { stat } from "node:fs/promises";
2+
13
import fs from "fs";
24
import git from "isomorphic-git";
35
import { Readable } from "stream";
46

57
import { ResumableProcessor } from "../cache/resumable-processor.js";
68
import { time, timeLog } from "../index.js";
7-
import { ChangedFile, Commit, ExpandedCommit } from "../interfaces.js";
9+
import {
10+
ChangedFile,
11+
ChangedFileType,
12+
Commit,
13+
ExpandedCommit,
14+
} from "../interfaces.js";
815

916
interface GitReadOptions {
1017
stream?: Readable;
@@ -77,11 +84,11 @@ export class GitRepository {
7784
prevOID: string,
7885
nextOID: string
7986
): Promise<ChangedFile[]> {
80-
return await git.walk({
87+
const files = await git.walk({
8188
fs,
8289
dir: this.repoPath,
8390
trees: [git.TREE({ ref: prevOID }), git.TREE({ ref: nextOID })],
84-
map: async function (filepath, [commitA, commitB]) {
91+
map: async (filepath, [commitA, commitB]) => {
8592
let aOID = "";
8693
let bOID = "";
8794
let aType = "";
@@ -115,7 +122,7 @@ export class GitRepository {
115122
}
116123

117124
// determine modification type:
118-
let type = "equal";
125+
let type: ChangedFileType = "equal";
119126
if (aOID !== bOID) {
120127
type = "modify";
121128
}
@@ -132,5 +139,20 @@ export class GitRepository {
132139
};
133140
},
134141
});
142+
// check if file exists:
143+
for (const file of files) {
144+
file.isExistingFile = await this.checkFileExists(
145+
`${this.repoPath}${file.path}`
146+
);
147+
}
148+
return files;
149+
}
150+
private async checkFileExists(path: string): Promise<boolean> {
151+
try {
152+
const stats = await stat(path);
153+
return stats.isFile();
154+
} catch {
155+
return false;
156+
}
135157
}
136158
}

src/index.ts

+16-15
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { SummaryDashboard } from "./dashboard/summary-dashboard.js";
55
import { GitRepository } from "./git-reader/git-repository.js";
66
import { ExpandedCommit } from "./interfaces.js";
77
import { ListOfContributorsPerFileAggregate } from "./stats/aggregate/list-of-contributors-per-file-aggregate.js";
8-
import { getListOfContributorsPerFile } from "./stats/list-of-contributors-per-file.js";
98
import { getNumberOfChangesPerFile } from "./stats/number-of-changes-per-file.js";
109
import { getNumberOfCommitsByAuthor } from "./stats/number-of-commits-by-author.js";
1110
import { getNumberOfContributorsPerFile } from "./stats/number-of-contributors-per-file.js";
@@ -53,25 +52,27 @@ async function collectHotFiles(commitsWithChangedFiles: ExpandedCommit[]) {
5352
async function collectKnowledgeGaps(commitsWithChangedFiles: ExpandedCommit[]) {
5453
const contributorsPerFile = getNumberOfContributorsPerFile(
5554
commitsWithChangedFiles
56-
);
55+
).filter((x) => x.isExistingFile);
5756
log(
5857
"knowledge gaps (files with least number of contributors)",
59-
Object.keys(contributorsPerFile)
60-
.map((x) => {
61-
return [x, contributorsPerFile[x]];
58+
contributorsPerFile
59+
.sort((a, b) => {
60+
if (a.contributorsNames.length === b.contributorsNames.length) {
61+
return a.lastChange.getTime() - b.lastChange.getTime();
62+
}
63+
return a.contributorsNames.length - b.contributorsNames.length;
6264
})
63-
.sort((a, b) => Number(a[1]) - Number(b[1]))
6465
.slice(0, 50)
6566
);
6667
}
67-
function collectDetailedContributorsPerFile(
68-
commitsWithChangedFiles: ExpandedCommit[]
69-
) {
70-
const listOfContributorsPerFile = getListOfContributorsPerFile(
71-
commitsWithChangedFiles
72-
);
73-
log("detailed contributors for each file", listOfContributorsPerFile);
74-
}
68+
// function collectDetailedContributorsPerFile(
69+
// commitsWithChangedFiles: ExpandedCommit[]
70+
// ) {
71+
// const listOfContributorsPerFile = getListOfContributorsPerFile(
72+
// commitsWithChangedFiles
73+
// );
74+
// log("detailed contributors for each file", listOfContributorsPerFile);
75+
// }
7576

7677
/* eslint-disable-next-line max-lines-per-function, max-statements */
7778
async function main() {
@@ -152,6 +153,6 @@ async function main() {
152153
});
153154
await collectHotFiles(commitsWithChangedFiles);
154155
await collectKnowledgeGaps(commitsWithChangedFiles);
155-
collectDetailedContributorsPerFile(commitsWithChangedFiles);
156+
// collectDetailedContributorsPerFile(commitsWithChangedFiles);
156157
}
157158
main();

src/interfaces.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export type ChangedFileType = "modify" | "add" | "remove" | "equal";
99
export interface ChangedFile {
1010
type: ChangedFileType;
1111
path: string;
12+
isExistingFile: boolean;
1213
}
1314

1415
export interface Commit {

src/stats/number-of-contributors-per-file.ts

+35-8
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,51 @@
11
import { ExpandedCommit } from "../interfaces.js";
2+
interface ContributorsSummary {
3+
filePath: string;
4+
contributorsNames: string[];
5+
firstChange: Date;
6+
lastChange: Date;
7+
isExistingFile: boolean;
8+
}
29

310
export function getNumberOfContributorsPerFile(
411
commits: ExpandedCommit[]
5-
): Record<string, number> {
6-
const changedFiles: Record<string, string[]> = {};
12+
): ContributorsSummary[] {
13+
const changedFiles: Record<string, Set<string>> = {};
14+
const existingFiles: Record<string, boolean> = {};
15+
const firstChange: Record<string, number> = {};
16+
const lastChange: Record<string, number> = {};
717

818
commits.forEach((commit) => {
919
commit.changedFiles.forEach((file) => {
10-
if (!changedFiles[file.path]) {
11-
changedFiles[file.path] = [];
20+
if (file.type === "equal") {
21+
return;
1222
}
13-
if (!changedFiles[file.path].includes(commit.commit.commit.author.name)) {
14-
changedFiles[file.path].push(commit.commit.commit.author.name);
23+
if (!changedFiles[file.path]) {
24+
changedFiles[file.path] = new Set();
1525
}
26+
changedFiles[file.path].add(commit.commit.commit.author.name);
27+
existingFiles[file.path] = file.isExistingFile;
28+
29+
firstChange[file.path] = Math.min(
30+
firstChange[file.path] || 1_000_000_000_000,
31+
commit.commit.commit.author.timestamp
32+
);
33+
lastChange[file.path] = Math.max(
34+
lastChange[file.path] || 0,
35+
commit.commit.commit.author.timestamp
36+
);
1637
});
1738
});
1839

19-
const results: Record<string, number> = {};
40+
const results: ContributorsSummary[] = [];
2041
Object.keys(changedFiles).forEach((filePath) => {
21-
results[filePath] = changedFiles[filePath].length;
42+
results.push({
43+
filePath,
44+
contributorsNames: Array.from(changedFiles[filePath].values()),
45+
firstChange: new Date(firstChange[filePath] * 1000),
46+
lastChange: new Date(lastChange[filePath] * 1000),
47+
isExistingFile: existingFiles[filePath],
48+
});
2249
});
2350

2451
return results;

0 commit comments

Comments
 (0)