Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Recognize git worktree directories as valid git repositories #19832

Merged
merged 1 commit into from
Nov 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions spec/fixtures/git/master.git/config
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
[remote "origin"]
url = https://github.com/example-user/example-repo.git
fetch = +refs/heads/*:refs/remotes/origin/*
[gc]
worktreePruneExpire = never
1 change: 1 addition & 0 deletions spec/fixtures/git/master.git/worktrees/worktree-dir/HEAD
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ef046e9eecaa5255ea5e9817132d4001724d6ae1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
../..
Binary file not shown.
38 changes: 38 additions & 0 deletions spec/git-repository-provider-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,25 @@ describe('GitRepositoryProvider', () => {
});
});

describe('when specified a Directory with a commondir file for a worktree', () => {
it('returns a Promise that resolves to a GitRepository', async () => {
const directory = new Directory(
path.join(
__dirname,
'fixtures',
'git',
'master.git',
'worktrees',
'worktree-dir'
)
);
const result = await provider.repositoryForDirectory(directory);
expect(result).toBeInstanceOf(GitRepository);
expect(provider.pathToRepository[result.getPath()]).toBeTruthy();
expect(result.getType()).toBe('git');
});
});

describe('when specified a Directory without exists()', () => {
let directory;

Expand Down Expand Up @@ -193,6 +212,25 @@ describe('GitRepositoryProvider', () => {
});
});

describe('when specified a Directory with a commondir file for a worktree', () => {
it('returns a Promise that resolves to a GitRepository', () => {
const directory = new Directory(
path.join(
__dirname,
'fixtures',
'git',
'master.git',
'worktrees',
'worktree-dir'
)
);
const result = provider.repositoryForDirectorySync(directory);
expect(result).toBeInstanceOf(GitRepository);
expect(provider.pathToRepository[result.getPath()]).toBeTruthy();
expect(result.getType()).toBe('git');
});
});

describe('when specified a Directory without existsSync()', () => {
let directory;

Expand Down
32 changes: 28 additions & 4 deletions src/git-repository-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,22 @@ function isValidGitDirectorySync(directory) {
// To decide whether a directory has a valid .git folder, we use
// the heuristic adopted by the valid_repository_path() function defined in
// node_modules/git-utils/deps/libgit2/src/repository.c.
const commonDirFile = directory.getSubdirectory('commondir');
let commonDir;
if (commonDirFile.existsSync()) {
const commonDirPathBuff = fs.readFileSync(commonDirFile.getPath());
const commonDirPathString = commonDirPathBuff.toString().trim();
commonDir = new Directory(directory.resolve(commonDirPathString));
if (!commonDir.existsSync()) {
return false;
}
} else {
commonDir = directory;
}
return (
directory.getSubdirectory('objects').existsSync() &&
directory.getFile('HEAD').existsSync() &&
directory.getSubdirectory('refs').existsSync()
commonDir.getSubdirectory('objects').existsSync() &&
commonDir.getSubdirectory('refs').existsSync()
);
}

Expand All @@ -114,10 +126,22 @@ async function isValidGitDirectory(directory) {
// To decide whether a directory has a valid .git folder, we use
// the heuristic adopted by the valid_repository_path() function defined in
// node_modules/git-utils/deps/libgit2/src/repository.c.
const commonDirFile = directory.getSubdirectory('commondir');
let commonDir;
if (await commonDirFile.exists()) {
const commonDirPathBuff = await fs.readFile(commonDirFile.getPath());
const commonDirPathString = commonDirPathBuff.toString().trim();
commonDir = new Directory(directory.resolve(commonDirPathString));
if (!(await commonDir.exists())) {
return false;
}
} else {
commonDir = directory;
}
return (
(await directory.getSubdirectory('objects').exists()) &&
(await directory.getFile('HEAD').exists()) &&
directory.getSubdirectory('refs').exists()
(await commonDir.getSubdirectory('objects').exists()) &&
commonDir.getSubdirectory('refs').exists()
);
}

Expand Down