Skip to content
This repository was archived by the owner on Apr 8, 2026. It is now read-only.

Commit 1421baf

Browse files
jjmschofieldgithub-codeowners
andauthored
Git only tweaks (#39)
* Adding documentation for --only-git * Fixing --root documentation * adding int tests for --only-git * Shuffling deck chairs and preffering exec over execFile * giving git an identity in ci Co-authored-by: github-codeowners <github-codeowners@example.com>
1 parent 172061a commit 1421baf

10 files changed

Lines changed: 124 additions & 47 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,9 @@ Options:
8585
-c, --codeowners <filePath> path to codeowners file (default: "<dir>/.github/CODEOWNERS")
8686
-o, --output <outputFormat> how to output format eg: simple, jsonl, csv (default: "simple")
8787
-u, --unloved unowned files only (default: false)
88+
-g, --only-git consider only files tracked by git (default: false)
8889
-s, --stats output stats (default: true)
89-
-i, --include <partialPath> paths begening with partial path only (default: '')
90+
-r, --root <rootPath> the root path to filter files by (default: "")
9091
-h, --help output usage information
9192
```
9293

src/commands/__snapshots__/audit.test.int.ts.snap

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,22 @@ src/ext-wildcard-owner.js,@js-owner
4545
"
4646
`;
4747

48+
exports[`audit csv should only consider files tracked in git root when asked: stderr 1`] = `""`;
49+
50+
exports[`audit csv should only consider files tracked in git root when asked: stdout 1`] = `
51+
".github/CODEOWNERS,@global-owner1,@global-owner2
52+
.gitignore,@global-owner1,@global-owner2
53+
build/logs/deep/recursive-root-dir-owner.log,@doctocat
54+
build/logs/recursive-root-dir-owner.log,@doctocat
55+
deep/apps/recursive-deep-dir-owner.ts,@octocat
56+
deep/nested-ignore/.gitignore,@global-owner1,@global-owner2
57+
deep/nested-ignore/overridden-ignore.js,@js-owner
58+
default-wildcard-owners.md,@global-owner1,@global-owner2
59+
docs/non-recursive-dir-owner.md,@doctocat
60+
src/ext-wildcard-owner.js,@js-owner
61+
"
62+
`;
63+
4864
exports[`audit csv should show only unloved files when asked: stderr 1`] = `""`;
4965

5066
exports[`audit csv should show only unloved files when asked: stdout 1`] = `""`;
@@ -90,6 +106,22 @@ exports[`audit jsonl should list ownership for all files: stdout 1`] = `
90106
"
91107
`;
92108

109+
exports[`audit jsonl should only consider files tracked in git root when asked: stderr 1`] = `""`;
110+
111+
exports[`audit jsonl should only consider files tracked in git root when asked: stdout 1`] = `
112+
"{\\"path\\":\\".github/CODEOWNERS\\",\\"owners\\":[\\"@global-owner1\\",\\"@global-owner2\\"],\\"lines\\":29}
113+
{\\"path\\":\\".gitignore\\",\\"owners\\":[\\"@global-owner1\\",\\"@global-owner2\\"],\\"lines\\":4}
114+
{\\"path\\":\\"build/logs/deep/recursive-root-dir-owner.log\\",\\"owners\\":[\\"@doctocat\\"],\\"lines\\":0}
115+
{\\"path\\":\\"build/logs/recursive-root-dir-owner.log\\",\\"owners\\":[\\"@doctocat\\"],\\"lines\\":0}
116+
{\\"path\\":\\"deep/apps/recursive-deep-dir-owner.ts\\",\\"owners\\":[\\"@octocat\\"],\\"lines\\":0}
117+
{\\"path\\":\\"deep/nested-ignore/.gitignore\\",\\"owners\\":[\\"@global-owner1\\",\\"@global-owner2\\"],\\"lines\\":2}
118+
{\\"path\\":\\"deep/nested-ignore/overridden-ignore.js\\",\\"owners\\":[\\"@js-owner\\"],\\"lines\\":0}
119+
{\\"path\\":\\"default-wildcard-owners.md\\",\\"owners\\":[\\"@global-owner1\\",\\"@global-owner2\\"],\\"lines\\":0}
120+
{\\"path\\":\\"docs/non-recursive-dir-owner.md\\",\\"owners\\":[\\"@doctocat\\"],\\"lines\\":0}
121+
{\\"path\\":\\"src/ext-wildcard-owner.js\\",\\"owners\\":[\\"@js-owner\\"],\\"lines\\":0}
122+
"
123+
`;
124+
93125
exports[`audit jsonl should show only unloved files when asked: stderr 1`] = `""`;
94126

95127
exports[`audit jsonl should show only unloved files when asked: stdout 1`] = `""`;
@@ -154,6 +186,22 @@ src/ext-wildcard-owner.js @js-owner
154186
"
155187
`;
156188

189+
exports[`audit simple should only consider files tracked in git root when asked: stderr 1`] = `""`;
190+
191+
exports[`audit simple should only consider files tracked in git root when asked: stdout 1`] = `
192+
".github/CODEOWNERS @global-owner1 @global-owner2
193+
.gitignore @global-owner1 @global-owner2
194+
build/logs/deep/recursive-root-dir-owner.log @doctocat
195+
build/logs/recursive-root-dir-owner.log @doctocat
196+
deep/apps/recursive-deep-dir-owner.ts @octocat
197+
deep/nested-ignore/.gitignore @global-owner1 @global-owner2
198+
deep/nested-ignore/overridden-ignore.js @js-owner
199+
default-wildcard-owners.md @global-owner1 @global-owner2
200+
docs/non-recursive-dir-owner.md @doctocat
201+
src/ext-wildcard-owner.js @js-owner
202+
"
203+
`;
204+
157205
exports[`audit simple should show only unloved files when asked: stderr 1`] = `""`;
158206

159207
exports[`audit simple should show only unloved files when asked: stdout 1`] = `""`;

src/commands/audit.test.int.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,39 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import child_process from 'child_process';
4+
import util from 'util';
5+
16
import { v4 as uuidv4 } from 'uuid';
27
import fixtures from './__fixtures__/default';
38
import { generateProject } from './__fixtures__/project-builder.test.helper';
49

5-
import util from 'util';
6-
7-
const exec = util.promisify(require('child_process').exec);
10+
const exec = util.promisify(child_process.exec);
11+
const writeFile = util.promisify(fs.writeFile);
812

913
describe('audit', () => {
10-
const testId = uuidv4();
11-
1214
let testDir = 'not set';
1315

14-
beforeAll(async () => {
15-
testDir = await generateProject(testId, fixtures);
16-
// tslint:disable-next-line:no-console
17-
console.log(`test scratch dir: ${testDir}`);
18-
});
19-
2016
const runCli = async (args: string) => {
2117
return exec(`node ../../../dist/cli.js ${args}`, { cwd: testDir });
2218
};
2319

20+
const gitTrackProject = async () => {
21+
await exec(`git init`, { cwd: testDir });
22+
await exec(`git add .`, { cwd: testDir });
23+
await exec(`git config user.email "github-codeowners@example.com"`, { cwd: testDir });
24+
await exec(`git config user.name "github-codeowners"`, { cwd: testDir });
25+
await exec(`git commit -m "integration tests"`, { cwd: testDir });
26+
};
27+
2428
const outputs = ['simple', 'jsonl', 'csv'];
2529

2630
for (const output of outputs) {
2731
describe(output, () => {
32+
beforeEach(async () => {
33+
const testId = uuidv4();
34+
testDir = await generateProject(testId, fixtures);
35+
});
36+
2837
it('should list ownership for all files', async () => {
2938
const { stdout, stderr } = await runCli(`audit -o ${output}`);
3039
expect(stdout).toMatchSnapshot('stdout');
@@ -49,6 +58,19 @@ describe('audit', () => {
4958
expect(stderr).toMatchSnapshot('stderr');
5059
});
5160

61+
it('should only consider files tracked in git root when asked', async () => {
62+
// Arrange
63+
await gitTrackProject();
64+
await writeFile(path.resolve(testDir, 'git-untracked.txt'), 'not tracked in git');
65+
66+
// Act
67+
const { stdout, stderr } = await runCli(`audit -g -o ${output}`);
68+
69+
// Assert
70+
expect(stdout).toMatchSnapshot('stdout');
71+
expect(stderr).toMatchSnapshot('stderr');
72+
});
73+
5274
it('should do all commands in combination when asked', async () => {
5375
const { stdout, stderr } = await runCli(`audit -us -r deep -o ${output}`);
5476
expect(stdout).toMatchSnapshot('stdout');

src/lib/ownership/file.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
import * as path from 'path';
12
import { OwnedFile } from './lib/OwnedFile';
23
import { OwnershipEngine } from './lib/OwnershipEngine';
34
import { readDirRecursively } from './lib/readDirRecursively';
4-
import * as path from 'path';
5-
import { gitLsFiles } from './lib/gitLsFiles';
5+
import { readTrackedGitFiles } from './lib/readTrackedGitFiles';
66

77
export const getFileOwnership = async (options: { codeowners: string, dir: string, onlyGit: boolean, root?: string }): Promise<OwnedFile[]> => {
88
const engine = OwnershipEngine.FromCodeownersFile(options.codeowners);
99

1010
let filePaths;
1111
if (options.onlyGit) {
12-
filePaths = await gitLsFiles(options.dir);
12+
filePaths = await readTrackedGitFiles(options.dir);
1313
} else {
1414
filePaths = await readDirRecursively(options.dir, ['.git']);
1515
}

src/lib/ownership/lib/execFile.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/lib/ownership/lib/gitLsFiles.test.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/lib/ownership/lib/gitLsFiles.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { exec } from '../../util/exec';
2+
import { readTrackedGitFiles } from './readTrackedGitFiles';
3+
4+
jest.mock('../../util/exec');
5+
const execFileMock = exec as jest.Mock;
6+
7+
describe('readTrackedGitFiles', () => {
8+
it('should return the expected list of files when called', async () => {
9+
execFileMock.mockResolvedValue({ stdout: 'foo\nbar\n', stderr: '' });
10+
11+
const result = await readTrackedGitFiles('some/dir');
12+
13+
expect(result).toStrictEqual(['foo', 'bar']);
14+
});
15+
16+
it('should call git ls-files with the correct directory', async () => {
17+
execFileMock.mockResolvedValue({ stdout: '', stderr: '' });
18+
19+
const result = await readTrackedGitFiles('some/dir');
20+
21+
expect(exec).toHaveBeenCalledWith(
22+
'git ls-files',
23+
expect.objectContaining({
24+
cwd: 'some/dir',
25+
}),
26+
);
27+
});
28+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { exec } from '../../util/exec';
2+
3+
export const readTrackedGitFiles = async (dir: string): Promise<string[]> => {
4+
const { stdout } = await exec('git ls-files', { cwd: dir });
5+
return stdout.split('\n').filter(x => !!x);
6+
};

src/lib/util/exec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { exec as realExec } from 'child_process';
2+
import { promisify } from 'util';
3+
4+
export const exec = promisify(realExec);

0 commit comments

Comments
 (0)