private static void visitGitDirVfs(@NotNull VirtualFile gitDir) { gitDir.getChildren(); for (String subdir : GitRepositoryFiles.getSubDirRelativePaths()) { VirtualFile dir = gitDir.findFileByRelativePath(subdir); // process recursively, because we need to visit all branches under refs/heads and // refs/remotes visitAllChildrenRecursively(dir); } }
GitRepositoryUpdater(GitRepository repository) { VirtualFile gitDir = repository.getGitDir(); myWatchRequest = LocalFileSystem.getInstance().addRootToWatch(gitDir.getPath(), true); myRepositoryFiles = GitRepositoryFiles.getInstance(gitDir); visitGitDirVfs(gitDir); myHeadsDir = VcsUtil.getVirtualFile(myRepositoryFiles.getRefsHeadsPath()); myRemotesDir = VcsUtil.getVirtualFile(myRepositoryFiles.getRefsRemotesPath()); Project project = repository.getProject(); myUpdateQueue = new QueueProcessor<GitRepository.TrackedTopic>( new Updater(repository), project.getDisposed()); if (!project.isDisposed()) { myMessageBusConnection = project.getMessageBus().connect(); myMessageBusConnection.subscribe(VirtualFileManager.VFS_CHANGES, this); } else { myMessageBusConnection = null; } }
@Override public void after(@NotNull List<? extends VFileEvent> events) { // which files in .git were changed boolean configChanged = false; boolean headChanged = false; boolean branchFileChanged = false; boolean packedRefsChanged = false; boolean rebaseFileChanged = false; boolean mergeFileChanged = false; for (VFileEvent event : events) { final VirtualFile file = event.getFile(); if (file == null) { continue; } String filePath = GitFileUtils.stripFileProtocolPrefix(file.getPath()); if (myRepositoryFiles.isConfigFile(filePath)) { configChanged = true; } else if (myRepositoryFiles.isHeadFile(filePath)) { headChanged = true; } else if (myRepositoryFiles.isBranchFile(filePath)) { // it is also possible, that a local branch with complex name ("myfolder/mybranch") was // created => the folder also to be watched. branchFileChanged = true; visitAllChildrenRecursively(myHeadsDir); } else if (myRepositoryFiles.isRemoteBranchFile(filePath)) { // it is possible, that a branch from a new remote was fetch => we need to add new remote // folder to the VFS branchFileChanged = true; visitAllChildrenRecursively(myRemotesDir); } else if (myRepositoryFiles.isPackedRefs(filePath)) { packedRefsChanged = true; } else if (myRepositoryFiles.isRebaseFile(filePath)) { rebaseFileChanged = true; } else if (myRepositoryFiles.isMergeFile(filePath)) { mergeFileChanged = true; } } // what should be updated in GitRepository boolean updateCurrentBranch = false; boolean updateCurrentRevision = false; boolean updateState = false; boolean updateBranches = false; if (headChanged) { updateCurrentBranch = true; updateCurrentRevision = true; updateState = true; } if (branchFileChanged) { updateCurrentRevision = true; updateBranches = true; } if (rebaseFileChanged || mergeFileChanged) { updateState = true; } if (packedRefsChanged) { updateCurrentBranch = true; updateBranches = true; } // update GitRepository on pooled thread, because it requires reading from disk and parsing // data. if (updateCurrentBranch) { myUpdateQueue.add(GitRepository.TrackedTopic.CURRENT_BRANCH); } if (updateCurrentRevision) { myUpdateQueue.add(GitRepository.TrackedTopic.CURRENT_REVISION); } if (updateState) { myUpdateQueue.add(GitRepository.TrackedTopic.STATE); } if (updateBranches) { myUpdateQueue.add(GitRepository.TrackedTopic.BRANCHES); } if (configChanged) { myUpdateQueue.add(GitRepository.TrackedTopic.CONFIG); } }