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
;
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
) {
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
);
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()) {
153 public void projectOpened() {
154 final StartupManager manager
= StartupManager
.getInstance(myProject
);
155 manager
.registerPostStartupActivity(new DumbAwareRunnable() {
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
);
165 myContentManager
= ContentFactory
.SERVICE
.getInstance().createContentManager(true, myProject
);
171 public void projectClosed() {
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
) {
191 public AbstractVcs
getVcsFor(@NotNull VirtualFile file
) {
192 final String vcsName
= myMappings
.getVcsFor(file
);
193 if (vcsName
== null || vcsName
.length() == 0) {
196 return AllVcses
.getInstance(myProject
).getByName(vcsName
);
200 public AbstractVcs
getVcsFor(final FilePath file
) {
201 return ApplicationManager
.getApplication().runReadAction(new Computable
<AbstractVcs
>() {
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
);
208 return getVcsFor(vFile
);
216 public VirtualFile
getVcsRootFor(final VirtualFile file
) {
217 final VcsDirectoryMapping mapping
= myMappings
.getMappingFor(file
);
218 if (mapping
== null) {
221 final String directory
= mapping
.getDirectory();
222 if (directory
.length() == 0) {
223 return myDefaultVcsRootPolicy
.getVcsRootFor(file
);
225 return LocalFileSystem
.getInstance().findFileByPath(directory
);
229 public VirtualFile
getVcsRootFor(final FilePath file
) {
230 return ApplicationManager
.getApplication().runReadAction(new Computable
<VirtualFile
>() {
232 public VirtualFile
compute() {
233 VirtualFile vFile
= ChangesUtil
.findValidParent(file
);
235 return getVcsRootFor(vFile
);
242 private void dispose() {
243 // todo dispose lock is bad here..
244 synchronized (myDisposeLock
) {
245 if (myIsDisposed
) return;
247 myMappings
.disposeMe();
249 myContentManager
= null;
251 ToolWindowManager toolWindowManager
= ToolWindowManager
.getInstance(myProject
);
252 if (toolWindowManager
!= null && toolWindowManager
.getToolWindow(ToolWindowId
.VCS
) != null) {
253 toolWindowManager
.unregisterToolWindow(ToolWindowId
.VCS
);
262 public void unregisterVcs(AbstractVcs vcs
) {
263 if ((! ApplicationManager
.getApplication().isUnitTestMode()) && (myMappings
.haveActiveVcs(vcs
.getName()))) {
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() {
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
));
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();
334 public VcsShowSettingOption
getOptions(VcsConfiguration
.StandardOption option
) {
335 return myOptionsAndConfirmations
.getOptions(option
);
338 public List
<VcsShowOptionsSettingImpl
> getAllOptions() {
339 return myOptionsAndConfirmations
.getAllOptions();
343 public VcsShowSettingOption
getStandardOption(@NotNull VcsConfiguration
.StandardOption option
, @NotNull AbstractVcs vcs
) {
344 final VcsShowOptionsSettingImpl options
= (VcsShowOptionsSettingImpl
) getOptions(option
);
345 options
.addApplicableVcs(vcs
);
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());
389 public VcsDirectoryMapping
getDirectoryMappingFor(final FilePath path
) {
390 return ApplicationManager
.getApplication().runReadAction(new Computable
<VcsDirectoryMapping
>() {
392 public VcsDirectoryMapping
compute() {
393 VirtualFile vFile
= ChangesUtil
.findValidParent(path
);
395 return myMappings
.getMappingFor(vFile
);
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
);
444 public VcsShowConfirmationOption
getStandardConfirmation(@NotNull VcsConfiguration
.StandardConfirmation option
,
445 @NotNull AbstractVcs vcs
) {
446 final VcsShowConfirmationOptionImpl result
= getConfirmation(option
);
447 result
.addApplicableVcs(vcs
);
451 public List
<VcsShowConfirmationOptionImpl
> getAllConfirmations() {
452 return myOptionsAndConfirmations
.getAllConfirmations();
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
);
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() {
529 public void notifyDirectoryMappingChanged() {
530 myEventDispatcher
.getMulticaster().directoryMappingChanged();
533 public void readDirectoryMappings(final Element element
) {
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) {
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());
586 rootSettings
.writeExternal(rootSettingsElement
);
587 child
.addContent(rootSettingsElement
);
589 catch (WriteExternalException e
) {
593 element
.addContent(child
);
597 public boolean needAutodetectMappings() {
598 return !myHaveLegacyVcsConfiguration
&& !myMappingsLoaded
;
602 public AbstractVcs
findVersioningVcs(VirtualFile file
) {
603 for(AbstractVcs vcs
: getAllVcss()) {
604 if (vcs
.isVersionedDirectory(file
)) {
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
);
636 public void addInitializationRequest(final VcsInitObject vcsInitObject
, final Runnable runnable
) {
637 ApplicationManager
.getApplication().runReadAction(new Runnable() {
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));
660 private boolean isFileInBaseDir(final VirtualFile file
) {
661 VirtualFile parent
= file
.getParent();
662 return !file
.isDirectory() && parent
!= null && parent
.equals(myProject
.getBaseDir());