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
;
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
) {
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
);
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()) {
152 public void projectOpened() {
153 final StartupManager manager
= StartupManager
.getInstance(myProject
);
154 manager
.registerPostStartupActivity(new DumbAwareRunnable() {
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
);
164 myContentManager
= ContentFactory
.SERVICE
.getInstance().createContentManager(true, myProject
);
170 public void projectClosed() {
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
) {
190 public AbstractVcs
getVcsFor(@NotNull VirtualFile file
) {
191 final String vcsName
= myMappings
.getVcsFor(file
);
192 if (vcsName
== null || vcsName
.length() == 0) {
195 return AllVcses
.getInstance(myProject
).getByName(vcsName
);
199 public AbstractVcs
getVcsFor(final FilePath file
) {
200 return ApplicationManager
.getApplication().runReadAction(new Computable
<AbstractVcs
>() {
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
);
207 return getVcsFor(vFile
);
215 public VirtualFile
getVcsRootFor(final VirtualFile file
) {
216 final VcsDirectoryMapping mapping
= myMappings
.getMappingFor(file
);
217 if (mapping
== null) {
220 final String directory
= mapping
.getDirectory();
221 if (directory
.length() == 0) {
222 return myDefaultVcsRootPolicy
.getVcsRootFor(file
);
224 return LocalFileSystem
.getInstance().findFileByPath(directory
);
228 public VirtualFile
getVcsRootFor(final FilePath file
) {
229 return ApplicationManager
.getApplication().runReadAction(new Computable
<VirtualFile
>() {
231 public VirtualFile
compute() {
232 VirtualFile vFile
= ChangesUtil
.findValidParent(file
);
234 return getVcsRootFor(vFile
);
241 private void dispose() {
242 // todo dispose lock is bad here..
243 synchronized (myDisposeLock
) {
244 if (myIsDisposed
) return;
246 myMappings
.disposeMe();
248 myContentManager
= null;
250 ToolWindowManager toolWindowManager
= ToolWindowManager
.getInstance(myProject
);
251 if (toolWindowManager
!= null && toolWindowManager
.getToolWindow(ToolWindowId
.VCS
) != null) {
252 toolWindowManager
.unregisterToolWindow(ToolWindowId
.VCS
);
261 public void unregisterVcs(AbstractVcs vcs
) {
262 if ((! ApplicationManager
.getApplication().isUnitTestMode()) && (myMappings
.haveActiveVcs(vcs
.getName()))) {
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() {
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
));
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();
331 public VcsShowSettingOption
getOptions(VcsConfiguration
.StandardOption option
) {
332 return myOptionsAndConfirmations
.getOptions(option
);
335 public List
<VcsShowOptionsSettingImpl
> getAllOptions() {
336 return myOptionsAndConfirmations
.getAllOptions();
340 public VcsShowSettingOption
getStandardOption(@NotNull VcsConfiguration
.StandardOption option
, @NotNull AbstractVcs vcs
) {
341 final VcsShowOptionsSettingImpl options
= (VcsShowOptionsSettingImpl
) getOptions(option
);
342 options
.addApplicableVcs(vcs
);
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());
386 public VcsDirectoryMapping
getDirectoryMappingFor(final FilePath path
) {
387 return ApplicationManager
.getApplication().runReadAction(new Computable
<VcsDirectoryMapping
>() {
389 public VcsDirectoryMapping
compute() {
390 VirtualFile vFile
= ChangesUtil
.findValidParent(path
);
392 return myMappings
.getMappingFor(vFile
);
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
);
441 public VcsShowConfirmationOption
getStandardConfirmation(@NotNull VcsConfiguration
.StandardConfirmation option
,
442 @NotNull AbstractVcs vcs
) {
443 final VcsShowConfirmationOptionImpl result
= getConfirmation(option
);
444 result
.addApplicableVcs(vcs
);
448 public List
<VcsShowConfirmationOptionImpl
> getAllConfirmations() {
449 return myOptionsAndConfirmations
.getAllConfirmations();
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
);
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() {
526 public void notifyDirectoryMappingChanged() {
527 myEventDispatcher
.getMulticaster().directoryMappingChanged();
530 public void readDirectoryMappings(final Element element
) {
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) {
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());
583 rootSettings
.writeExternal(rootSettingsElement
);
584 child
.addContent(rootSettingsElement
);
586 catch (WriteExternalException e
) {
590 element
.addContent(child
);
594 public boolean needAutodetectMappings() {
595 return !myHaveLegacyVcsConfiguration
&& !myMappingsLoaded
;
599 public AbstractVcs
findVersioningVcs(VirtualFile file
) {
600 for(AbstractVcs vcs
: getAllVcss()) {
601 if (vcs
.isVersionedDirectory(file
)) {
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
);
633 public void addInitializationRequest(final VcsInitObject vcsInitObject
, final Runnable runnable
) {
634 ApplicationManager
.getApplication().runReadAction(new Runnable() {
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));
657 private boolean isFileInBaseDir(final VirtualFile file
) {
658 VirtualFile parent
= file
.getParent();
659 return !file
.isDirectory() && parent
!= null && parent
.equals(myProject
.getBaseDir());