optional show/hide vcs console tool window (via rehistry)
[fedora-idea.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / impl / ProjectLevelVcsManagerImpl.java
blob8446ab8ed23bb3a3fd0b0cc6b8b8dd6acc39c6fb
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.vcs.impl;
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.application.ModalityState;
20 import com.intellij.openapi.components.ProjectComponent;
21 import com.intellij.openapi.components.StorageScheme;
22 import com.intellij.openapi.diagnostic.Logger;
23 import com.intellij.openapi.editor.DisposableEditorPanel;
24 import com.intellij.openapi.editor.Editor;
25 import com.intellij.openapi.editor.EditorFactory;
26 import com.intellij.openapi.editor.EditorSettings;
27 import com.intellij.openapi.editor.markup.TextAttributes;
28 import com.intellij.openapi.extensions.Extensions;
29 import com.intellij.openapi.progress.ProcessCanceledException;
30 import com.intellij.openapi.project.DumbAwareRunnable;
31 import com.intellij.openapi.project.Project;
32 import com.intellij.openapi.project.ex.ProjectEx;
33 import com.intellij.openapi.startup.StartupManager;
34 import com.intellij.openapi.util.*;
35 import com.intellij.openapi.util.io.FileUtil;
36 import com.intellij.openapi.util.registry.Registry;
37 import com.intellij.openapi.vcs.*;
38 import com.intellij.openapi.vcs.changes.ChangesUtil;
39 import com.intellij.openapi.vcs.checkin.CheckinHandlerFactory;
40 import com.intellij.openapi.vcs.checkout.CompositeCheckoutListener;
41 import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
42 import com.intellij.openapi.vcs.impl.projectlevelman.*;
43 import com.intellij.openapi.vcs.update.ActionInfo;
44 import com.intellij.openapi.vcs.update.UpdateInfoTree;
45 import com.intellij.openapi.vcs.update.UpdatedFiles;
46 import com.intellij.openapi.vfs.LocalFileSystem;
47 import com.intellij.openapi.vfs.VfsUtil;
48 import com.intellij.openapi.vfs.VirtualFile;
49 import com.intellij.openapi.wm.ToolWindow;
50 import com.intellij.openapi.wm.ToolWindowAnchor;
51 import com.intellij.openapi.wm.ToolWindowId;
52 import com.intellij.openapi.wm.ToolWindowManager;
53 import com.intellij.ui.content.Content;
54 import com.intellij.ui.content.ContentFactory;
55 import com.intellij.ui.content.ContentManager;
56 import com.intellij.util.ContentsUtil;
57 import com.intellij.util.EventDispatcher;
58 import com.intellij.util.Icons;
59 import com.intellij.util.Processor;
60 import com.intellij.util.containers.Convertor;
61 import com.intellij.util.ui.EditorAdapter;
62 import org.jdom.Element;
63 import org.jetbrains.annotations.NonNls;
64 import org.jetbrains.annotations.NotNull;
65 import org.jetbrains.annotations.Nullable;
67 import java.util.*;
69 public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx implements ProjectComponent, JDOMExternalizable {
70 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl");
72 private final ProjectLevelVcsManagerSerialization mySerialization;
73 private final OptionsAndConfirmations myOptionsAndConfirmations;
75 private NewMappings myMappings;
76 private final Project myProject;
77 private MappingsToRoots myMappingsToRoots;
79 private volatile boolean myIsDisposed = false;
80 private final Object myDisposeLock = new Object();
82 private ContentManager myContentManager;
83 private EditorAdapter myEditorAdapter;
85 private final VcsInitialization myInitialization;
87 @NonNls private static final String ELEMENT_MAPPING = "mapping";
88 @NonNls private static final String ATTRIBUTE_DIRECTORY = "directory";
89 @NonNls private static final String ATTRIBUTE_VCS = "vcs";
90 @NonNls private static final String ATTRIBUTE_DEFAULT_PROJECT = "defaultProject";
91 @NonNls private static final String ELEMENT_ROOT_SETTINGS = "rootSettings";
92 @NonNls private static final String ATTRIBUTE_CLASS = "class";
94 private final List<CheckinHandlerFactory> myRegisteredBeforeCheckinHandlers = new ArrayList<CheckinHandlerFactory>();
95 private final EventDispatcher<VcsListener> myEventDispatcher = EventDispatcher.create(VcsListener.class);
96 private boolean myMappingsLoaded = false;
97 private boolean myHaveLegacyVcsConfiguration = false;
98 private boolean myCheckinHandlerFactoriesLoaded = false;
99 private DefaultVcsRootPolicy myDefaultVcsRootPolicy;
101 private volatile int myBackgroundOperationCounter = 0;
103 private final Map<VcsBackgroundableActions, BackgroundableActionEnabledHandler> myBackgroundableActionHandlerMap;
105 private List<Pair<String, TextAttributes>> myPendingOutput = new ArrayList<Pair<String, TextAttributes>>();
107 public ProjectLevelVcsManagerImpl(Project project) {
108 myProject = project;
109 mySerialization = new ProjectLevelVcsManagerSerialization();
110 myOptionsAndConfirmations = new OptionsAndConfirmations();
112 myDefaultVcsRootPolicy = DefaultVcsRootPolicy.getInstance(project);
114 myBackgroundableActionHandlerMap = new HashMap<VcsBackgroundableActions, BackgroundableActionEnabledHandler>();
115 myInitialization = new VcsInitialization(myProject);
116 myMappings = new NewMappings(myProject, myEventDispatcher, this);
117 myMappingsToRoots = new MappingsToRoots(myMappings, myProject);
120 public void initComponent() {
121 myOptionsAndConfirmations.init(new Convertor<String, VcsShowConfirmationOption.Value>() {
122 public VcsShowConfirmationOption.Value convert(String o) {
123 return mySerialization.getInitOptionValue(o);
128 public void registerVcs(AbstractVcs vcs) {
129 AllVcses.getInstance(myProject).registerManually(vcs);
132 @Nullable
133 public AbstractVcs findVcsByName(String name) {
134 if (name == null) return null;
135 if (myProject.isDisposed()) return null;
136 return AllVcses.getInstance(myProject).getByName(name);
139 public AbstractVcs[] getAllVcss() {
140 return AllVcses.getInstance(myProject).getAll();
143 public boolean haveVcses() {
144 return ! AllVcses.getInstance(myProject).isEmpty();
147 public void disposeComponent() {
148 if (ApplicationManager.getApplication().isUnitTestMode()) {
149 dispose();
153 public void projectOpened() {
154 final StartupManager manager = StartupManager.getInstance(myProject);
155 manager.registerPostStartupActivity(new DumbAwareRunnable() {
156 public void run() {
157 ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
158 if (toolWindowManager != null) { // Can be null in tests
159 ToolWindow toolWindow =
160 toolWindowManager.registerToolWindow(ToolWindowId.VCS, true, ToolWindowAnchor.BOTTOM, myProject, true);
161 myContentManager = toolWindow.getContentManager();
162 toolWindow.setIcon(Icons.VCS_SMALL_TAB);
163 toolWindow.installWatcher(myContentManager);
164 } else {
165 myContentManager = ContentFactory.SERVICE.getInstance().createContentManager(true, myProject);
171 public void projectClosed() {
172 dispose();
175 @NotNull
176 public String getComponentName() {
177 return "ProjectLevelVcsManager";
180 public boolean checkAllFilesAreUnder(AbstractVcs abstractVcs, VirtualFile[] files) {
181 if (files == null) return false;
182 for (VirtualFile file : files) {
183 if (getVcsFor(file) != abstractVcs) {
184 return false;
187 return true;
190 @Nullable
191 public AbstractVcs getVcsFor(@NotNull VirtualFile file) {
192 final String vcsName = myMappings.getVcsFor(file);
193 if (vcsName == null || vcsName.length() == 0) {
194 return null;
196 return AllVcses.getInstance(myProject).getByName(vcsName);
199 @Nullable
200 public AbstractVcs getVcsFor(final FilePath file) {
201 return ApplicationManager.getApplication().runReadAction(new Computable<AbstractVcs>() {
202 @Nullable
203 public AbstractVcs compute() {
204 if ((! ApplicationManager.getApplication().isUnitTestMode()) && (! myProject.isInitialized())) return null;
205 if (myProject.isDisposed()) throw new ProcessCanceledException();
206 VirtualFile vFile = ChangesUtil.findValidParent(file);
207 if (vFile != null) {
208 return getVcsFor(vFile);
210 return null;
215 @Nullable
216 public VirtualFile getVcsRootFor(final VirtualFile file) {
217 final VcsDirectoryMapping mapping = myMappings.getMappingFor(file);
218 if (mapping == null) {
219 return null;
221 final String directory = mapping.getDirectory();
222 if (directory.length() == 0) {
223 return myDefaultVcsRootPolicy.getVcsRootFor(file);
225 return LocalFileSystem.getInstance().findFileByPath(directory);
228 @Nullable
229 public VirtualFile getVcsRootFor(final FilePath file) {
230 return ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile>() {
231 @Nullable
232 public VirtualFile compute() {
233 VirtualFile vFile = ChangesUtil.findValidParent(file);
234 if (vFile != null) {
235 return getVcsRootFor(vFile);
237 return null;
242 private void dispose() {
243 // todo dispose lock is bad here..
244 synchronized (myDisposeLock) {
245 if (myIsDisposed) return;
247 myMappings.disposeMe();
248 try {
249 myContentManager = null;
251 ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
252 if (toolWindowManager != null && toolWindowManager.getToolWindow(ToolWindowId.VCS) != null) {
253 toolWindowManager.unregisterToolWindow(ToolWindowId.VCS);
256 finally {
257 myIsDisposed = true;
262 public void unregisterVcs(AbstractVcs vcs) {
263 if ((! ApplicationManager.getApplication().isUnitTestMode()) && (myMappings.haveActiveVcs(vcs.getName()))) {
264 // unlikely
265 LOG.warn("Active vcs '" + vcs.getName() + "' is being unregistered. Remove from mappings first.");
267 myMappings.beingUnregistered(vcs.getName());
268 AllVcses.getInstance(myProject).unregisterManually(vcs);
271 public ContentManager getContentManager() {
272 return myContentManager;
275 public boolean checkVcsIsActive(AbstractVcs vcs) {
276 return checkVcsIsActive(vcs.getName());
279 public boolean checkVcsIsActive(final String vcsName) {
280 return myMappings.haveActiveVcs(vcsName);
283 public AbstractVcs[] getAllActiveVcss() {
284 return myMappings.getActiveVcses();
287 public boolean hasAnyMappings() {
288 return ! myMappings.isEmpty();
291 public void addMessageToConsoleWindow(final String message, final TextAttributes attributes) {
292 if (!Registry.is("vcs.showConsole")) return;
294 ApplicationManager.getApplication().invokeLater(new Runnable() {
295 public void run() {
296 // for default and disposed projects the ContentManager is not available.
297 if (myProject.isDisposed() || myProject.isDefault()) return;
298 final ContentManager contentManager = getContentManager();
299 if (contentManager == null) {
300 myPendingOutput.add(new Pair<String, TextAttributes>(message, attributes));
302 else {
303 getOrCreateConsoleContent(contentManager);
304 myEditorAdapter.appendString(message, attributes);
307 }, ModalityState.defaultModalityState());
310 private Content getOrCreateConsoleContent(final ContentManager contentManager) {
311 final String displayName = VcsBundle.message("vcs.console.toolwindow.display.name");
312 Content content = contentManager.findContent(displayName);
313 if (content == null) {
314 final EditorFactory editorFactory = EditorFactory.getInstance();
315 final Editor editor = editorFactory.createViewer(editorFactory.createDocument(""));
316 EditorSettings editorSettings = editor.getSettings();
317 editorSettings.setLineMarkerAreaShown(false);
318 editorSettings.setLineNumbersShown(false);
319 editorSettings.setFoldingOutlineShown(false);
321 myEditorAdapter = new EditorAdapter(editor, myProject);
322 content = ContentFactory.SERVICE.getInstance().createContent(new DisposableEditorPanel(editor), displayName, true);
323 contentManager.addContent(content);
325 for (Pair<String, TextAttributes> pair : myPendingOutput) {
326 myEditorAdapter.appendString(pair.first, pair.second);
328 myPendingOutput.clear();
330 return content;
333 @NotNull
334 public VcsShowSettingOption getOptions(VcsConfiguration.StandardOption option) {
335 return myOptionsAndConfirmations.getOptions(option);
338 public List<VcsShowOptionsSettingImpl> getAllOptions() {
339 return myOptionsAndConfirmations.getAllOptions();
342 @NotNull
343 public VcsShowSettingOption getStandardOption(@NotNull VcsConfiguration.StandardOption option, @NotNull AbstractVcs vcs) {
344 final VcsShowOptionsSettingImpl options = (VcsShowOptionsSettingImpl) getOptions(option);
345 options.addApplicableVcs(vcs);
346 return options;
349 @NotNull
350 public VcsShowSettingOption getOrCreateCustomOption(@NotNull String vcsActionName, @NotNull AbstractVcs vcs) {
351 return myOptionsAndConfirmations.getOrCreateCustomOption(vcsActionName, vcs);
354 public void showProjectOperationInfo(final UpdatedFiles updatedFiles, String displayActionName) {
355 showUpdateProjectInfo(updatedFiles, displayActionName, ActionInfo.STATUS);
358 public UpdateInfoTree showUpdateProjectInfo(UpdatedFiles updatedFiles, String displayActionName, ActionInfo actionInfo) {
359 synchronized (myDisposeLock) {
360 if (myIsDisposed) return null;
361 ContentManager contentManager = getContentManager();
362 if (contentManager == null) {
363 return null; // content manager is made null during dispose; flag is set later
365 final UpdateInfoTree updateInfoTree = new UpdateInfoTree(contentManager, myProject, updatedFiles, displayActionName, actionInfo);
366 Content content = ContentFactory.SERVICE.getInstance().createContent(updateInfoTree, VcsBundle.message(
367 "toolwindow.title.update.action.info", displayActionName), true);
368 Disposer.register(content, updateInfoTree);
369 ContentsUtil.addContent(contentManager, content, true);
370 ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.VCS).activate(null);
371 updateInfoTree.expandRootChildren();
372 return updateInfoTree;
376 public void cleanupMappings() {
377 myMappings.cleanupMappings();
380 public List<VcsDirectoryMapping> getDirectoryMappings() {
381 return myMappings.getDirectoryMappings();
384 public List<VcsDirectoryMapping> getDirectoryMappings(final AbstractVcs vcs) {
385 return myMappings.getDirectoryMappings(vcs.getName());
388 @Nullable
389 public VcsDirectoryMapping getDirectoryMappingFor(final FilePath path) {
390 return ApplicationManager.getApplication().runReadAction(new Computable<VcsDirectoryMapping>() {
391 @Nullable
392 public VcsDirectoryMapping compute() {
393 VirtualFile vFile = ChangesUtil.findValidParent(path);
394 if (vFile != null) {
395 return myMappings.getMappingFor(vFile);
397 return null;
402 public boolean hasExplicitMapping(final FilePath f) {
403 VirtualFile vFile = ChangesUtil.findValidParent(f);
404 if (vFile == null) return false;
405 return hasExplicitMapping(vFile);
408 public boolean hasExplicitMapping(final VirtualFile vFile) {
409 final VcsDirectoryMapping mapping = myMappings.getMappingFor(vFile);
410 return mapping != null && (! mapping.isDefaultMapping());
413 public void setDirectoryMapping(final String path, final String activeVcsName) {
414 if (myMappingsLoaded) return; // ignore per-module VCS settings if the mapping table was loaded from .ipr
415 myHaveLegacyVcsConfiguration = true;
416 myMappings.setMapping(FileUtil.toSystemIndependentName(path), activeVcsName);
419 public void setAutoDirectoryMapping(String path, String activeVcsName) {
420 myMappings.setMapping(path, activeVcsName);
423 public void removeDirectoryMapping(VcsDirectoryMapping mapping) {
424 myMappings.removeDirectoryMapping(mapping);
427 public void setDirectoryMappings(final List<VcsDirectoryMapping> items) {
428 myMappings.setDirectoryMappings(items);
431 public void iterateVcsRoot(final VirtualFile root, final Processor<FilePath> iterator) {
432 VcsRootIterator.iterateVcsRoot(myProject, root, iterator);
435 public void readExternal(Element element) throws InvalidDataException {
436 mySerialization.readExternalUtil(element, myOptionsAndConfirmations);
439 public void writeExternal(Element element) throws WriteExternalException {
440 mySerialization.writeExternalUtil(element, myOptionsAndConfirmations);
443 @NotNull
444 public VcsShowConfirmationOption getStandardConfirmation(@NotNull VcsConfiguration.StandardConfirmation option,
445 @NotNull AbstractVcs vcs) {
446 final VcsShowConfirmationOptionImpl result = getConfirmation(option);
447 result.addApplicableVcs(vcs);
448 return result;
451 public List<VcsShowConfirmationOptionImpl> getAllConfirmations() {
452 return myOptionsAndConfirmations.getAllConfirmations();
455 @NotNull
456 public VcsShowConfirmationOptionImpl getConfirmation(VcsConfiguration.StandardConfirmation option) {
457 return myOptionsAndConfirmations.getConfirmation(option);
460 public List<CheckinHandlerFactory> getRegisteredCheckinHandlerFactories() {
461 if (!myCheckinHandlerFactoriesLoaded) {
462 myCheckinHandlerFactoriesLoaded = true;
463 Collections.addAll(myRegisteredBeforeCheckinHandlers, Extensions.getExtensions(CheckinHandlerFactory.EP_NAME, myProject));
465 return Collections.unmodifiableList(myRegisteredBeforeCheckinHandlers);
468 public void registerCheckinHandlerFactory(CheckinHandlerFactory factory) {
469 myRegisteredBeforeCheckinHandlers.add(factory);
472 public void unregisterCheckinHandlerFactory(CheckinHandlerFactory handler) {
473 myRegisteredBeforeCheckinHandlers.remove(handler);
476 public void addVcsListener(VcsListener listener) {
477 myEventDispatcher.addListener(listener);
480 public void removeVcsListener(VcsListener listener) {
481 myEventDispatcher.removeListener(listener);
484 public void startBackgroundVcsOperation() {
485 myBackgroundOperationCounter++;
488 public void stopBackgroundVcsOperation() {
489 // in fact, the condition is "should not be called under ApplicationManager.invokeLater() and similiar"
490 assert ! ApplicationManager.getApplication().isDispatchThread();
491 LOG.assertTrue(myBackgroundOperationCounter > 0, "myBackgroundOperationCounter > 0");
492 myBackgroundOperationCounter--;
495 public boolean isBackgroundVcsOperationRunning() {
496 return myBackgroundOperationCounter > 0;
499 public VirtualFile[] getRootsUnderVcs(AbstractVcs vcs) {
500 return myMappingsToRoots.getRootsUnderVcs(vcs);
503 public VirtualFile[] getAllVersionedRoots() {
504 List<VirtualFile> vFiles = new ArrayList<VirtualFile>();
505 final AbstractVcs[] vcses = myMappings.getActiveVcses();
506 for (AbstractVcs vcs : vcses) {
507 Collections.addAll(vFiles, getRootsUnderVcs(vcs));
509 return VfsUtil.toVirtualFileArray(vFiles);
512 @NotNull
513 public VcsRoot[] getAllVcsRoots() {
514 List<VcsRoot> vcsRoots = new ArrayList<VcsRoot>();
515 final AbstractVcs[] vcses = myMappings.getActiveVcses();
516 for (AbstractVcs vcs : vcses) {
517 final VirtualFile[] roots = getRootsUnderVcs(vcs);
518 for(VirtualFile root: roots) {
519 vcsRoots.add(new VcsRoot(vcs, root));
522 return vcsRoots.toArray(new VcsRoot[vcsRoots.size()]);
525 public void updateActiveVcss() {
526 // not needed
529 public void notifyDirectoryMappingChanged() {
530 myEventDispatcher.getMulticaster().directoryMappingChanged();
533 public void readDirectoryMappings(final Element element) {
534 myMappings.clear();
536 final List<VcsDirectoryMapping> mappingsList = new ArrayList<VcsDirectoryMapping>();
537 final List list = element.getChildren(ELEMENT_MAPPING);
538 boolean haveNonEmptyMappings = false;
539 for(Object childObj: list) {
540 Element child = (Element) childObj;
541 final String vcs = child.getAttributeValue(ATTRIBUTE_VCS);
542 if (vcs != null && vcs.length() > 0) {
543 haveNonEmptyMappings = true;
545 VcsDirectoryMapping mapping = new VcsDirectoryMapping(child.getAttributeValue(ATTRIBUTE_DIRECTORY), vcs);
546 mappingsList.add(mapping);
548 Element rootSettingsElement = child.getChild(ELEMENT_ROOT_SETTINGS);
549 if (rootSettingsElement != null) {
550 String className = rootSettingsElement.getAttributeValue(ATTRIBUTE_CLASS);
551 AbstractVcs vcsInstance = findVcsByName(mapping.getVcs());
552 if (vcsInstance != null && className != null) {
553 final VcsRootSettings rootSettings = vcsInstance.createEmptyVcsRootSettings();
554 if (rootSettings != null) {
555 try {
556 rootSettings.readExternal(rootSettingsElement);
557 mapping.setRootSettings(rootSettings);
558 } catch (InvalidDataException e) {
559 LOG.error("Failed to load VCS root settings class "+ className + " for VCS " + vcsInstance.getClass().getName(), e);
565 boolean defaultProject = Boolean.TRUE.toString().equals(element.getAttributeValue(ATTRIBUTE_DEFAULT_PROJECT));
566 // run autodetection if there's no VCS in default project and
567 if (haveNonEmptyMappings || !defaultProject) {
568 myMappingsLoaded = true;
570 myMappings.setDirectoryMappings(mappingsList);
573 public void writeDirectoryMappings(final Element element) {
574 if (myProject.isDefault()) {
575 element.setAttribute(ATTRIBUTE_DEFAULT_PROJECT, Boolean.TRUE.toString());
577 for(VcsDirectoryMapping mapping: getDirectoryMappings()) {
578 Element child = new Element(ELEMENT_MAPPING);
579 child.setAttribute(ATTRIBUTE_DIRECTORY, mapping.getDirectory());
580 child.setAttribute(ATTRIBUTE_VCS, mapping.getVcs());
581 final VcsRootSettings rootSettings = mapping.getRootSettings();
582 if (rootSettings != null) {
583 Element rootSettingsElement = new Element(ELEMENT_ROOT_SETTINGS);
584 rootSettingsElement.setAttribute(ATTRIBUTE_CLASS, rootSettings.getClass().getName());
585 try {
586 rootSettings.writeExternal(rootSettingsElement);
587 child.addContent(rootSettingsElement);
589 catch (WriteExternalException e) {
590 // don't add element
593 element.addContent(child);
597 public boolean needAutodetectMappings() {
598 return !myHaveLegacyVcsConfiguration && !myMappingsLoaded;
601 @Nullable
602 public AbstractVcs findVersioningVcs(VirtualFile file) {
603 for(AbstractVcs vcs: getAllVcss()) {
604 if (vcs.isVersionedDirectory(file)) {
605 return vcs;
608 return null;
611 public CheckoutProvider.Listener getCompositeCheckoutListener() {
612 return new CompositeCheckoutListener(myProject);
615 public void fireDirectoryMappingsChanged() {
616 if (! myIsDisposed) {
617 myMappings.mappingsChanged();
621 public String haveDefaultMapping() {
622 return myMappings.haveDefaultMapping();
625 public BackgroundableActionEnabledHandler getBackgroundableActionHandler(final VcsBackgroundableActions action) {
626 ApplicationManager.getApplication().assertIsDispatchThread();
628 BackgroundableActionEnabledHandler result = myBackgroundableActionHandlerMap.get(action);
629 if (result == null) {
630 result = new BackgroundableActionEnabledHandler();
631 myBackgroundableActionHandlerMap.put(action, result);
633 return result;
636 public void addInitializationRequest(final VcsInitObject vcsInitObject, final Runnable runnable) {
637 ApplicationManager.getApplication().runReadAction(new Runnable() {
638 public void run() {
639 myInitialization.add(vcsInitObject, runnable);
644 public boolean isFileInContent(final VirtualFile vf) {
645 final ExcludedFileIndex excludedIndex = ExcludedFileIndex.getInstance(myProject);
646 return (vf != null) && (excludedIndex.isInContent(vf) || isFileInBaseDir(vf) || vf.equals(myProject.getBaseDir()) ||
647 hasExplicitMapping(vf) || isInDirectoryBasedRoot(vf)) && (! excludedIndex.isExcludedFile(vf));
650 private boolean isInDirectoryBasedRoot(final VirtualFile file) {
651 if (file == null) return false;
652 final StorageScheme storageScheme = ((ProjectEx) myProject).getStateStore().getStorageScheme();
653 if (StorageScheme.DIRECTORY_BASED.equals(storageScheme)) {
654 final VirtualFile ideaDir = myProject.getBaseDir().findChild(Project.DIRECTORY_STORE_FOLDER);
655 return (ideaDir != null && ideaDir.isValid() && ideaDir.isDirectory() && VfsUtil.isAncestor(ideaDir, file, false));
657 return false;
660 private boolean isFileInBaseDir(final VirtualFile file) {
661 VirtualFile parent = file.getParent();
662 return !file.isDirectory() && parent != null && parent.equals(myProject.getBaseDir());