Skip to content

Commit 50f4935

Browse files
committed
fix: add support for git worktree
fixes #87
1 parent 6e8b02e commit 50f4935

File tree

6 files changed

+44
-35
lines changed

6 files changed

+44
-35
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
"@softwareventures/array": "6.1.0",
3030
"@softwareventures/nullable": "3.2.0",
3131
"execa": "5.1.1",
32-
"find-up": "5.0.0",
3332
"glob": "8.1.0",
3433
"ignore": "5.3.1",
3534
"mri": "1.2.0",

src/git-utils.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
import {sync as findUpSync} from "find-up";
2-
import {dirname} from "path";
3-
4-
import {runCommandSync} from "./utils";
1+
import {normalize} from "path";
52
import {hasProperty} from "unknown";
63
import {notNull} from "@softwareventures/nullable";
4+
import {runCommandSync} from "./utils";
75

86
interface DiffIndexFile {
97
diffFilterChar: string;
108
filename: string;
119
}
1210

13-
export function resolveNearestGitDirectoryParent(workingDirectory: string) {
14-
const gitDirectoryPath = findUpSync(".git", {cwd: workingDirectory, type: "directory"});
15-
if (!gitDirectoryPath) {
16-
throw new Error("No .git directory found");
17-
}
18-
return dirname(gitDirectoryPath);
11+
export function resolveGitWorkingTreePath(workingDirectory: string): string {
12+
return normalize(
13+
runCommandSync("git", ["rev-parse", "--show-toplevel"], workingDirectory).stdout
14+
);
1915
}
2016

2117
export const index = Symbol("index");

src/index.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import {isAbsolute, join, relative} from "path";
22

33
import type {Observable} from "rxjs";
4-
import {
5-
getModifiedFilenames,
6-
index,
7-
resolveNearestGitDirectoryParent,
8-
workingTree
9-
} from "./git-utils";
4+
import {getModifiedFilenames, index, resolveGitWorkingTreePath, workingTree} from "./git-utils";
105
import {NO_LINE_CHANGE_DATA_ERROR, generateFilesWhitelistPredicate} from "./utils";
116
import {ModifiedFile} from "./modified-file";
127
import {preciseFormatterPrettier} from "./precise-formatters/prettier";
@@ -87,15 +82,15 @@ export function main(
8782

8883
emit({event: "Init", workingDirectory});
8984

90-
// Resolve the relevant .git directory's parent directory up front, as we will need this when
91-
// executing various `git` commands.
92-
const gitDirectoryParent = resolveNearestGitDirectoryParent(workingDirectory);
85+
// Resolve the working tree path up front, as we will need this
86+
// when executing various `git` commands.
87+
const workingTreePath = resolveGitWorkingTreePath(workingDirectory);
9388

9489
// We fundamentally check whether or not the file extensions are supported by the given formatter,
9590
// whether or not they are included in the optional `filesWhitelist` array, and that the user
9691
// has not chosen to ignore them via any supported "ignore" mechanism of the formatter.
97-
const modifiedFiles = getModifiedFilenames(gitDirectoryParent, options.base, options.head)
98-
.map(path => join(gitDirectoryParent, path))
92+
const modifiedFiles = getModifiedFilenames(workingTreePath, options.base, options.head)
93+
.map(path => join(workingTreePath, path))
9994
.map(path => relative(workingDirectory, path))
10095
.filter(path => !isAbsolute(path))
10196
.filter(selectedFormatter.hasSupportedFileExtension)
@@ -114,7 +109,7 @@ export function main(
114109
// Read the modified file contents and resolve the relevant formatter.
115110
const modifiedFile = new ModifiedFile({
116111
fullPath,
117-
gitDirectoryParent,
112+
gitDirectoryParent: workingTreePath,
118113
base: options.base,
119114
head: options.head ?? index,
120115
selectedFormatter
@@ -182,7 +177,7 @@ export function main(
182177
if (options.head == null) {
183178
const workingTreeFile = new ModifiedFile({
184179
fullPath,
185-
gitDirectoryParent,
180+
gitDirectoryParent: workingTreePath,
186181
base: options.base,
187182
head: workingTree,
188183
selectedFormatter

test/git-utils.spec.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
import {TestBed, readFixtures} from "./test-utils";
1+
import {sep} from "path";
2+
import * as tempy from "tempy";
3+
import {mkdirp} from "mkdirp";
4+
import {runCommandSync} from "../src/utils";
25
import {
36
getDiffForFile,
4-
resolveNearestGitDirectoryParent,
7+
resolveGitWorkingTreePath,
58
getModifiedFilenames,
69
index
710
} from "../src/git-utils";
11+
import {TestBed, readFixtures} from "./test-utils";
812

913
const fixtures = readFixtures();
1014
let testBed: TestBed;
1115

1216
describe("git-utils", () => {
13-
describe("resolveNearestGitDirectoryParent()", () => {
17+
describe("resolveGitWorkingTreePath()", () => {
1418
beforeAll(() => {
1519
testBed = new TestBed();
1620
});
@@ -26,11 +30,21 @@ describe("git-utils", () => {
2630
/**
2731
* The tmpFile should resolve to its own .git directory
2832
*/
29-
expect(resolveNearestGitDirectoryParent(tmpFile.directoryPath)).toEqual(
33+
expect(resolveGitWorkingTreePath(tmpFile.directoryPath)).toEqual(
3034
tmpFile.directoryPath
3135
);
3236
});
3337
});
38+
39+
it(`should resolve the correct working tree path in a working tree created by git worktree`, async () => {
40+
await tempy.directory.task(async worktreePath => {
41+
runCommandSync("git", ["worktree", "add", "-B", "worktree", worktreePath]);
42+
const subdirPath = `${worktreePath}${sep}subdir`;
43+
await mkdirp(subdirPath);
44+
expect(resolveGitWorkingTreePath(subdirPath)).toEqual(worktreePath);
45+
runCommandSync("git", ["worktree", "remove", worktreePath]);
46+
});
47+
});
3448
});
3549

3650
describe("getDiffForFile()", () => {
@@ -46,8 +60,9 @@ describe("git-utils", () => {
4660
it(fixture.fixtureName, () => {
4761
testBed.prepareFixtureInTmpDirectory(fixture);
4862
const tmpFile = testBed.getTmpFileForFixture(fixture);
63+
const gitDirectoryParent = resolveGitWorkingTreePath(tmpFile.directoryPath);
4964
const diff = getDiffForFile(
50-
resolveNearestGitDirectoryParent(tmpFile.directoryPath),
65+
gitDirectoryParent,
5166
tmpFile.path,
5267
tmpFile.initialCommitSHA,
5368
tmpFile.updatedCommitSHA ?? index
@@ -70,8 +85,9 @@ describe("git-utils", () => {
7085
it(fixture.fixtureName, () => {
7186
testBed.prepareFixtureInTmpDirectory(fixture);
7287
const tmpFile = testBed.getTmpFileForFixture(fixture);
88+
const gitDirectoryParent = resolveGitWorkingTreePath(tmpFile.directoryPath);
7389
const fileNames = getModifiedFilenames(
74-
resolveNearestGitDirectoryParent(tmpFile.directoryPath),
90+
gitDirectoryParent,
7591
tmpFile.initialCommitSHA,
7692
tmpFile.updatedCommitSHA
7793
);

test/modified-file.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {TestBed, readFixtures} from "./test-utils";
22

33
import {ModifiedFile} from "../src/modified-file";
44
import {preciseFormatterPrettier} from "../src/precise-formatters/prettier";
5-
import {resolveNearestGitDirectoryParent, workingTree} from "../src/git-utils";
5+
import {resolveGitWorkingTreePath, workingTree} from "../src/git-utils";
66

77
const fixtures = readFixtures();
88
let testBed: TestBed;
@@ -21,9 +21,10 @@ describe("ModifiedFile", () => {
2121
it(fixture.fixtureName, () => {
2222
testBed.prepareFixtureInTmpDirectory(fixture);
2323
const tmpFile = testBed.getTmpFileForFixture(fixture);
24+
const gitDirectoryParent = resolveGitWorkingTreePath(tmpFile.directoryPath);
2425
const modifiedFile = new ModifiedFile({
2526
fullPath: tmpFile.path,
26-
gitDirectoryParent: resolveNearestGitDirectoryParent(tmpFile.directoryPath),
27+
gitDirectoryParent,
2728
base: tmpFile.initialCommitSHA,
2829
head: tmpFile.updatedCommitSHA ?? workingTree,
2930
selectedFormatter: preciseFormatterPrettier

test/utils.spec.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {TestBed, readFixtures} from "./test-utils";
2-
import {getDiffForFile, index, resolveNearestGitDirectoryParent} from "../src/git-utils";
2+
import {getDiffForFile, index, resolveGitWorkingTreePath} from "../src/git-utils";
33
import {extractLineChangeData, calculateCharacterRangesFromLineChanges} from "../src/utils";
44

55
const fixtures = readFixtures();
@@ -39,8 +39,9 @@ describe("utils", () => {
3939
it(fixture.fixtureName, () => {
4040
testBed.prepareFixtureInTmpDirectory(fixture);
4141
const tmpFile = testBed.getTmpFileForFixture(fixture);
42+
const gitDirectoryParent = resolveGitWorkingTreePath(tmpFile.directoryPath);
4243
const diff = getDiffForFile(
43-
resolveNearestGitDirectoryParent(tmpFile.directoryPath),
44+
gitDirectoryParent,
4445
tmpFile.path,
4546
tmpFile.initialCommitSHA,
4647
tmpFile.updatedCommitSHA ?? index
@@ -64,8 +65,9 @@ describe("utils", () => {
6465
it(fixture.fixtureName, () => {
6566
testBed.prepareFixtureInTmpDirectory(fixture);
6667
const tmpFile = testBed.getTmpFileForFixture(fixture);
68+
const gitDirectoryParent = resolveGitWorkingTreePath(tmpFile.directoryPath);
6769
const diff = getDiffForFile(
68-
resolveNearestGitDirectoryParent(tmpFile.directoryPath),
70+
gitDirectoryParent,
6971
tmpFile.path,
7072
tmpFile.initialCommitSHA,
7173
tmpFile.updatedCommitSHA ?? index

0 commit comments

Comments
 (0)