dd34b99dfddefecf1dda65526367873945b272bb
[fedora-idea.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / impl / ProjectLevelVcsManagerImpl.java
blobdd34b99dfddefecf1dda65526367873945b272bb
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.vcs.*;
37 import com.intellij.openapi.vcs.changes.ChangesUtil;
38 import com.intellij.openapi.vcs.checkin.CheckinHandlerFactory;
39 import com.intellij.openapi.vcs.checkout.CompositeCheckoutListener;
40 import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
41 import com.intellij.openapi.vcs.impl.projectlevelman.*;
42 import com.intellij.openapi.vcs.update.ActionInfo;
43 import com.intellij.openapi.vcs.update.UpdateInfoTree;
44 import com.intellij.openapi.vcs.update.UpdatedFiles;
45 import com.intellij.openapi.vfs.LocalFileSystem;
46 import com.intellij.openapi.vfs.VfsUtil;
47 import com.intellij.openapi.vfs.VirtualFile;
48 import com.intellij.openapi.wm.ToolWindow;
49 import com.intellij.openapi.wm.ToolWindowAnchor;
50 import com.intellij.openapi.wm.ToolWindowId;
51 import com.intellij.openapi.wm.ToolWindowManager;
52 import com.intellij.ui.content.Content;
53 import com.intellij.ui.content.ContentFactory;
54 import com.intellij.ui.content.ContentManager;
55 import com.intellij.util.ContentsUtil;
56 import com.intellij.util.EventDispatcher;
57 import com.intellij.util.Icons;
58 import com.intellij.util.Processor;
59 import com.intellij.util.containers.Convertor;
60 import com.intellij.util.ui.EditorAdapter;
61 import org.jdom.Element;
62 import org.jetbrains.annotations.NonNls;
63 import org.jetbrains.annotations.NotNull;
64 import org.jetbrains.annotations.Nullable;
66 import java.util.*;
68 public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx implements ProjectComponent, JDOMExternalizable {
69 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl");
71 private final ProjectLevelVcsManagerSerialization mySerialization;
72 private final OptionsAndConfirmations myOptionsAndConfirmations;
74 private NewMappings myMappings;
75 private final Project myProject;
76 private MappingsToRoots myMappingsToRoots;
78 private volatile boolean myIsDisposed = false;
79 private final Object myDisposeLock = new Object();
81 private ContentManager myContentManager;
82 private EditorAdapter myEditorAdapter;
84 private final VcsInitialization myInitialization;
86 @NonNls private static final String ELEMENT_MAPPING = "mapping";
87 @NonNls private static final String ATTRIBUTE_DIRECTORY = "directory";
88 @NonNls private static final String ATTRIBUTE_VCS = "vcs";
89 @NonNls private static final String ATTRIBUTE_DEFAULT_PROJECT = "defaultProject";
90 @NonNls private static final String ELEMENT_ROOT_SETTINGS = "rootSettings";
91 @NonNls private static final String ATTRIBUTE_CLASS = "class";
93 private final List<CheckinHandlerFactory> myRegisteredBeforeCheckinHandlers = new ArrayList<CheckinHandlerFactory>();
94 private final EventDispatcher<VcsListener> myEventDispatcher = EventDispatcher.create(VcsListener.class);
95 private boolean myMappingsLoaded = false;
96 private boolean myHaveLegacyVcsConfiguration = false;
97 private boolean myCheckinHandlerFactoriesLoaded = false;
98 private DefaultVcsRootPolicy myDefaultVcsRootPolicy;
100 private volatile int myBackgroundOperationCounter = 0;
102 private final Map<VcsBackgroundableActions, BackgroundableActionEnabledHandler> myBackgroundableActionHandlerMap;
104 private List<Pair<String, TextAttributes>> myPendingOutput = new ArrayList<Pair<String, TextAttributes>>();
106 public ProjectLevelVcsManagerImpl(Project project) {
107 myProject = project;
108 mySerialization = new ProjectLevelVcsManagerSerialization();
109 myOptionsAndConfirmations = new OptionsAndConfirmations();
111 myDefaultVcsRootPolicy = DefaultVcsRootPolicy.getInstance(project);
113 myBackgroundableActionHandlerMap = new HashMap<VcsBackgroundableActions, BackgroundableActionEnabledHandler>();
114 myInitialization = new VcsInitialization(myProject);
115 myMappings = new NewMappings(myProject, myEventDispatcher, this);
116 myMappingsToRoots = new MappingsToRoots(myMappings, myProject);
119 public void initComponent() {
120 myOptionsAndConfirmations.init(new Convertor<String, VcsShowConfirmationOption.Value>() {
121 public VcsShowConfirmationOption.Value convert(String o) {
122 return mySerialization.getInitOptionValue(o);
127 public void registerVcs(AbstractVcs vcs) {
128 AllVcses.getInstance(myProject).registerManually(vcs);
131 @Nullable
132 public AbstractVcs findVcsByName(String name) {
133 if (name == null) return null;
134 if (myProject.isDisposed()) return null;
135 return AllVcses.getInstance(myProject).getByName(name);
138 public AbstractVcs[] getAllVcss() {
139 return AllVcses.getInstance(myProject).getAll();
142 public boolean haveVcses() {
143 return ! AllVcses.getInstance(myProject).isEmpty();
146 public void disposeComponent() {
147 if (ApplicationManager.getApplication().isUnitTestMode()) {
148 dispose();
152 public void projectOpened() {
153 final StartupManager manager = StartupManager.getInstance(myProject);
154 manager.registerPostStartupActivity(new DumbAwareRunnable() {
155 public void run() {
156 ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
157 if (toolWindowManager != null) { // Can be null in tests
158 ToolWindow toolWindow =
159 toolWindowManager.registerToolWindow(ToolWindowId.VCS, true, ToolWindowAnchor.BOTTOM, myProject, true);
160 myContentManager = toolWindow.getContentManager();
161 toolWindow.setIcon(Icons.VCS_SMALL_TAB);
162 toolWindow.installWatcher(myContentManager);
163 } else {
164 myContentManager = ContentFactory.SERVICE.getInstance().createContentManager(true, myProject);
170 public void projectClosed() {
171 dispose();
174 @NotNull
175 public String getComponentName() {
176 return "ProjectLevelVcsManager";
179 public boolean checkAllFilesAreUnder(AbstractVcs abstractVcs, VirtualFile[] files) {
180 if (files == null) return false;
181 for (VirtualFile file : files) {
182 if (getVcsFor(file) != abstractVcs) {
183 return false;
186 return true;
189 @Nullable
190 public AbstractVcs getVcsFor(@NotNull VirtualFile file) {
191 final String vcsName = myMappings.getVcsFor(file);
192 if (vcsName == null || vcsName.length() == 0) {
193 return null;
195 return AllVcses.getInstance(myProject).getByName(vcsName);
198 @Nullable
199 public AbstractVcs getVcsFor(final FilePath file) {
200 return ApplicationManager.getApplication().runReadAction(new Computable<AbstractVcs>() {
201 @Nullable
202 public AbstractVcs compute() {
203 if ((! ApplicationManager.getApplication().isUnitTestMode()) && (! myProject.isInitialized())) return null;
204 if (myProject.isDisposed()) throw new ProcessCanceledException();
205 VirtualFile vFile = ChangesUtil.findValidParent(file);
206 if (vFile != null) {
207 return getVcsFor(vFile);
209 return null;
214 @Nullable
215 public VirtualFile getVcsRootFor(final VirtualFile file) {
216 final VcsDirectoryMapping mapping = myMappings.getMappingFor(file);
217 if (mapping == null) {
218 return null;
220 final String directory = mapping.getDirectory();
221 if (directory.length() == 0) {
222 return myDefaultVcsRootPolicy.getVcsRootFor(file);
224 return LocalFileSystem.getInstance().findFileByPath(directory);
227 @Nullable
228 public VirtualFile getVcsRootFor(final FilePath file) {
229 return ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile>() {
230 @Nullable
231 public VirtualFile compute() {
232 VirtualFile vFile = ChangesUtil.findValidParent(file);
233 if (vFile != null) {
234 return getVcsRootFor(vFile);
236 return null;
241 private void dispose() {
242 // todo dispose lock is bad here..
243 synchronized (myDisposeLock) {
244 if (myIsDisposed) return;
246 myMappings.disposeMe();
247 try {
248 myContentManager = null;
250 ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
251 if (toolWindowManager != null && toolWindowManager.getToolWindow(ToolWindowId.VCS) != null) {
252 toolWindowManager.unregisterToolWindow(ToolWindowId.VCS);
255 finally {
256 myIsDisposed = true;
261 public void unregisterVcs(AbstractVcs vcs) {
262 if ((! ApplicationManager.getApplication().isUnitTestMode()) && (myMappings.haveActiveVcs(vcs.getName()))) {
263 // unlikely
264 LOG.warn("Active vcs '" + vcs.getName() + "' is being unregistered. Remove from mappings first.");
266 myMappings.beingUnregistered(vcs.getName());
267 AllVcses.getInstance(myProject).unregisterManually(vcs);
270 public ContentManager getContentManager() {
271 return myContentManager;
274 public boolean checkVcsIsActive(AbstractVcs vcs) {
275 return checkVcsIsActive(vcs.getName());
278 public boolean checkVcsIsActive(final String vcsName) {
279 return myMappings.haveActiveVcs(vcsName);
282 public AbstractVcs[] getAllActiveVcss() {
283 return myMappings.getActiveVcses();
286 public boolean hasAnyMappings() {
287 return ! myMappings.isEmpty();
290 public void addMessageToConsoleWindow(final String message, final TextAttributes attributes) {
291 ApplicationManager.getApplication().invokeLater(new Runnable() {
292 public void run() {
293 // for default and disposed projects the ContentManager is not available.
294 if (myProject.isDisposed() || myProject.isDefault()) return;
295 final ContentManager contentManager = getContentManager();
296 if (contentManager == null) {
297 myPendingOutput.add(new Pair<String, TextAttributes>(message, attributes));
299 else {
300 getOrCreateConsoleContent(contentManager);
301 myEditorAdapter.appendString(message, attributes);
304 }, ModalityState.defaultModalityState());
307 private Content getOrCreateConsoleContent(final ContentManager contentManager) {
308 final String displayName = VcsBundle.message("vcs.console.toolwindow.display.name");
309 Content content = contentManager.findContent(displayName);
310 if (content == null) {
311 final EditorFactory editorFactory = EditorFactory.getInstance();
312 final Editor editor = editorFactory.createViewer(editorFactory.createDocument(""));
313 EditorSettings editorSettings = editor.getSettings();
314 editorSettings.setLineMarkerAreaShown(false);
315 editorSettings.setLineNumbersShown(false);
316 editorSettings.setFoldingOutlineShown(false);
318 myEditorAdapter = new EditorAdapter(editor, myProject);
319 content = ContentFactory.SERVICE.getInstance().createContent(new DisposableEditorPanel(editor), displayName, true);
320 contentManager.addContent(content);
322 for (Pair<String, TextAttributes> pair : myPendingOutput) {
323 myEditorAdapter.appendString(pair.first, pair.second);
325 myPendingOutput.clear();
327 return content;
330 @NotNull
331 public VcsShowSettingOption getOptions(VcsConfiguration.StandardOption option) {
332 return myOptionsAndConfirmations.getOptions(option);
335 public List<VcsShowOptionsSettingImpl> getAllOptions() {
336 return myOptionsAndConfirmations.getAllOptions();
339 @NotNull
340 public VcsShowSettingOption getStandardOption(@NotNull VcsConfiguration.StandardOption option, @NotNull AbstractVcs vcs) {
341 final VcsShowOptionsSettingImpl options = (VcsShowOptionsSettingImpl) getOptions(option);
342 options.addApplicableVcs(vcs);
343 return options;
346 @NotNull
347 public VcsShowSettingOption getOrCreateCustomOption(@NotNull String vcsActionName, @NotNull AbstractVcs vcs) {
348 return myOptionsAndConfirmations.getOrCreateCustomOption(vcsActionName, vcs);
351 public void showProjectOperationInfo(final UpdatedFiles updatedFiles, String displayActionName) {
352 showUpdateProjectInfo(updatedFiles, displayActionName, ActionInfo.STATUS);
355 public UpdateInfoTree showUpdateProjectInfo(UpdatedFiles updatedFiles, String displayActionName, ActionInfo actionInfo) {
356 synchronized (myDisposeLock) {
357 if (myIsDisposed) return null;
358 ContentManager contentManager = getContentManager();
359 if (contentManager == null) {
360 return null; // content manager is made null during dispose; flag is set later
362 final UpdateInfoTree updateInfoTree = new UpdateInfoTree(contentManager, myProject, updatedFiles, displayActionName, actionInfo);
363 Content content = ContentFactory.SERVICE.getInstance().createContent(updateInfoTree, VcsBundle.message(
364 "toolwindow.title.update.action.info", displayActionName), true);
365 Disposer.register(content, updateInfoTree);
366 ContentsUtil.addContent(contentManager, content, true);
367 ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.VCS).activate(null);
368 updateInfoTree.expandRootChildren();
369 return updateInfoTree;
373 public void cleanupMappings() {
374 myMappings.cleanupMappings();
377 public List<VcsDirectoryMapping> getDirectoryMappings() {
378 return myMappings.getDirectoryMappings();
381 public List<VcsDirectoryMapping> getDirectoryMappings(final AbstractVcs vcs) {
382 return myMappings.getDirectoryMappings(vcs.getName());
385 @Nullable
386 public VcsDirectoryMapping getDirectoryMappingFor(final FilePath path) {
387 return ApplicationManager.getApplication().runReadAction(new Computable<VcsDirectoryMapping>() {
388 @Nullable
389 public VcsDirectoryMapping compute() {
390 VirtualFile vFile = ChangesUtil.findValidParent(path);
391 if (vFile != null) {
392 return myMappings.getMappingFor(vFile);
394 return null;
399 public boolean hasExplicitMapping(final FilePath f) {
400 VirtualFile vFile = ChangesUtil.findValidParent(f);
401 if (vFile == null) return false;
402 return hasExplicitMapping(vFile);
405 public boolean hasExplicitMapping(final VirtualFile vFile) {
406 final VcsDirectoryMapping mapping = myMappings.getMappingFor(vFile);
407 return mapping != null && (! mapping.isDefaultMapping());
410 public void setDirectoryMapping(final String path, final String activeVcsName) {
411 if (myMappingsLoaded) return; // ignore per-module VCS settings if the mapping table was loaded from .ipr
412 myHaveLegacyVcsConfiguration = true;
413 myMappings.setMapping(FileUtil.toSystemIndependentName(path), activeVcsName);
416 public void setAutoDirectoryMapping(String path, String activeVcsName) {
417 myMappings.setMapping(path, activeVcsName);
420 public void removeDirectoryMapping(VcsDirectoryMapping mapping) {
421 myMappings.removeDirectoryMapping(mapping);
424 public void setDirectoryMappings(final List<VcsDirectoryMapping> items) {
425 myMappings.setDirectoryMappings(items);
428 public void iterateVcsRoot(final VirtualFile root, final Processor<FilePath> iterator) {
429 VcsRootIterator.iterateVcsRoot(myProject, root, iterator);
432 public void readExternal(Element element) throws InvalidDataException {
433 mySerialization.readExternalUtil(element, myOptionsAndConfirmations);
436 public void writeExternal(Element element) throws WriteExternalException {
437 mySerialization.writeExternalUtil(element, myOptionsAndConfirmations);
440 @NotNull
441 public VcsShowConfirmationOption getStandardConfirmation(@NotNull VcsConfiguration.StandardConfirmation option,
442 @NotNull AbstractVcs vcs) {
443 final VcsShowConfirmationOptionImpl result = getConfirmation(option);
444 result.addApplicableVcs(vcs);
445 return result;
448 public List<VcsShowConfirmationOptionImpl> getAllConfirmations() {
449 return myOptionsAndConfirmations.getAllConfirmations();
452 @NotNull
453 public VcsShowConfirmationOptionImpl getConfirmation(VcsConfiguration.StandardConfirmation option) {
454 return myOptionsAndConfirmations.getConfirmation(option);
457 public List<CheckinHandlerFactory> getRegisteredCheckinHandlerFactories() {
458 if (!myCheckinHandlerFactoriesLoaded) {
459 myCheckinHandlerFactoriesLoaded = true;
460 Collections.addAll(myRegisteredBeforeCheckinHandlers, Extensions.getExtensions(CheckinHandlerFactory.EP_NAME, myProject));
462 return Collections.unmodifiableList(myRegisteredBeforeCheckinHandlers);
465 public void registerCheckinHandlerFactory(CheckinHandlerFactory factory) {
466 myRegisteredBeforeCheckinHandlers.add(factory);
469 public void unregisterCheckinHandlerFactory(CheckinHandlerFactory handler) {
470 myRegisteredBeforeCheckinHandlers.remove(handler);
473 public void addVcsListener(VcsListener listener) {
474 myEventDispatcher.addListener(listener);
477 public void removeVcsListener(VcsListener listener) {
478 myEventDispatcher.removeListener(listener);
481 public void startBackgroundVcsOperation() {
482 myBackgroundOperationCounter++;
485 public void stopBackgroundVcsOperation() {
486 // in fact, the condition is "should not be called under ApplicationManager.invokeLater() and similiar"
487 assert ! ApplicationManager.getApplication().isDispatchThread();
488 LOG.assertTrue(myBackgroundOperationCounter > 0, "myBackgroundOperationCounter > 0");
489 myBackgroundOperationCounter--;
492 public boolean isBackgroundVcsOperationRunning() {
493 return myBackgroundOperationCounter > 0;
496 public VirtualFile[] getRootsUnderVcs(AbstractVcs vcs) {
497 return myMappingsToRoots.getRootsUnderVcs(vcs);
500 public VirtualFile[] getAllVersionedRoots() {
501 List<VirtualFile> vFiles = new ArrayList<VirtualFile>();
502 final AbstractVcs[] vcses = myMappings.getActiveVcses();
503 for (AbstractVcs vcs : vcses) {
504 Collections.addAll(vFiles, getRootsUnderVcs(vcs));
506 return VfsUtil.toVirtualFileArray(vFiles);
509 @NotNull
510 public VcsRoot[] getAllVcsRoots() {
511 List<VcsRoot> vcsRoots = new ArrayList<VcsRoot>();
512 final AbstractVcs[] vcses = myMappings.getActiveVcses();
513 for (AbstractVcs vcs : vcses) {
514 final VirtualFile[] roots = getRootsUnderVcs(vcs);
515 for(VirtualFile root: roots) {
516 vcsRoots.add(new VcsRoot(vcs, root));
519 return vcsRoots.toArray(new VcsRoot[vcsRoots.size()]);
522 public void updateActiveVcss() {
523 // not needed
526 public void notifyDirectoryMappingChanged() {
527 myEventDispatcher.getMulticaster().directoryMappingChanged();
530 public void readDirectoryMappings(final Element element) {
531 myMappings.clear();
533 final List<VcsDirectoryMapping> mappingsList = new ArrayList<VcsDirectoryMapping>();
534 final List list = element.getChildren(ELEMENT_MAPPING);
535 boolean haveNonEmptyMappings = false;
536 for(Object childObj: list) {
537 Element child = (Element) childObj;
538 final String vcs = child.getAttributeValue(ATTRIBUTE_VCS);
539 if (vcs != null && vcs.length() > 0) {
540 haveNonEmptyMappings = true;
542 VcsDirectoryMapping mapping = new VcsDirectoryMapping(child.getAttributeValue(ATTRIBUTE_DIRECTORY), vcs);
543 mappingsList.add(mapping);
545 Element rootSettingsElement = child.getChild(ELEMENT_ROOT_SETTINGS);
546 if (rootSettingsElement != null) {
547 String className = rootSettingsElement.getAttributeValue(ATTRIBUTE_CLASS);
548 AbstractVcs vcsInstance = findVcsByName(mapping.getVcs());
549 if (vcsInstance != null && className != null) {
550 final VcsRootSettings rootSettings = vcsInstance.createEmptyVcsRootSettings();
551 if (rootSettings != null) {
552 try {
553 rootSettings.readExternal(rootSettingsElement);
554 mapping.setRootSettings(rootSettings);
555 } catch (InvalidDataException e) {
556 LOG.error("Failed to load VCS root settings class "+ className + " for VCS " + vcsInstance.getClass().getName(), e);
562 boolean defaultProject = Boolean.TRUE.toString().equals(element.getAttributeValue(ATTRIBUTE_DEFAULT_PROJECT));
563 // run autodetection if there's no VCS in default project and
564 if (haveNonEmptyMappings || !defaultProject) {
565 myMappingsLoaded = true;
567 myMappings.setDirectoryMappings(mappingsList);
570 public void writeDirectoryMappings(final Element element) {
571 if (myProject.isDefault()) {
572 element.setAttribute(ATTRIBUTE_DEFAULT_PROJECT, Boolean.TRUE.toString());
574 for(VcsDirectoryMapping mapping: getDirectoryMappings()) {
575 Element child = new Element(ELEMENT_MAPPING);
576 child.setAttribute(ATTRIBUTE_DIRECTORY, mapping.getDirectory());
577 child.setAttribute(ATTRIBUTE_VCS, mapping.getVcs());
578 final VcsRootSettings rootSettings = mapping.getRootSettings();
579 if (rootSettings != null) {
580 Element rootSettingsElement = new Element(ELEMENT_ROOT_SETTINGS);
581 rootSettingsElement.setAttribute(ATTRIBUTE_CLASS, rootSettings.getClass().getName());
582 try {
583 rootSettings.writeExternal(rootSettingsElement);
584 child.addContent(rootSettingsElement);
586 catch (WriteExternalException e) {
587 // don't add element
590 element.addContent(child);
594 public boolean needAutodetectMappings() {
595 return !myHaveLegacyVcsConfiguration && !myMappingsLoaded;
598 @Nullable
599 public AbstractVcs findVersioningVcs(VirtualFile file) {
600 for(AbstractVcs vcs: getAllVcss()) {
601 if (vcs.isVersionedDirectory(file)) {
602 return vcs;
605 return null;
608 public CheckoutProvider.Listener getCompositeCheckoutListener() {
609 return new CompositeCheckoutListener(myProject);
612 public void fireDirectoryMappingsChanged() {
613 if (! myIsDisposed) {
614 myMappings.mappingsChanged();
618 public String haveDefaultMapping() {
619 return myMappings.haveDefaultMapping();
622 public BackgroundableActionEnabledHandler getBackgroundableActionHandler(final VcsBackgroundableActions action) {
623 ApplicationManager.getApplication().assertIsDispatchThread();
625 BackgroundableActionEnabledHandler result = myBackgroundableActionHandlerMap.get(action);
626 if (result == null) {
627 result = new BackgroundableActionEnabledHandler();
628 myBackgroundableActionHandlerMap.put(action, result);
630 return result;
633 public void addInitializationRequest(final VcsInitObject vcsInitObject, final Runnable runnable) {
634 ApplicationManager.getApplication().runReadAction(new Runnable() {
635 public void run() {
636 myInitialization.add(vcsInitObject, runnable);
641 public boolean isFileInContent(final VirtualFile vf) {
642 final ExcludedFileIndex excludedIndex = ExcludedFileIndex.getInstance(myProject);
643 return (vf != null) && (excludedIndex.isInContent(vf) || isFileInBaseDir(vf) || vf.equals(myProject.getBaseDir()) ||
644 hasExplicitMapping(vf) || isInDirectoryBasedRoot(vf)) && (! excludedIndex.isExcludedFile(vf));
647 private boolean isInDirectoryBasedRoot(final VirtualFile file) {
648 if (file == null) return false;
649 final StorageScheme storageScheme = ((ProjectEx) myProject).getStateStore().getStorageScheme();
650 if (StorageScheme.DIRECTORY_BASED.equals(storageScheme)) {
651 final VirtualFile ideaDir = myProject.getBaseDir().findChild(Project.DIRECTORY_STORE_FOLDER);
652 return (ideaDir != null && ideaDir.isValid() && ideaDir.isDirectory() && VfsUtil.isAncestor(ideaDir, file, false));
654 return false;
657 private boolean isFileInBaseDir(final VirtualFile file) {
658 VirtualFile parent = file.getParent();
659 return !file.isDirectory() && parent != null && parent.equals(myProject.getBaseDir());