forked from angular/components
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathownerslint.ts
More file actions
73 lines (64 loc) · 2.57 KB
/
Copy pathownerslint.ts
File metadata and controls
73 lines (64 loc) · 2.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import chalk from 'chalk';
import {readdirSync, readFileSync, statSync} from 'fs';
import {IMinimatch, Minimatch} from 'minimatch';
import {join} from 'path';
/**
* Script that lints the CODEOWNERS file and makes sure that all files have an owner.
*/
/** Path for the Github owners file. */
const ownersFilePath = '.github/CODEOWNERS';
/** Path for the .gitignore file. */
const gitIgnorePath = '.gitignore';
let errors = 0;
const ownedPaths = readFileSync(ownersFilePath, 'utf8').split('\n')
// Trim lines.
.map(line => line.trim())
// Remove empty lines and comments.
.filter(line => line && !line.startsWith('#'))
// Split off just the path glob.
.map(line => line.split(/\s+/)[0])
// Turn paths into Minimatch objects.
.map(path => new Minimatch(path, {dot: true, matchBase: true}));
const ignoredPaths = readFileSync(gitIgnorePath, 'utf8').split('\n')
// Trim lines.
.map(line => line.trim())
// Remove empty lines and comments.
.filter(line => line && !line.startsWith('#'))
// Turn paths into Minimatch objects.
.map(path => new Minimatch(path, {dot: true, matchBase: true}));
for (let paths = getChildPaths('.'); paths.length;) {
paths = Array.prototype.concat(...paths
// Remove ignored paths
.filter(path => !ignoredPaths.reduce(
(isIgnored, ignoredPath) => isIgnored || ignoredPath.match('/' + path), false))
// Remove paths that match an owned path.
.filter(path => !ownedPaths.reduce(
(isOwned, ownedPath) => isOwned || isOwnedBy(path, ownedPath), false))
// Report an error for any files that didn't match any owned paths.
.filter(path => {
if (statSync(path).isFile()) {
console.log(chalk.red(`No code owner found for "${path}".`));
errors++;
return false;
}
return true;
})
// Get the next level of children for any directories.
.map(path => getChildPaths(path)));
}
if (errors) {
throw Error(`Found ${errors} files with no owner. Code owners for the files ` +
`should be added in the CODEOWNERS file.`);
}
/** Check if the given path is owned by the given owned path matcher. */
function isOwnedBy(path: string, ownedPath: IMinimatch) {
// If the owned path ends with `**` its safe to eliminate whole directories.
if (ownedPath.pattern.endsWith('**') || statSync(path).isFile()) {
return ownedPath.match('/' + path);
}
return false;
}
/** Get the immediate child paths of the given path. */
function getChildPaths(path: string) {
return readdirSync(path).map(child => join(path, child));
}