private class MyExecutor extends AbstractExecutorService { private final AtomicBoolean isShuttingDown = new AtomicBoolean(); private final QueueProcessor<Runnable> myProcessor = QueueProcessor.createRunnableQueueProcessor(); @Override public void shutdown() { myProcessor.clear(); isShuttingDown.set(myDisposed); } @Override public List<Runnable> shutdownNow() { throw new UnsupportedOperationException(); } @Override public boolean isShutdown() { return isShuttingDown.get(); } @Override public boolean isTerminated() { return isShutdown() && myProcessor.isEmpty(); } @Override public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException { throw new UnsupportedOperationException(); } @Override public void execute(@NotNull Runnable command) { myProcessor.add(command); } }
@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); } }
@Override public void execute(@NotNull Runnable command) { myProcessor.add(command); }
@Override public boolean isTerminated() { return isShutdown() && myProcessor.isEmpty(); }
@Override public void shutdown() { myProcessor.clear(); isShuttingDown.set(myDisposed); }