18
const fs = require('fs-extra');
19
const globby = require('globby');
20
const sloc = require('sloc');
21
const codeownersUtils = require('codeowners-utils');
22
const { resolve: resolvePath } = require('path');
24
async function loadOwners(rootDir) {
25
const codeowners = await codeownersUtils.loadOwners(rootDir);
27
return function getOwners(path) {
28
const { owners } = codeownersUtils.matchFile(path, codeowners);
30
owners.includes('@backstage/maintainers') &&
31
owners.includes('@backstage/reviewers')
33
return owners.filter(owner => owner !== '@backstage/reviewers');
39
function createLocCounter(rootDir) {
40
return async path => {
41
const content = await fs.readFile(resolvePath(rootDir, path), 'utf-8');
42
const stats = sloc(content, 'ts');
47
async function printOwnerDirectories(allFiles, getOwners, getLoc, onlyOwner) {
48
const countByPath = new Map();
52
for (const file of allFiles) {
53
const owners = getOwners(file);
54
const loc = await getLoc(file);
56
if (owners.includes(onlyOwner)) {
57
const share = loc / owners.length;
61
const path = file.split('/').slice(0, 2).join('/');
62
if ((await fs.stat(path)).isDirectory()) {
63
countByPath.set(path, (countByPath.get(path) || 0) + share);
68
const sortedPaths = Array.from(countByPath)
69
.map(([path, loc]) => ({ path, loc: Math.round(loc) }))
70
.sort((a, b) => b.loc - a.loc);
72
const maxPathLen = Math.max(...sortedPaths.map(({ path }) => path.length));
73
for (const { path, loc } of sortedPaths) {
74
console.log(`${path.padEnd(maxPathLen)} ${loc}`);
77
console.log('Total share:', Math.round(totalShare));
78
console.log('Total lines of code:', total);
81
async function printAllOwners(allFiles, getOwners, getLoc) {
82
const countByOwners = new Map();
85
for (const file of allFiles) {
86
const owners = getOwners(file);
87
const loc = await getLoc(file);
90
const share = loc / owners.length;
91
for (const owner of owners) {
92
countByOwners.set(owner, (countByOwners.get(owner) || 0) + share);
96
const sortedOwners = Array.from(countByOwners)
97
.map(([owner, loc]) => ({ owner, loc: Math.round(loc) }))
98
.sort((a, b) => b.loc - a.loc);
100
const maxOwnerLen = Math.max(
101
...sortedOwners.map(({ owner }) => owner.length),
103
for (const { owner, loc } of sortedOwners) {
104
console.log(`${owner.padEnd(maxOwnerLen)} ${loc}`);
107
console.log('Total lines of code:', total);
110
async function main(onlyOwner) {
111
const rootDir = resolvePath(__dirname, '..');
113
const allFiles = await globby(
115
'**/*.{js,jsx,ts,tsx,mjs,cjs}',
116
'!**/*.{generated,test}.*',
117
'!**/{__fixtures__,fixtures}',
122
followSymbolicLinks: false,
126
const getOwners = await loadOwners(rootDir);
127
const getLoc = createLocCounter(rootDir);
130
await printOwnerDirectories(allFiles, getOwners, getLoc, onlyOwner);
132
await printAllOwners(allFiles, getOwners, getLoc);
136
main(...process.argv.slice(2)).catch(err => {
137
console.error(err.stack);