Skip to content

Commit fc755c4

Browse files
committed
run knowledge gap analysis applying the filtering for ignored files
1 parent 6e261a7 commit fc755c4

8 files changed

Lines changed: 111 additions & 59 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.env
22
node_modules
3-
.idea
3+
.idea
4+
.cache

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ CLI wrapper around https://github.com/anton-107/codebase-stats-collector
55
## Usage
66

77
```
8-
npm run cli -- knowledge-gaps <PATH TO GIT REPO> --ignoreFiles /path/to/ignored/folder
8+
npm run cli -- knowledge-gaps <PATH TO LOCAL GIT REPO> --ignoreFiles /path/to/ignored/folder
99
```

eslint.config.mjs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,18 @@ import simpleImportSort from "eslint-plugin-simple-import-sort";
44
import globals from "globals";
55
import tseslint from "typescript-eslint";
66

7-
87
/** @type {import('eslint').Linter.Config[]} */
98
export default [
10-
{files: ["**/*.{ts,tsx}"]},
11-
{files: ["**/*.ts"], languageOptions: {sourceType: "script"}},
12-
{languageOptions: { globals: globals.node }},
9+
{ files: ["**/*.{ts,tsx}"] },
10+
{ files: ["**/*.ts"], languageOptions: { sourceType: "script" } },
11+
{ languageOptions: { globals: globals.node } },
1312
pluginJs.configs.recommended,
1413
...tseslint.configs.recommended,
1514
comments.recommended,
1615
{
1716
rules: {
18-
"@eslint-community/eslint-comments/no-unused-disable": "error"
19-
}
17+
"@eslint-community/eslint-comments/no-unused-disable": "error",
18+
},
2019
},
2120
{
2221
plugins: {
@@ -36,6 +35,6 @@ export default [
3635
"max-lines-per-function": ["error", 56],
3736
"max-statements": ["error", 22],
3837
"max-params": ["error", 3],
39-
}
40-
}
41-
];
38+
},
39+
},
40+
];

src/cli.ts

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
11
import { cli, command } from "cleye";
2-
import {GitRepository} from "codebase-stats-collector/dist/git-reader/git-repository.js";
3-
import {getNumberOfContributorsPerFile} from "codebase-stats-collector/dist/stats/number-of-contributors-per-file.js";
4-
import { Readable } from "stream";
52

6-
export function log(arg1: string, arg2: object | string | null) {
7-
if (arg2 === null) {
8-
// eslint-disable-next-line no-console
9-
console.log(arg1);
10-
return;
11-
}
12-
// eslint-disable-next-line no-console
13-
console.log(arg1, arg2);
14-
}
3+
import { collectKnowledgeGaps } from "./commands/knowledge-gaps.js";
4+
import { log } from "./console.js";
155

16-
export class CommandLineInterface {
6+
export class CommandLineInterface {
177
constructor() {}
188
public run() {
199
cli({
@@ -31,45 +21,17 @@ export class CommandLineInterface {
3121
},
3222
async (argv) => {
3323
const dir = argv._.pathToRepository;
34-
log(
35-
"Calculating files with least number of contributors",
36-
dir,
37-
);
24+
log("Calculating files with least number of contributors", dir);
25+
let ignoreFilesPattern: string | null = null;
3826
if (argv.flags.ignoreFiles) {
3927
// eslint-disable-next-line no-console
4028
console.log(
4129
"will ignore the following files in the output: ",
4230
argv.flags.ignoreFiles,
4331
);
32+
ignoreFilesPattern = argv.flags.ignoreFiles;
4433
}
45-
46-
// initialize repo
47-
const repo = new GitRepository(dir);
48-
const commitsStream = new Readable({
49-
objectMode: true,
50-
read() {
51-
// do nothing.
52-
},
53-
});
54-
const commitsWithChangedFiles = await repo.getListOfCommitsWithChangedFiles({
55-
stream: commitsStream,
56-
});
57-
const contributorsPerFile = getNumberOfContributorsPerFile(
58-
commitsWithChangedFiles
59-
).filter((x) => x.isExistingFile);
60-
const topKnowledgeGaps = contributorsPerFile
61-
.sort((a, b) => {
62-
if (a.contributorsNames.length === b.contributorsNames.length) {
63-
return a.lastChange.getTime() - b.lastChange.getTime();
64-
}
65-
return a.contributorsNames.length - b.contributorsNames.length;
66-
})
67-
.slice(0, 50);
68-
69-
log(
70-
"knowledge gaps (files with least number of contributors)",
71-
topKnowledgeGaps
72-
);
34+
await collectKnowledgeGaps(dir, ignoreFilesPattern);
7335
},
7436
),
7537
],

src/commands/knowledge-gaps.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { debug } from "codebase-stats-collector/dist/console/console.js";
2+
import { SummaryDashboard } from "codebase-stats-collector/dist/dashboard/summary-dashboard.js";
3+
import { GitRepository } from "codebase-stats-collector/dist/git-reader/git-repository.js";
4+
import { ExpandedCommit } from "codebase-stats-collector/dist/interfaces.js";
5+
import { getNumberOfContributorsPerFile } from "codebase-stats-collector/dist/stats/number-of-contributors-per-file.js";
6+
import { Readable } from "stream";
7+
8+
import { log } from "../console.js";
9+
10+
function setupProgressStream(summaryDashboard: SummaryDashboard): Readable {
11+
let commitsCounter = 0;
12+
13+
const commitsStream = new Readable({
14+
objectMode: true,
15+
read() {
16+
// do nothing.
17+
},
18+
});
19+
commitsStream.on("data", (commit: ExpandedCommit) => {
20+
debug("Commit", commit);
21+
22+
commitsCounter += 1;
23+
summaryDashboard.setCurrentProgress(commitsCounter, commit);
24+
});
25+
commitsStream.on("error", (err) => {
26+
debug("error reading commits", { err });
27+
});
28+
commitsStream.on("end", () => {
29+
debug("done reading commits", {});
30+
});
31+
commitsStream.on("close", () => {
32+
debug("stream closed", {});
33+
});
34+
return commitsStream;
35+
}
36+
37+
export async function collectKnowledgeGaps(
38+
dir: string,
39+
ignoreFiles: string | null,
40+
): Promise<void> {
41+
// initialize repo
42+
const repo = new GitRepository(dir);
43+
44+
// initialize summary dashboard:
45+
const summaryDashboard = new SummaryDashboard([]);
46+
summaryDashboard.startProgress();
47+
48+
const commitsStream = setupProgressStream(summaryDashboard);
49+
50+
// number of total commits:
51+
const commits = await repo.getListOfCommits();
52+
summaryDashboard.setCommits(commits);
53+
54+
const commitsWithChangedFiles = await repo.getListOfCommitsWithChangedFiles({
55+
stream: commitsStream,
56+
});
57+
const contributorsPerFile = getNumberOfContributorsPerFile(
58+
commitsWithChangedFiles,
59+
).filter((x) => x.isExistingFile);
60+
let knowledgeGaps = contributorsPerFile.sort((a, b) => {
61+
if (a.contributorsNames.length === b.contributorsNames.length) {
62+
return a.lastChange.getTime() - b.lastChange.getTime();
63+
}
64+
return a.contributorsNames.length - b.contributorsNames.length;
65+
});
66+
67+
if (ignoreFiles) {
68+
knowledgeGaps = knowledgeGaps.filter((x) => !x.filePath.match(ignoreFiles));
69+
}
70+
71+
const topKnowledgeGaps = knowledgeGaps.slice(0, 50);
72+
73+
log(
74+
"knowledge gaps (files with least number of contributors)",
75+
topKnowledgeGaps,
76+
);
77+
}

src/console.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export function log(arg1: string, arg2: object | string | null) {
2+
if (arg2 === null) {
3+
// eslint-disable-next-line no-console
4+
console.log(arg1);
5+
return;
6+
}
7+
// eslint-disable-next-line no-console
8+
console.log(arg1, arg2);
9+
}

src/main.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { CommandLineInterface } from "./cli.js";
22

3-
43
export function main() {
5-
new CommandLineInterface().run();
4+
new CommandLineInterface().run();
65
}
7-
main();
6+
main();

tsconfig.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,10 @@
107107
/* Completeness */
108108
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
109109
"skipLibCheck": true /* Skip type checking all .d.ts files. */
110+
},
111+
"ts-node": {
112+
"experimentalSpecifierResolution": "node",
113+
"transpileOnly": true,
114+
"esm": true
110115
}
111116
}

0 commit comments

Comments
 (0)