VCS: show history usages into backgroundable, markup for VCS providers, markup for...
[fedora-idea.git] / vcs-impl / src / com / intellij / openapi / vcs / impl / ProjectLevelVcsManagerImpl.java
blobb99b6e1af95c44383b0f5bee2f44baaf1787ebbd
1 /*
2 * Copyright (c) 2004 JetBrains s.r.o. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * -Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * -Redistribution in binary form must reproduct the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the distribution.
15 * Neither the name of JetBrains or IntelliJ IDEA
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * This software is provided "AS IS," without a warranty of any kind. ALL
20 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
21 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
22 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. JETBRAINS AND ITS LICENSORS SHALL NOT
23 * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
24 * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
25 * DERIVATIVES. IN NO EVENT WILL JETBRAINS OR ITS LICENSORS BE LIABLE FOR ANY LOST
26 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
27 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
28 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
29 * IF JETBRAINS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32 package com.intellij.openapi.vcs.impl;
34 import com.intellij.openapi.application.ApplicationManager;
35 import com.intellij.openapi.application.ModalityState;
36 import com.intellij.openapi.components.ProjectComponent;
37 import com.intellij.openapi.diagnostic.Logger;
38 import com.intellij.openapi.editor.DisposableEditorPanel;
39 import com.intellij.openapi.editor.Editor;
40 import com.intellij.openapi.editor.EditorFactory;
41 import com.intellij.openapi.editor.EditorSettings;
42 import com.intellij.openapi.editor.markup.TextAttributes;
43 import com.intellij.openapi.extensions.Extensions;
44 import com.intellij.openapi.progress.ProcessCanceledException;
45 import com.intellij.openapi.project.DumbAwareRunnable;
46 import com.intellij.openapi.project.Project;
47 import com.intellij.openapi.startup.StartupManager;
48 import com.intellij.openapi.util.*;
49 import com.intellij.openapi.util.io.FileUtil;
50 import com.intellij.openapi.vcs.*;
51 import com.intellij.openapi.vcs.changes.ChangesUtil;
52 import com.intellij.openapi.vcs.checkin.CheckinHandlerFactory;
53 import com.intellij.openapi.vcs.checkout.CompositeCheckoutListener;
54 import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
55 import com.intellij.openapi.vcs.impl.projectlevelman.*;
56 import com.intellij.openapi.vcs.update.ActionInfo;
57 import com.intellij.openapi.vcs.update.UpdateInfoTree;
58 import com.intellij.openapi.vcs.update.UpdatedFiles;
59 import com.intellij.openapi.vfs.LocalFileSystem;
60 import com.intellij.openapi.vfs.VirtualFile;
61 import com.intellij.openapi.wm.ToolWindow;
62 import com.intellij.openapi.wm.ToolWindowAnchor;
63 import com.intellij.openapi.wm.ToolWindowId;
64 import com.intellij.openapi.wm.ToolWindowManager;
65 import com.intellij.ui.content.Content;
66 import com.intellij.ui.content.ContentFactory;
67 import com.intellij.ui.content.ContentManager;
68 import com.intellij.util.ContentsUtil;
69 import com.intellij.util.EventDispatcher;
70 import com.intellij.util.Icons;
71 import com.intellij.util.Processor;
72 import com.intellij.util.containers.Convertor;
73 import com.intellij.util.ui.EditorAdapter;
74 import org.jdom.Element;
75 import org.jetbrains.annotations.NonNls;
76 import org.jetbrains.annotations.NotNull;
77 import org.jetbrains.annotations.Nullable;
79 import java.util.*;
81 public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx implements ProjectComponent, JDOMExternalizable {
82 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl");
84 private final ProjectLevelVcsManagerSerialization mySerialization;
85 private final OptionsAndConfirmations myOptionsAndConfirmations;
87 private NewMappings myMappings;
88 private final Project myProject;
89 private MappingsToRoots myMappingsToRoots;
91 private volatile boolean myIsDisposed = false;
92 private final Object myDisposeLock = new Object();
94 private ContentManager myContentManager;
95 private EditorAdapter myEditorAdapter;
97 @NonNls private static final String ELEMENT_MAPPING = "mapping";
98 @NonNls private static final String ATTRIBUTE_DIRECTORY = "directory";
99 @NonNls private static final String ATTRIBUTE_VCS = "vcs";
100 @NonNls private static final String ATTRIBUTE_DEFAULT_PROJECT = "defaultProject";
101 @NonNls private static final String ELEMENT_ROOT_SETTINGS = "rootSettings";
102 @NonNls private static final String ATTRIBUTE_CLASS = "class";
104 private final List<CheckinHandlerFactory> myRegisteredBeforeCheckinHandlers = new ArrayList<CheckinHandlerFactory>();
105 private final EventDispatcher<VcsListener> myEventDispatcher = EventDispatcher.create(VcsListener.class);
106 private boolean myMappingsLoaded = false;
107 private boolean myHaveLegacyVcsConfiguration = false;
108 private boolean myCheckinHandlerFactoriesLoaded = false;
109 private DefaultVcsRootPolicy myDefaultVcsRootPolicy;
111 private volatile int myBackgroundOperationCounter = 0;
113 private final Map<VcsBackgroundableActions, BackgroundableActionEnabledHandler> myBackgroundableActionHandlerMap;
115 private List<Pair<String, TextAttributes>> myPendingOutput = new ArrayList<Pair<String, TextAttributes>>();
117 public ProjectLevelVcsManagerImpl(Project project) {
118 myProject = project;
119 mySerialization = new ProjectLevelVcsManagerSerialization();
120 myOptionsAndConfirmations = new OptionsAndConfirmations();
122 myDefaultVcsRootPolicy = DefaultVcsRootPolicy.getInstance(project);
124 myMappings = new NewMappings(myProject, myEventDispatcher);
125 myMappingsToRoots = new MappingsToRoots(myMappings, myProject);
126 myBackgroundableActionHandlerMap = new HashMap<VcsBackgroundableActions, BackgroundableActionEnabledHandler>();
129 public void initComponent() {
130 myOptionsAndConfirmations.init(new Convertor<String, VcsShowConfirmationOption.Value>() {
131 public VcsShowConfirmationOption.Value convert(String o) {
132 return mySerialization.getInitOptionValue(o);
137 public void registerVcs(AbstractVcs vcs) {
138 AllVcses.getInstance(myProject).registerManually(vcs);
141 @Nullable
142 public AbstractVcs findVcsByName(String name) {
143 if (name == null) return null;
144 if (myProject.isDisposed()) return null;
145 return AllVcses.getInstance(myProject).getByName(name);
148 public AbstractVcs[] getAllVcss() {
149 return AllVcses.getInstance(myProject).getAll();
152 public boolean haveVcses() {
153 return ! AllVcses.getInstance(myProject).isEmpty();
156 public void disposeComponent() {
157 if (ApplicationManager.getApplication().isUnitTestMode()) {
158 dispose();
162 public void projectOpened() {
163 final StartupManager manager = StartupManager.getInstance(myProject);
164 manager.registerPostStartupActivity(new DumbAwareRunnable() {
165 public void run() {
166 ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
167 if (toolWindowManager != null) { // Can be null in tests
168 ToolWindow toolWindow =
169 toolWindowManager.registerToolWindow(ToolWindowId.VCS, true, ToolWindowAnchor.BOTTOM, myProject, true);
170 myContentManager = toolWindow.getContentManager();
171 toolWindow.setIcon(Icons.VCS_SMALL_TAB);
172 toolWindow.installWatcher(myContentManager);
173 } else {
174 myContentManager = ContentFactory.SERVICE.getInstance().createContentManager(true, myProject);
180 public void projectClosed() {
181 dispose();
184 @NotNull
185 public String getComponentName() {
186 return "ProjectLevelVcsManager";
189 public boolean checkAllFilesAreUnder(AbstractVcs abstractVcs, VirtualFile[] files) {
190 if (files == null) return false;
191 for (VirtualFile file : files) {
192 if (getVcsFor(file) != abstractVcs) {
193 return false;
196 return true;
199 @Nullable
200 public AbstractVcs getVcsFor(@NotNull VirtualFile file) {
201 final String vcsName = myMappings.getVcsFor(file);
202 if (vcsName == null || vcsName.length() == 0) {
203 return null;
205 return AllVcses.getInstance(myProject).getByName(vcsName);
208 @Nullable
209 public AbstractVcs getVcsFor(final FilePath file) {
210 return ApplicationManager.getApplication().runReadAction(new Computable<AbstractVcs>() {
211 @Nullable
212 public AbstractVcs compute() {
213 if (! myProject.isInitialized()) return null;
214 if (myProject.isDisposed()) throw new ProcessCanceledException();
215 VirtualFile vFile = ChangesUtil.findValidParent(file);
216 if (vFile != null) {
217 return getVcsFor(vFile);
219 return null;
224 @Nullable
225 public VirtualFile getVcsRootFor(final VirtualFile file) {
226 final VcsDirectoryMapping mapping = myMappings.getMappingFor(file);
227 if (mapping == null) {
228 return null;
230 final String directory = mapping.getDirectory();
231 if (directory.length() == 0) {
232 return myDefaultVcsRootPolicy.getVcsRootFor(file);
234 return LocalFileSystem.getInstance().findFileByPath(directory);
237 @Nullable
238 public VirtualFile getVcsRootFor(final FilePath file) {
239 return ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile>() {
240 @Nullable
241 public VirtualFile compute() {
242 VirtualFile vFile = ChangesUtil.findValidParent(file);
243 if (vFile != null) {
244 return getVcsRootFor(vFile);
246 return null;
251 private void dispose() {
252 // todo dispose lock is bad here..
253 synchronized (myDisposeLock) {
254 if (myIsDisposed) return;
256 myMappings.disposeMe();
257 try {
258 myContentManager = null;
260 ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
261 if (toolWindowManager != null && toolWindowManager.getToolWindow(ToolWindowId.VCS) != null) {
262 toolWindowManager.unregisterToolWindow(ToolWindowId.VCS);
265 finally {
266 myIsDisposed = true;
271 public void unregisterVcs(AbstractVcs vcs) {
272 if ((! ApplicationManager.getApplication().isUnitTestMode()) && (myMappings.haveActiveVcs(vcs.getName()))) {
273 // unlikely
274 LOG.warn("Active vcs '" + vcs.getName() + "' is being unregistered. Remove from mappings first.");
276 myMappings.beingUnregistered(vcs.getName());
277 AllVcses.getInstance(myProject).unregisterManually(vcs);
280 public ContentManager getContentManager() {
281 return myContentManager;
284 public boolean checkVcsIsActive(AbstractVcs vcs) {
285 return checkVcsIsActive(vcs.getName());
288 public boolean checkVcsIsActive(final String vcsName) {
289 return myMappings.haveActiveVcs(vcsName);
292 public AbstractVcs[] getAllActiveVcss() {
293 return myMappings.getActiveVcses();
296 public boolean hasAnyMappings() {
297 return ! myMappings.isEmpty();
300 public void addMessageToConsoleWindow(final String message, final TextAttributes attributes) {
301 ApplicationManager.getApplication().invokeLater(new Runnable() {
302 public void run() {
303 // for default and disposed projects the ContentManager is not available.
304 if (myProject.isDisposed() || myProject.isDefault()) return;
305 final ContentManager contentManager = getContentManager();
306 if (contentManager == null) {
307 myPendingOutput.add(new Pair<String, TextAttributes>(message, attributes));
309 else {
310 getOrCreateConsoleContent(contentManager);
311 myEditorAdapter.appendString(message, attributes);
314 }, ModalityState.defaultModalityState());
317 private Content getOrCreateConsoleContent(final ContentManager contentManager) {
318 final String displayName = VcsBundle.message("vcs.console.toolwindow.display.name");
319 Content content = contentManager.findContent(displayName);
320 if (content == null) {
321 final EditorFactory editorFactory = EditorFactory.getInstance();
322 final Editor editor = editorFactory.createViewer(editorFactory.createDocument(""));
323 EditorSettings editorSettings = editor.getSettings();
324 editorSettings.setLineMarkerAreaShown(false);
325 editorSettings.setLineNumbersShown(false);
326 editorSettings.setFoldingOutlineShown(false);
328 myEditorAdapter = new EditorAdapter(editor, myProject);
329 content = ContentFactory.SERVICE.getInstance().createContent(new DisposableEditorPanel(editor), displayName, true);
330 contentManager.addContent(content);
332 for (Pair<String, TextAttributes> pair : myPendingOutput) {
333 myEditorAdapter.appendString(pair.first, pair.second);
335 myPendingOutput.clear();
337 return content;
340 @NotNull
341 public VcsShowSettingOption getOptions(VcsConfiguration.StandardOption option) {
342 return myOptionsAndConfirmations.getOptions(option);
345 public List<VcsShowOptionsSettingImpl> getAllOptions() {
346 return myOptionsAndConfirmations.getAllOptions();
349 @NotNull
350 public VcsShowSettingOption getStandardOption(@NotNull VcsConfiguration.StandardOption option, @NotNull AbstractVcs vcs) {
351 final VcsShowOptionsSettingImpl options = (VcsShowOptionsSettingImpl) getOptions(option);
352 options.addApplicableVcs(vcs);
353 return options;
356 @NotNull
357 public VcsShowSettingOption getOrCreateCustomOption(@NotNull String vcsActionName, @NotNull AbstractVcs vcs) {
358 return myOptionsAndConfirmations.getOrCreateCustomOption(vcsActionName, vcs);
361 public void showProjectOperationInfo(final UpdatedFiles updatedFiles, String displayActionName) {
362 showUpdateProjectInfo(updatedFiles, displayActionName, ActionInfo.STATUS);
365 public UpdateInfoTree showUpdateProjectInfo(UpdatedFiles updatedFiles, String displayActionName, ActionInfo actionInfo) {
366 synchronized (myDisposeLock) {
367 if (myIsDisposed) return null;
368 ContentManager contentManager = getContentManager();
369 if (contentManager == null) {
370 return null; // content manager is made null during dispose; flag is set later
372 final UpdateInfoTree updateInfoTree = new UpdateInfoTree(contentManager, myProject, updatedFiles, displayActionName, actionInfo);
373 Content content = ContentFactory.SERVICE.getInstance().createContent(updateInfoTree, VcsBundle.message(
374 "toolwindow.title.update.action.info", displayActionName), true);
375 Disposer.register(content, updateInfoTree);
376 ContentsUtil.addContent(contentManager, content, true);
377 ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.VCS).activate(null);
378 updateInfoTree.expandRootChildren();
379 return updateInfoTree;
383 public void cleanupMappings() {
384 myMappings.cleanupMappings();
387 public List<VcsDirectoryMapping> getDirectoryMappings() {
388 return myMappings.getDirectoryMappings();
391 public List<VcsDirectoryMapping> getDirectoryMappings(final AbstractVcs vcs) {
392 return myMappings.getDirectoryMappings(vcs.getName());
395 @Nullable
396 public VcsDirectoryMapping getDirectoryMappingFor(final FilePath path) {
397 return ApplicationManager.getApplication().runReadAction(new Computable<VcsDirectoryMapping>() {
398 @Nullable
399 public VcsDirectoryMapping compute() {
400 VirtualFile vFile = ChangesUtil.findValidParent(path);
401 if (vFile != null) {
402 return myMappings.getMappingFor(vFile);
404 return null;
409 public boolean hasExplicitMapping(final FilePath f) {
410 VirtualFile vFile = ChangesUtil.findValidParent(f);
411 if (vFile == null) return false;
412 return hasExplicitMapping(vFile);
415 public boolean hasExplicitMapping(final VirtualFile vFile) {
416 final VcsDirectoryMapping mapping = myMappings.getMappingFor(vFile);
417 return mapping != null && (! mapping.isDefaultMapping());
420 public void setDirectoryMapping(final String path, final String activeVcsName) {
421 if (myMappingsLoaded) return; // ignore per-module VCS settings if the mapping table was loaded from .ipr
422 myHaveLegacyVcsConfiguration = true;
423 myMappings.setMapping(FileUtil.toSystemIndependentName(path), activeVcsName);
426 public void setAutoDirectoryMapping(String path, String activeVcsName) {
427 myMappings.setMapping(path, activeVcsName);
430 public void removeDirectoryMapping(VcsDirectoryMapping mapping) {
431 myMappings.removeDirectoryMapping(mapping);
434 public void setDirectoryMappings(final List<VcsDirectoryMapping> items) {
435 myMappings.setDirectoryMappings(items);
438 public void iterateVcsRoot(final VirtualFile root, final Processor<FilePath> iterator) {
439 VcsRootIterator.iterateVcsRoot(myProject, root, iterator);
442 public void readExternal(Element element) throws InvalidDataException {
443 mySerialization.readExternalUtil(element, myOptionsAndConfirmations);
446 public void writeExternal(Element element) throws WriteExternalException {
447 mySerialization.writeExternalUtil(element, myOptionsAndConfirmations);
450 @NotNull
451 public VcsShowConfirmationOption getStandardConfirmation(@NotNull VcsConfiguration.StandardConfirmation option,
452 @NotNull AbstractVcs vcs) {
453 final VcsShowConfirmationOptionImpl result = getConfirmation(option);
454 result.addApplicableVcs(vcs);
455 return result;
458 public List<VcsShowConfirmationOptionImpl> getAllConfirmations() {
459 return myOptionsAndConfirmations.getAllConfirmations();
462 @NotNull
463 public VcsShowConfirmationOptionImpl getConfirmation(VcsConfiguration.StandardConfirmation option) {
464 return myOptionsAndConfirmations.getConfirmation(option);
467 public List<CheckinHandlerFactory> getRegisteredCheckinHandlerFactories() {
468 if (!myCheckinHandlerFactoriesLoaded) {
469 myCheckinHandlerFactoriesLoaded = true;
470 Collections.addAll(myRegisteredBeforeCheckinHandlers, Extensions.getExtensions(CheckinHandlerFactory.EP_NAME, myProject));
472 return Collections.unmodifiableList(myRegisteredBeforeCheckinHandlers);
475 public void registerCheckinHandlerFactory(CheckinHandlerFactory factory) {
476 myRegisteredBeforeCheckinHandlers.add(factory);
479 public void unregisterCheckinHandlerFactory(CheckinHandlerFactory handler) {
480 myRegisteredBeforeCheckinHandlers.remove(handler);
483 public void addVcsListener(VcsListener listener) {
484 myEventDispatcher.addListener(listener);
487 public void removeVcsListener(VcsListener listener) {
488 myEventDispatcher.removeListener(listener);
491 public void startBackgroundVcsOperation() {
492 myBackgroundOperationCounter++;
495 public void stopBackgroundVcsOperation() {
496 // in fact, the condition is "should not be called under ApplicationManager.invokeLater() and similiar"
497 assert ! ApplicationManager.getApplication().isDispatchThread();
498 LOG.assertTrue(myBackgroundOperationCounter > 0, "myBackgroundOperationCounter > 0");
499 myBackgroundOperationCounter--;
502 public boolean isBackgroundVcsOperationRunning() {
503 return myBackgroundOperationCounter > 0;
506 public VirtualFile[] getRootsUnderVcs(AbstractVcs vcs) {
507 return myMappingsToRoots.getRootsUnderVcs(vcs);
510 public VirtualFile[] getAllVersionedRoots() {
511 List<VirtualFile> vFiles = new ArrayList<VirtualFile>();
512 final AbstractVcs[] vcses = myMappings.getActiveVcses();
513 for (AbstractVcs vcs : vcses) {
514 Collections.addAll(vFiles, getRootsUnderVcs(vcs));
516 return vFiles.toArray(new VirtualFile[vFiles.size()]);
519 @NotNull
520 public VcsRoot[] getAllVcsRoots() {
521 List<VcsRoot> vcsRoots = new ArrayList<VcsRoot>();
522 final AbstractVcs[] vcses = myMappings.getActiveVcses();
523 for (AbstractVcs vcs : vcses) {
524 final VirtualFile[] roots = getRootsUnderVcs(vcs);
525 for(VirtualFile root: roots) {
526 vcsRoots.add(new VcsRoot(vcs, root));
529 return vcsRoots.toArray(new VcsRoot[vcsRoots.size()]);
532 public void updateActiveVcss() {
533 // not needed
536 public void notifyDirectoryMappingChanged() {
537 myEventDispatcher.getMulticaster().directoryMappingChanged();
540 public void readDirectoryMappings(final Element element) {
541 myMappings.clear();
543 final List<VcsDirectoryMapping> mappingsList = new ArrayList<VcsDirectoryMapping>();
544 final List list = element.getChildren(ELEMENT_MAPPING);
545 boolean haveNonEmptyMappings = false;
546 for(Object childObj: list) {
547 Element child = (Element) childObj;
548 final String vcs = child.getAttributeValue(ATTRIBUTE_VCS);
549 if (vcs != null && vcs.length() > 0) {
550 haveNonEmptyMappings = true;
552 VcsDirectoryMapping mapping = new VcsDirectoryMapping(child.getAttributeValue(ATTRIBUTE_DIRECTORY), vcs);
553 mappingsList.add(mapping);
555 Element rootSettingsElement = child.getChild(ELEMENT_ROOT_SETTINGS);
556 if (rootSettingsElement != null) {
557 String className = rootSettingsElement.getAttributeValue(ATTRIBUTE_CLASS);
558 AbstractVcs vcsInstance = findVcsByName(mapping.getVcs());
559 if (vcsInstance != null && className != null) {
560 try {
561 final Class<?> aClass = vcsInstance.getClass().getClassLoader().loadClass(className);
562 final VcsRootSettings instance = (VcsRootSettings) aClass.newInstance();
563 instance.readExternal(rootSettingsElement);
564 mapping.setRootSettings(instance);
566 catch (Exception e) {
567 LOG.error("Failed to load VCS root settings class "+ className + " for VCS " + vcsInstance.getClass().getName(), e);
572 boolean defaultProject = Boolean.TRUE.toString().equals(element.getAttributeValue(ATTRIBUTE_DEFAULT_PROJECT));
573 // run autodetection if there's no VCS in default project and
574 if (haveNonEmptyMappings || !defaultProject) {
575 myMappingsLoaded = true;
577 StartupManager.getInstance(myProject).registerStartupActivity(new Runnable() {
578 public void run() {
579 myMappings.setDirectoryMappings(mappingsList);
584 public void writeDirectoryMappings(final Element element) {
585 if (myProject.isDefault()) {
586 element.setAttribute(ATTRIBUTE_DEFAULT_PROJECT, Boolean.TRUE.toString());
588 for(VcsDirectoryMapping mapping: getDirectoryMappings()) {
589 Element child = new Element(ELEMENT_MAPPING);
590 child.setAttribute(ATTRIBUTE_DIRECTORY, mapping.getDirectory());
591 child.setAttribute(ATTRIBUTE_VCS, mapping.getVcs());
592 final VcsRootSettings rootSettings = mapping.getRootSettings();
593 if (rootSettings != null) {
594 Element rootSettingsElement = new Element(ELEMENT_ROOT_SETTINGS);
595 rootSettingsElement.setAttribute(ATTRIBUTE_CLASS, rootSettings.getClass().getName());
596 try {
597 rootSettings.writeExternal(rootSettingsElement);
598 child.addContent(rootSettingsElement);
600 catch (WriteExternalException e) {
601 // don't add element
604 element.addContent(child);
608 public boolean needAutodetectMappings() {
609 return !myHaveLegacyVcsConfiguration && !myMappingsLoaded;
612 @Nullable
613 public AbstractVcs findVersioningVcs(VirtualFile file) {
614 for(AbstractVcs vcs: getAllVcss()) {
615 if (vcs.isVersionedDirectory(file)) {
616 return vcs;
619 return null;
622 public CheckoutProvider.Listener getCompositeCheckoutListener() {
623 return new CompositeCheckoutListener(myProject);
626 public void fireDirectoryMappingsChanged() {
627 if (! myIsDisposed) {
628 myMappings.mappingsChanged();
632 public String haveDefaultMapping() {
633 return myMappings.haveDefaultMapping();
636 public BackgroundableActionEnabledHandler getBackgroundableActionHandler(final VcsBackgroundableActions action) {
637 ApplicationManager.getApplication().assertIsDispatchThread();
639 BackgroundableActionEnabledHandler result = myBackgroundableActionHandlerMap.get(action);
640 if (result == null) {
641 result = new BackgroundableActionEnabledHandler();
642 myBackgroundableActionHandlerMap.put(action, result);
644 return result;