-
Notifications
You must be signed in to change notification settings - Fork 28
/
codeowners.js
executable file
·88 lines (67 loc) · 2.31 KB
/
codeowners.js
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// @ts-check
const findUp = require('find-up');
const fs = require('fs');
const ignore = require('ignore');
const isDirectory = require('is-directory');
const path = require('path');
const trueCasePath = require('true-case-path');
function ownerMatcher(pathString) {
const matcher = ignore().add(pathString);
return matcher.ignores.bind(matcher);
}
function Codeowners(currentPath, fileName = 'CODEOWNERS') {
const pathOrCwd = currentPath || process.cwd();
const codeownersPath = findUp.sync(
[`.github/${fileName}`, `.gitlab/${fileName}`, `docs/${fileName}`, `${fileName}`],
{ cwd: pathOrCwd }
);
if (!codeownersPath) {
throw new Error(`Could not find a CODEOWNERS file`);
}
this.codeownersFilePath = trueCasePath(codeownersPath);
this.codeownersDirectory = path.dirname(this.codeownersFilePath);
// We might have found a bare codeowners file or one inside the three supported subdirectories.
// In the latter case the project root is up another level.
if (this.codeownersDirectory.match(/\/(.github|.gitlab|docs)$/i)) {
this.codeownersDirectory = path.dirname(this.codeownersDirectory);
}
const codeownersFile = path.basename(this.codeownersFilePath);
if (codeownersFile !== fileName) {
throw new Error(`Found a ${fileName} file but it was lower-cased: ${this.codeownersFilePath}`);
}
if (isDirectory.sync(this.codeownersFilePath)) {
throw new Error(`Found a ${fileName} but it's a directory: ${this.codeownersFilePath}`);
}
const lines = fs
.readFileSync(this.codeownersFilePath)
.toString()
.split(/\r\n|\r|\n/);
const ownerEntries = [];
for (const line of lines) {
if (!line) {
continue;
}
if (line.startsWith('#')) {
continue;
}
const [pathString, ...usernames] = line.split(/\s+/);
ownerEntries.push({
path: pathString,
usernames,
match: ownerMatcher(pathString),
});
}
// reverse the owner entries to search from bottom to top
// the last matching pattern takes the most precedence
this.ownerEntries = ownerEntries.reverse();
}
const EMPTY_ARRAY = [];
Codeowners.prototype.getOwner = function getOwner(filePath) {
for (const entry of this.ownerEntries) {
if (entry.match(filePath)) {
return [...entry.usernames];
}
}
return EMPTY_ARRAY;
};
module.exports = Codeowners;