mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Support Git submodules as nested roots
Submodules in Git don't have a .git dir. Instead they have .git file referencing to the actual Git repository located in <super_project>/.git/modules/<module_name> To get the .git dir use GitUtil.findGitDir This fixes IDEA-80047 and IDEA-79674
This commit is contained in:
@@ -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
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -89,14 +89,18 @@ public class GitUntrackedFilesHolder implements Disposable, BulkFileListener {
|
||||
private Set<VirtualFile> myPossiblyTrackedFiles = new HashSet<VirtualFile>();
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user