diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java index adcc40604db6..9d21bab8482c 100644 --- a/plugins/git4idea/src/git4idea/GitUtil.java +++ b/plugins/git4idea/src/git4idea/GitUtil.java @@ -48,6 +48,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.*; @@ -93,6 +94,43 @@ public class GitUtil { // do nothing } + @Nullable + public static VirtualFile findGitDir(@NotNull VirtualFile rootDir) { + VirtualFile child = rootDir.findChild(".git"); + if (child == null) { + return null; + } + if (child.isDirectory()) { + return child; + } + + // this is standard for submodules, although probably it can + String content = readFile(child); + String pathToDir; + String prefix = "gitdir:"; + if (content.startsWith(prefix)) { + pathToDir = content.substring(prefix.length()).trim(); + } + else { + pathToDir = content; + } + return VcsUtil.getVirtualFile(pathToDir); + } + + @NotNull + private static String readFile(@NotNull VirtualFile file) { + Exception exception = null; + for (int attempts = 0; attempts < 3; attempts++) { + try { + return new String(file.contentsToByteArray()); + } + catch (IOException e) { + exception = e; + } + } + throw new RuntimeException("Couldn't read " + file, exception); + } + /** * Sort files by Git root * diff --git a/plugins/git4idea/src/git4idea/repo/GitRepository.java b/plugins/git4idea/src/git4idea/repo/GitRepository.java index b3d88b4b5efc..12f571199f28 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepository.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepository.java @@ -26,6 +26,7 @@ import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.messages.Topic; import git4idea.GitBranch; +import git4idea.GitUtil; import git4idea.branch.GitBranchesCollection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -174,12 +175,12 @@ public final class GitRepository implements Disposable { myProject = project; Disposer.register(parentDisposable, this); - myGitDir = myRootDir.findChild(".git"); + myGitDir = GitUtil.findGitDir(myRootDir); assert myGitDir != null : ".git directory wasn't found under " + rootDir.getPresentableUrl(); myReader = new GitRepositoryReader(VfsUtil.virtualToIoFile(myGitDir)); - myUntrackedFilesHolder = new GitUntrackedFilesHolder(rootDir, project); + myUntrackedFilesHolder = new GitUntrackedFilesHolder(this); Disposer.register(this, myUntrackedFilesHolder); myMessageBus = project.getMessageBus(); @@ -222,6 +223,11 @@ public final class GitRepository implements Disposable { return myRootDir; } + @NotNull + public VirtualFile getGitDir() { + return myGitDir; + } + @NotNull public String getPresentableUrl() { return getRoot().getPresentableUrl(); diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java index 3dea7f406c29..d4f68bb512f4 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java @@ -45,16 +45,13 @@ public class GitRepositoryFiles { private final String myCommitMessagePath; private final String myExcludePath; - public static GitRepositoryFiles getInstance(@NotNull VirtualFile root) { + public static GitRepositoryFiles getInstance(@NotNull VirtualFile gitDir) { // maybe will be cached later to store a single GitRepositoryFiles for a root. - return new GitRepositoryFiles(root); + return new GitRepositoryFiles(gitDir); } - private GitRepositoryFiles(@NotNull VirtualFile root) { + private GitRepositoryFiles(@NotNull VirtualFile gitDir) { // add .git/ and .git/refs/heads to the VFS - VirtualFile gitDir = root.findChild(".git"); - assert gitDir != null; - // save paths of the files, that we will watch String gitDirPath = GitFileUtils.stripFileProtocolPrefix(gitDir.getPath()); myConfigFilePath = gitDirPath + "/config"; diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java index cce8a02bf5ba..b495b534a295 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java @@ -50,11 +50,10 @@ final class GitRepositoryUpdater implements Disposable, BulkFileListener { myRepository = repository; VirtualFile root = repository.getRoot(); - VirtualFile gitDir = root.findChild(".git"); - assert gitDir != null; + VirtualFile gitDir = repository.getGitDir(); LocalFileSystem.getInstance().addRootToWatch(gitDir.getPath(), true); - myRepositoryFiles = GitRepositoryFiles.getInstance(root); + myRepositoryFiles = GitRepositoryFiles.getInstance(gitDir); visitGitDirVfs(gitDir); myHeadsDir = VcsUtil.getVirtualFile(myRepositoryFiles.getRefsHeadsPath()); myRemotesDir = VcsUtil.getVirtualFile(myRepositoryFiles.getRefsRemotesPath()); diff --git a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java index 31d2aee06b2c..356ba991486b 100644 --- a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java +++ b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java @@ -89,14 +89,18 @@ public class GitUntrackedFilesHolder implements Disposable, BulkFileListener { private Set myPossiblyTrackedFiles = new HashSet(); private boolean myReady; // if false, total refresh is needed private final Object LOCK = new Object(); + private final GitRepositoryManager myRepositoryManager; - GitUntrackedFilesHolder(@NotNull VirtualFile root, @NotNull Project project) { - myProject = project; - myRoot = root; - myRepositoryFiles = GitRepositoryFiles.getInstance(root); - myChangeListManager = ChangeListManager.getInstance(project); - myDirtyScopeManager = VcsDirtyScopeManager.getInstance(project); + GitUntrackedFilesHolder(@NotNull GitRepository repository) { + myProject = repository.getProject(); + myRoot = repository.getRoot(); + myChangeListManager = ChangeListManager.getInstance(myProject); + myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject); myGit = ServiceManager.getService(Git.class); + + myRepositoryManager = GitUtil.getRepositoryManager(myProject); + assert myRepositoryManager != null; + myRepositoryFiles = GitRepositoryFiles.getInstance(repository.getGitDir()); } void setupVfsListener(@NotNull Project project) { @@ -302,7 +306,7 @@ public class GitUntrackedFilesHolder implements Disposable, BulkFileListener { } private boolean belongsToThisRepository(VirtualFile file) { - final GitRepository repository = GitUtil.getRepositoryManager(myProject).getRepositoryForFile(file); + final GitRepository repository = myRepositoryManager.getRepositoryForFile(file); return repository != null && repository.getRoot().equals(myRoot); }