From 61fc90b0cd3d4a0d9168781dec2e1887682ae56e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 13 Mar 2012 12:43:03 +0400 Subject: [PATCH 1/5] IDEA-82632 Git: scan for roots only after VCS mappings are ready. Move scanning of roots to a separate class: GitRootScanner. Perform only 1 scan at a time (and reject others while scanning - not-scanning is not critical). Scan only when project is initialized and VCS mappings are ready (i.e. the first VcsListener event is fired). --- .../git4idea/repo/GitRepositoryManager.java | 56 +------ .../src/git4idea/roots/GitRootScanner.java | 140 ++++++++++++++++++ 2 files changed, 144 insertions(+), 52 deletions(-) create mode 100644 plugins/git4idea/src/git4idea/roots/GitRootScanner.java diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java index be048ed1ef53..54aaa3010075 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java @@ -15,30 +15,20 @@ */ package git4idea.repo; -import com.intellij.ProjectTopics; import com.intellij.openapi.Disposable; import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ModuleRootEvent; -import com.intellij.openapi.roots.ModuleRootListener; -import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileManager; -import com.intellij.openapi.vfs.newvfs.BulkFileListener; -import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.ArrayUtil; -import com.intellij.util.Consumer; -import com.intellij.util.concurrency.QueueProcessor; -import com.intellij.util.messages.MessageBus; import git4idea.GitUtil; import git4idea.PlatformFacade; -import git4idea.roots.GitRootProblemNotifier; +import git4idea.roots.GitRootScanner; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,16 +50,7 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme @NotNull private final Set myListeners = new HashSet(); @NotNull private final ReentrantReadWriteLock REPO_LOCK = new ReentrantReadWriteLock(); - - @NotNull private final Object ROOT_SCAN_STUB_OBJECT = new Object(); - @NotNull private final QueueProcessor myRootScanQueue = new QueueProcessor(new Consumer() { - @Override - public void consume(Object o) { - if (!myProject.isDisposed()) { - GitRootProblemNotifier.getInstance(myProject).rescanAndNotifyIfNeeded(); - } - } - }); + private GitRootScanner myRootScanner; @Nullable public static GitRepositoryManager getInstance(@NotNull Project project) { @@ -85,16 +66,13 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme @Override public void initComponent() { Disposer.register(myProject, this); - StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() { + myRootScanner = new GitRootScanner(myProject, new DumbAwareRunnable() { @Override public void run() { - final MessageBus messageBus = myProject.getMessageBus(); - final MyRepositoryCreationDeletionListener rootChangeListener = new MyRepositoryCreationDeletionListener(); - messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, rootChangeListener); - messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, rootChangeListener); updateRepositoriesCollection(); } }); + Disposer.register(this, myRootScanner); } @Override @@ -211,8 +189,6 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme finally { REPO_LOCK.writeLock().unlock(); } - - myRootScanQueue.add(ROOT_SCAN_STUB_OBJECT); } private static boolean gitRootOK(@NotNull VirtualFile root) { @@ -233,28 +209,4 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme return "GitRepositoryManager{myRepositories: " + myRepositories + '}'; } - private class MyRepositoryCreationDeletionListener implements BulkFileListener, ModuleRootListener { - @Override - public void before(@NotNull List events) { - } - - @Override - public void after(@NotNull List events) { - for (VFileEvent event : events) { - VirtualFile file = event.getFile(); - if (file != null && file.getName().equalsIgnoreCase(".git") && file.isDirectory()) { - updateRepositoriesCollection(); - } - } - } - - @Override - public void beforeRootsChange(ModuleRootEvent event) { - } - - @Override - public void rootsChanged(ModuleRootEvent event) { - updateRepositoriesCollection(); - } - } } diff --git a/plugins/git4idea/src/git4idea/roots/GitRootScanner.java b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java new file mode 100644 index 000000000000..047a62cc1c8d --- /dev/null +++ b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java @@ -0,0 +1,140 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea.roots; + +import com.intellij.ProjectTopics; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.DumbAwareRunnable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootEvent; +import com.intellij.openapi.roots.ModuleRootListener; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.VcsListener; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.util.messages.MessageBus; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.List; + +/** + * @author Kirill Likhodedov + */ +public class GitRootScanner implements BulkFileListener, ModuleRootListener, Disposable, VcsListener { + + @NotNull private final Runnable myExecuteAfterScan; + @NotNull private final GitRootProblemNotifier myRootProblemNotifier; + + private volatile boolean myProjectIsInitialized; + private volatile boolean myMappingsAreReady; + private volatile boolean myScanning; + @NotNull private final Object SCAN_LOCK = new Object(); + + public GitRootScanner(@NotNull Project project, @NotNull Runnable executeAfterScan) { + myExecuteAfterScan = executeAfterScan; + + StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() { + @Override + public void run() { + myProjectIsInitialized = true; + } + }); + + final MessageBus messageBus = project.getMessageBus(); + messageBus.connect().subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, this); + messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, this); + messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, this); + + myRootProblemNotifier = GitRootProblemNotifier.getInstance(project); + } + + @Override + public void dispose() { + } + + @Override + public void before(@NotNull List events) { + } + + @Override + public void after(@NotNull List events) { + for (VFileEvent event : events) { + VirtualFile file = event.getFile(); + if (file != null && file.getName().equalsIgnoreCase(".git") && file.isDirectory()) { + scanIfReady(); + } + } + } + + @Override + public void beforeRootsChange(ModuleRootEvent event) { + } + + @Override + public void rootsChanged(ModuleRootEvent event) { + scanIfReady(); + } + + @Override + public void directoryMappingChanged() { + myMappingsAreReady = true; + } + + private void scanIfReady() { + if (readyToScan()) { + scan(); + } + } + + private void scan() { + if (myScanning) { + return; + } + + if (SwingUtilities.isEventDispatchThread()) { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + public void run() { + scanWithLock(); + } + }); + } + else { + scanWithLock(); + } + } + + private void scanWithLock() { + synchronized (SCAN_LOCK) { + if (myScanning) { + return; + } + myScanning = true; + myRootProblemNotifier.rescanAndNotifyIfNeeded(); + myExecuteAfterScan.run(); + myScanning = false; + } + } + + private boolean readyToScan() { + return myMappingsAreReady && myProjectIsInitialized; + } + +} From 5b645fb2a98bead52f8dd77bd7652cd5ef8098db Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 13 Mar 2012 13:12:25 +0400 Subject: [PATCH 2/5] GitRepositoryManager - make it an interface Move implementation to GitRepositoryManagerImpl. Headless implementation - GitTestRepositoryManager (a complete stub for now, since it is not used in tests). Remove GRM#getInstance() and use GitUtil.getRepositoryManager everywhere. --- plugins/git4idea/src/META-INF/plugin.xml | 4 +- plugins/git4idea/src/git4idea/GitUtil.java | 12 +- .../actions/GitCompareWithBranchAction.java | 16 +- .../src/git4idea/actions/GitMerge.java | 6 +- .../src/git4idea/actions/GitPull.java | 11 +- .../git4idea/actions/GitRebaseActionBase.java | 11 +- .../git4idea/actions/GitRepositoryAction.java | 11 +- .../src/git4idea/actions/GitResetHead.java | 6 +- .../actions/GitResolveConflictsAction.java | 4 +- .../src/git4idea/actions/GitRevert.java | 10 +- .../checkin/GitCheckinEnvironment.java | 13 +- .../checkin/GitCheckinHandlerFactory.java | 6 +- .../git4idea/commands/GitCompoundResult.java | 4 +- .../src/git4idea/config/GitVcsPanel.java | 3 +- .../history/browser/LowLevelAccessImpl.java | 5 +- .../git4idea/history/wholeTree/GitLogUI.java | 7 +- .../src/git4idea/merge/GitPullDialog.java | 4 +- .../src/git4idea/push/GitPushDialog.java | 3 +- .../git4idea/src/git4idea/push/GitPusher.java | 2 +- .../git4idea/repo/GitRepositoryManager.java | 166 +-------------- .../repo/GitRepositoryManagerImpl.java | 192 ++++++++++++++++++ .../repo/GitUntrackedFilesHolder.java | 3 +- .../rollback/GitRollbackEnvironment.java | 7 +- .../status/GitNewChangesCollector.java | 6 +- .../src/git4idea/ui/GitTagDialog.java | 10 +- .../git4idea/ui/branch/GitBranchPopup.java | 7 +- .../git4idea/ui/branch/GitBranchUiUtil.java | 6 +- .../git4idea/ui/branch/GitBranchWidget.java | 6 +- .../git4idea/ui/branch/GitBranchesAction.java | 7 +- .../ui/branch/GitCompareBranchesDialog.java | 4 +- .../git4idea/update/GitComplexProcess.java | 3 +- .../src/git4idea/update/GitFetcher.java | 3 +- .../src/git4idea/util/GitFileUtils.java | 14 +- .../git4idea/src/git4idea/util/GitUIUtil.java | 6 +- .../test/GitTestRepositoryManager.java | 67 ++++++ .../github/GithubCheckoutListener.java | 7 +- .../github/GithubOpenInBrowserAction.java | 13 +- .../plugins/github/GithubRebaseAction.java | 19 +- 38 files changed, 453 insertions(+), 231 deletions(-) create mode 100644 plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java create mode 100644 plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml index e0c65226536f..fe62f7c555a4 100644 --- a/plugins/git4idea/src/META-INF/plugin.xml +++ b/plugins/git4idea/src/META-INF/plugin.xml @@ -74,7 +74,9 @@ - git4idea.repo.GitRepositoryManager + git4idea.repo.GitRepositoryManager + git4idea.repo.GitRepositoryManagerImpl + git4idea.test.GitTestRepositoryManager diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java index 841ca77aedfc..adcc40604db6 100644 --- a/plugins/git4idea/src/git4idea/GitUtil.java +++ b/plugins/git4idea/src/git4idea/GitUtil.java @@ -15,6 +15,7 @@ */ package git4idea; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; @@ -561,7 +562,11 @@ public class GitUtil { } public static boolean justOneGitRepository(Project project) { - return !GitRepositoryManager.getInstance(project).moreThanOneRoot(); + GitRepositoryManager manager = getRepositoryManager(project); + if (manager == null) { + return true; + } + return !manager.moreThanOneRoot(); } public static List sortRepositories(@NotNull Collection repositories) { @@ -708,4 +713,9 @@ public class GitUtil { } return affectedChanges; } + + @Nullable + public static GitRepositoryManager getRepositoryManager(@NotNull Project project) { + return ServiceManager.getService(project, GitRepositoryManager.class); + } } diff --git a/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java b/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java index 6182aedb53e2..45c32dbddf20 100644 --- a/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java @@ -37,6 +37,7 @@ import com.intellij.ui.components.JBList; import git4idea.GitBranch; import git4idea.GitFileRevision; import git4idea.GitRevisionNumber; +import git4idea.GitUtil; import git4idea.history.GitHistoryUtils; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; @@ -64,7 +65,11 @@ public class GitCompareWithBranchAction extends DumbAwareAction { final VirtualFile file = getAffectedFile(event); - GitRepository repository = GitRepositoryManager.getInstance(project).getRepositoryForFile(file); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + return; + } + GitRepository repository = manager.getRepositoryForFile(file); assert repository != null; final String head = repository.getCurrentRevision(); @@ -126,7 +131,14 @@ public class GitCompareWithBranchAction extends DumbAwareAction { return; } - GitRepository repository = GitRepositoryManager.getInstance(project).getRepositoryForFile(vFiles[0]); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + presentation.setEnabled(false); + presentation.setVisible(true); + return; + } + + GitRepository repository = manager.getRepositoryForFile(vFiles[0]); if (repository == null || repository.isFresh() || noBranchesToCompare(repository)) { presentation.setEnabled(false); presentation.setVisible(true); diff --git a/plugins/git4idea/src/git4idea/actions/GitMerge.java b/plugins/git4idea/src/git4idea/actions/GitMerge.java index 575fd9368e2d..b4e0645d2b7f 100644 --- a/plugins/git4idea/src/git4idea/actions/GitMerge.java +++ b/plugins/git4idea/src/git4idea/actions/GitMerge.java @@ -22,6 +22,7 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.update.ActionInfo; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitRevisionNumber; +import git4idea.GitUtil; import git4idea.commands.GitHandlerUtil; import git4idea.commands.GitLineHandler; import git4idea.i18n.GitBundle; @@ -71,7 +72,10 @@ public class GitMerge extends GitRepositoryAction { } finally { exceptions.addAll(h.errors()); - GitRepositoryManager.getInstance(project).updateRepository(root, GitRepository.TrackedTopic.ALL_CURRENT); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager != null) { + manager.updateRepository(root, GitRepository.TrackedTopic.ALL_CURRENT); + } } if (exceptions.size() != 0) { return; diff --git a/plugins/git4idea/src/git4idea/actions/GitPull.java b/plugins/git4idea/src/git4idea/actions/GitPull.java index 0d2cf7c1fe4b..9dad1b3a5f9c 100644 --- a/plugins/git4idea/src/git4idea/actions/GitPull.java +++ b/plugins/git4idea/src/git4idea/actions/GitPull.java @@ -71,7 +71,12 @@ public class GitPull extends GitRepositoryAction { new Task.Modal(project, GitBundle.message("pulling.title", dialog.getRemote()), true) { @Override public void run(@NotNull ProgressIndicator indicator) { - GitRepository repository = GitRepositoryManager.getInstance(project).getRepositoryForRoot(dialog.gitRoot()); + final GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(myProject); + if (repositoryManager == null) { + return; + } + + GitRepository repository = repositoryManager.getRepositoryForRoot(dialog.gitRoot()); assert repository != null : "Repository can't be null for root " + dialog.gitRoot(); String remoteOrUrl = dialog.getRemote(); @@ -108,13 +113,13 @@ public class GitPull extends GitRepositoryAction { @Override protected void onSuccess() { GitMergeUtil.showUpdates(GitPull.this, project, exceptions, root, currentRev, beforeLabel, getActionName(), ActionInfo.UPDATE); - GitRepositoryManager.getInstance(project).updateRepository(root, GitRepository.TrackedTopic.ALL); + repositoryManager.updateRepository(root, GitRepository.TrackedTopic.ALL); } @Override protected void onFailure() { GitUIUtil.notifyGitErrors(project, "Error pulling " + dialog.getRemote(), "", handlerReference.get().errors()); - GitRepositoryManager.getInstance(project).updateRepository(root, GitRepository.TrackedTopic.ALL); + repositoryManager.updateRepository(root, GitRepository.TrackedTopic.ALL); } }); } diff --git a/plugins/git4idea/src/git4idea/actions/GitRebaseActionBase.java b/plugins/git4idea/src/git4idea/actions/GitRebaseActionBase.java index cc692911cb96..452dd6c157bb 100644 --- a/plugins/git4idea/src/git4idea/actions/GitRebaseActionBase.java +++ b/plugins/git4idea/src/git4idea/actions/GitRebaseActionBase.java @@ -19,7 +19,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; -import git4idea.commands.*; +import git4idea.GitUtil; +import git4idea.commands.GitLineHandler; +import git4idea.commands.GitTask; +import git4idea.commands.GitTaskResult; +import git4idea.commands.GitTaskResultHandlerAdapter; import git4idea.i18n.GitBundle; import git4idea.rebase.GitInteractiveRebaseEditorHandler; import git4idea.rebase.GitRebaseEditorService; @@ -62,7 +66,10 @@ public abstract class GitRebaseActionBase extends GitRepositoryAction { @Override protected void run(GitTaskResult taskResult) { editor.close(); - GitRepositoryManager.getInstance(project).updateRepository(root, GitRepository.TrackedTopic.ALL_CURRENT); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager != null) { + manager.updateRepository(root, GitRepository.TrackedTopic.ALL_CURRENT); + } notifyAboutErrorResult(taskResult, resultListener, exceptions, project); } }); diff --git a/plugins/git4idea/src/git4idea/actions/GitRepositoryAction.java b/plugins/git4idea/src/git4idea/actions/GitRepositoryAction.java index a9fffc8cc91c..54d403158bff 100644 --- a/plugins/git4idea/src/git4idea/actions/GitRepositoryAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitRepositoryAction.java @@ -15,7 +15,10 @@ */ package git4idea.actions; -import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ActionPlaces; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAwareAction; @@ -113,7 +116,11 @@ public abstract class GitRepositoryAction extends DumbAwareAction { final VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY); if (files != null) { for (VirtualFile file : files) { - final GitRepository repositoryForFile = GitRepositoryManager.getInstance(project).getRepositoryForFile(file); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + return false; + } + final GitRepository repositoryForFile = manager.getRepositoryForFile(file); if (repositoryForFile != null && repositoryForFile.getState() == GitRepository.State.REBASING) { return true; } diff --git a/plugins/git4idea/src/git4idea/actions/GitResetHead.java b/plugins/git4idea/src/git4idea/actions/GitResetHead.java index 69bb0a6fc754..b84f5e33810c 100644 --- a/plugins/git4idea/src/git4idea/actions/GitResetHead.java +++ b/plugins/git4idea/src/git4idea/actions/GitResetHead.java @@ -18,6 +18,7 @@ package git4idea.actions; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; +import git4idea.GitUtil; import git4idea.commands.GitHandlerUtil; import git4idea.commands.GitLineHandler; import git4idea.i18n.GitBundle; @@ -57,6 +58,9 @@ public class GitResetHead extends GitRepositoryAction { GitLineHandler h = d.handler(); affectedRoots.add(d.getGitRoot()); GitHandlerUtil.doSynchronously(h, GitBundle.getString("resetting.title"), h.printableCommandLine()); - GitRepositoryManager.getInstance(project).updateRepository(d.getGitRoot(), GitRepository.TrackedTopic.ALL_CURRENT); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager != null) { + manager.updateRepository(d.getGitRoot(), GitRepository.TrackedTopic.ALL_CURRENT); + } } } diff --git a/plugins/git4idea/src/git4idea/actions/GitResolveConflictsAction.java b/plugins/git4idea/src/git4idea/actions/GitResolveConflictsAction.java index a6dc83176c91..69fadd69153f 100644 --- a/plugins/git4idea/src/git4idea/actions/GitResolveConflictsAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitResolveConflictsAction.java @@ -24,9 +24,9 @@ import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vfs.VirtualFile; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.repo.GitRepository; -import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -71,7 +71,7 @@ public class GitResolveConflictsAction extends GitAction { AbstractVcsHelper.getInstance(project).showMergeDialog(new ArrayList(conflictedFiles), GitVcs.getInstance(project).getMergeProvider()); for (VirtualFile conflictedFile : conflictedFiles) { - final GitRepository repo = GitRepositoryManager.getInstance(project).getRepositoryForFile(conflictedFile); + final GitRepository repo = GitUtil.getRepositoryManager(project).getRepositoryForFile(conflictedFile); if (repo != null) { repo.update(GitRepository.TrackedTopic.ALL_CURRENT); } diff --git a/plugins/git4idea/src/git4idea/actions/GitRevert.java b/plugins/git4idea/src/git4idea/actions/GitRevert.java index 571f0f8bbb05..29fbb90a3b52 100644 --- a/plugins/git4idea/src/git4idea/actions/GitRevert.java +++ b/plugins/git4idea/src/git4idea/actions/GitRevert.java @@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ui.RollbackChangesDialog; import com.intellij.openapi.vfs.VirtualFile; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.i18n.GitBundle; import git4idea.repo.GitRepository; @@ -50,9 +51,12 @@ public class GitRevert extends BasicAction { } RollbackChangesDialog.rollbackChanges(project, changes); for (VirtualFile conflictedFile : affectedFiles) { - final GitRepository repo = GitRepositoryManager.getInstance(project).getRepositoryForFile(conflictedFile); - if (repo != null) { - repo.update(GitRepository.TrackedTopic.ALL_CURRENT); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager != null) { + final GitRepository repo = manager.getRepositoryForFile(conflictedFile); + if (repo != null) { + repo.update(GitRepository.TrackedTopic.ALL_CURRENT); + } } } return false; diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java index 6ef8e74e2f68..18de6c810cb3 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java +++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java @@ -330,8 +330,10 @@ public class GitCheckinEnvironment implements CheckinEnvironment { } handler.endOptions(); handler.run(); - GitRepositoryManager.getInstance(project).updateRepository(root, GitRepository.TrackedTopic.CURRENT_REVISION, - GitRepository.TrackedTopic.STATE); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager != null) { + manager.updateRepository(root, GitRepository.TrackedTopic.CURRENT_REVISION, GitRepository.TrackedTopic.STATE); + } } catch (VcsException ex) { exceptions.add(ex); @@ -474,9 +476,10 @@ public class GitCheckinEnvironment implements CheckinEnvironment { handler.addParameters(paths); handler.run(); } - GitRepositoryManager.getInstance(project).updateRepository(root, - GitRepository.TrackedTopic.CURRENT_REVISION, - GitRepository.TrackedTopic.STATE); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager != null) { + manager.updateRepository(root, GitRepository.TrackedTopic.CURRENT_REVISION, GitRepository.TrackedTopic.STATE); + } } diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinHandlerFactory.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinHandlerFactory.java index f0bf62dd7d97..b45df4d672e5 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitCheckinHandlerFactory.java +++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinHandlerFactory.java @@ -28,6 +28,7 @@ import com.intellij.openapi.vcs.checkin.CheckinHandler; import com.intellij.openapi.vcs.checkin.VcsCheckinHandlerFactory; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.PairConsumer; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.config.GitConfigUtil; import git4idea.config.GitVersion; @@ -241,7 +242,10 @@ public class GitCheckinHandlerFactory extends VcsCheckinHandlerFactory { */ @Nullable private DetachedRoot getDetachedRoot() { - GitRepositoryManager repositoryManager = GitRepositoryManager.getInstance(myPanel.getProject()); + GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(myPanel.getProject()); + if (repositoryManager == null) { + return null; + } for (VirtualFile root : myPanel.getRoots()) { GitRepository repository = repositoryManager.getRepositoryForRoot(root); if (repository == null) { diff --git a/plugins/git4idea/src/git4idea/commands/GitCompoundResult.java b/plugins/git4idea/src/git4idea/commands/GitCompoundResult.java index cceba3283cb8..a0ea8be656f2 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCompoundResult.java +++ b/plugins/git4idea/src/git4idea/commands/GitCompoundResult.java @@ -16,8 +16,8 @@ package git4idea.commands; import com.intellij.openapi.project.Project; +import git4idea.GitUtil; import git4idea.repo.GitRepository; -import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; import java.util.HashMap; @@ -90,6 +90,6 @@ public final class GitCompoundResult { } private boolean onlyOneRepositoryInTheProject() { - return !GitRepositoryManager.getInstance(myProject).moreThanOneRoot(); + return !GitUtil.getRepositoryManager(myProject).moreThanOneRoot(); } } diff --git a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java index 038951c9bcae..8cff73be669b 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.ui.components.JBCheckBox; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.i18n.GitBundle; import git4idea.repo.GitRepositoryManager; @@ -74,7 +75,7 @@ public class GitVcsPanel { myConvertTextFilesComboBox.setSelectedItem(CRLF_ASK); myGitField.addBrowseFolderListener(GitBundle.getString("find.git.title"), GitBundle.getString("find.git.description"), project, FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor()); - final GitRepositoryManager repositoryManager = GitRepositoryManager.getInstance(project); + final GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(myProject); mySyncBranchControl.setVisible(repositoryManager != null && repositoryManager.moreThanOneRoot()); } diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java index a433ba6d5117..0863d4d10dfb 100644 --- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java +++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java @@ -26,12 +26,12 @@ import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.merge.MergeDialogCustomizer; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.AsynchConsumer; import git4idea.GitBranch; import git4idea.GitTag; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.branch.GitBranchesCollection; import git4idea.commands.GitCommand; @@ -43,7 +43,6 @@ import git4idea.history.wholeTree.AbstractHash; import git4idea.history.wholeTree.CommitHashPlusParents; import git4idea.merge.GitConflictResolver; import git4idea.repo.GitRepository; -import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -116,7 +115,7 @@ public class LowLevelAccessImpl implements LowLevelAccess { // uses cached version public CachedRefs getRefs() throws VcsException { final CachedRefs refs = new CachedRefs(); - final GitRepository repositoryForRoot = GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(myRoot); + final GitRepository repositoryForRoot = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(myRoot); final GitBranchesCollection branches; if (repositoryForRoot != null) { branches = repositoryForRoot.getBranches(); diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java index f81db8e39e81..f5bc8f60ee8d 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java @@ -57,6 +57,7 @@ import com.intellij.util.ui.AdjustComponentWhenShown; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.UIUtil; import com.intellij.vcsUtil.VcsUtil; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.changes.GitChangeUtils; import git4idea.history.browser.*; @@ -2326,7 +2327,7 @@ public class GitLogUI implements Disposable { if (commitAt.holdsDecoration() || myTableModel.isStashed(commitAt)) return; final GitRepository repository = - GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(commitAt.selectRepository(myRootsUnderVcs)); + GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(commitAt.selectRepository(myRootsUnderVcs)); if (repository == null) return; new GitBranchOperationsProcessor(repository, myRefresh).checkout(commitAt.getHash().getString()); } @@ -2350,7 +2351,7 @@ public class GitLogUI implements Disposable { if (commitAt.holdsDecoration() || myTableModel.isStashed(commitAt)) return; final GitRepository repository = - GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(commitAt.selectRepository(myRootsUnderVcs)); + GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(commitAt.selectRepository(myRootsUnderVcs)); if (repository == null) return; String reference = commitAt.getHash().getString(); @@ -2390,7 +2391,7 @@ public class GitLogUI implements Disposable { if (commitAt.holdsDecoration() || myTableModel.isStashed(commitAt)) return; final GitRepository repository = - GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(commitAt.selectRepository(myRootsUnderVcs)); + GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(commitAt.selectRepository(myRootsUnderVcs)); if (repository == null) return; new GitCreateNewTag(myProject, repository, commitAt.getHash().getString(), myRefresh).execute(); } diff --git a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java index d468164ef748..471fa9956f06 100644 --- a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java +++ b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java @@ -23,6 +23,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.DocumentAdapter; import com.intellij.util.ArrayUtil; import git4idea.GitDeprecatedRemote; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.commands.GitCommand; import git4idea.commands.GitHandlerUtil; @@ -31,7 +32,6 @@ import git4idea.commands.GitSimpleHandler; import git4idea.i18n.GitBundle; import git4idea.jgit.GitHttpAdapter; import git4idea.repo.GitRepository; -import git4idea.repo.GitRepositoryManager; import git4idea.util.GitUIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -183,7 +183,7 @@ public class GitPullDialog extends DialogWrapper { @NotNull private Collection getRemoteBranches(@NotNull GitDeprecatedRemote remote) { if (GitHttpAdapter.shouldUseJGit(remote.fetchUrl())) { - GitRepository repository = GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(gitRoot()); + GitRepository repository = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(gitRoot()); if (repository == null) { return Collections.emptyList(); } diff --git a/plugins/git4idea/src/git4idea/push/GitPushDialog.java b/plugins/git4idea/src/git4idea/push/GitPushDialog.java index cb4bcb804291..1c4f10560023 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushDialog.java +++ b/plugins/git4idea/src/git4idea/push/GitPushDialog.java @@ -30,7 +30,6 @@ import git4idea.GitUtil; import git4idea.history.browser.GitCommit; import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; -import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -67,7 +66,7 @@ public class GitPushDialog extends DialogWrapper { myProject = project; myPusher = new GitPusher(myProject, new EmptyProgressIndicator()); - myRepositories = GitRepositoryManager.getInstance(myProject).getRepositories(); + myRepositories = GitUtil.getRepositoryManager(myProject).getRepositories(); myLoadingPanel = new JBLoadingPanel(new BorderLayout(), this.getDisposable()); diff --git a/plugins/git4idea/src/git4idea/push/GitPusher.java b/plugins/git4idea/src/git4idea/push/GitPusher.java index e752c3a8322e..e8907f052130 100644 --- a/plugins/git4idea/src/git4idea/push/GitPusher.java +++ b/plugins/git4idea/src/git4idea/push/GitPusher.java @@ -122,7 +122,7 @@ public final class GitPusher { public GitPusher(@NotNull Project project, @NotNull ProgressIndicator indicator) { myProject = project; myProgressIndicator = indicator; - myRepositoryManager = GitRepositoryManager.getInstance(myProject); + myRepositoryManager = GitUtil.getRepositoryManager(myProject); myRepositories = myRepositoryManager.getRepositories(); mySettings = GitVcsSettings.getInstance(myProject); myPushSettings = GitPushSettings.getInstance(myProject); diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java index 54aaa3010075..e75e8583e8d3 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java @@ -15,198 +15,52 @@ */ package git4idea.repo; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.components.AbstractProjectComponent; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.DumbAwareRunnable; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.vcs.AbstractVcs; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ArrayUtil; -import git4idea.GitUtil; -import git4idea.PlatformFacade; -import git4idea.roots.GitRootScanner; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.List; /** * GitRepositoryManager initializes and stores {@link GitRepository GitRepositories} for Git roots defined in the project. * @author Kirill Likhodedov */ -public final class GitRepositoryManager extends AbstractProjectComponent implements Disposable { - - private static final Logger LOG = Logger.getInstance(GitRepositoryManager.class); - - @NotNull private final AbstractVcs myVcs; - @NotNull private final ProjectLevelVcsManager myVcsManager; - - @NotNull private final Map myRepositories = new HashMap(); - @NotNull private final Set myListeners = new HashSet(); - - @NotNull private final ReentrantReadWriteLock REPO_LOCK = new ReentrantReadWriteLock(); - private GitRootScanner myRootScanner; - - @Nullable - public static GitRepositoryManager getInstance(@NotNull Project project) { - return ServiceManager.getService(project, GitRepositoryManager.class); - } - - public GitRepositoryManager(@NotNull Project project, @NotNull PlatformFacade platformFacade) { - super(project); - myVcsManager = ProjectLevelVcsManager.getInstance(myProject); - myVcs = platformFacade.getVcs(myProject); - } - - @Override - public void initComponent() { - Disposer.register(myProject, this); - myRootScanner = new GitRootScanner(myProject, new DumbAwareRunnable() { - @Override - public void run() { - updateRepositoriesCollection(); - } - }); - Disposer.register(this, myRootScanner); - } - - @Override - public void dispose() { - try { - REPO_LOCK.writeLock().lock(); - myRepositories.clear(); - myListeners.clear(); - } - finally { - REPO_LOCK.writeLock().unlock(); - } - } +public interface GitRepositoryManager { /** * Returns the {@link GitRepository} which tracks the Git repository located in the given directory, - * or {@code null} if the given file is not a Git root known to this {@link Project}. + * or {@code null} if the given file is not a Git root known to this {@link com.intellij.openapi.project.Project}. */ @Nullable - public GitRepository getRepositoryForRoot(@Nullable VirtualFile root) { - if (root == null) { - return null; - } - try { - REPO_LOCK.readLock().lock(); - return myRepositories.get(root); - } - finally { - REPO_LOCK.readLock().unlock(); - } - } + GitRepository getRepositoryForRoot(@Nullable VirtualFile root); /** * Returns the {@link GitRepository} which the given file belongs to, or {@code null} if the file is not under any Git repository. */ @Nullable - public GitRepository getRepositoryForFile(@NotNull VirtualFile file) { - final VirtualFile vcsRoot = myVcsManager.getVcsRootFor(file); - if (vcsRoot == null) { return null; } - return getRepositoryForRoot(vcsRoot); - } + GitRepository getRepositoryForFile(@NotNull VirtualFile file); /** * @return all repositories tracked by the manager. */ @NotNull - public List getRepositories() { - try { - REPO_LOCK.readLock().lock(); - return GitUtil.sortRepositories(myRepositories.values()); - } - finally { - REPO_LOCK.readLock().unlock(); - } - } + List getRepositories(); - public boolean moreThanOneRoot() { - return myRepositories.values().size() > 1; - } + boolean moreThanOneRoot(); /** * Adds the listener to all existing repositories AND all future repositories. * I.e. if a new GitRepository is be created via this GitRepositoryManager, the listener will be added to the repository. */ - public void addListenerToAllRepositories(@NotNull GitRepositoryChangeListener listener) { - myListeners.add(listener); - for (GitRepository repo : getRepositories()) { - repo.addListener(listener); - } - } + void addListenerToAllRepositories(@NotNull GitRepositoryChangeListener listener); /** * Synchronously updates the specified information about Git repository under the given root. * @param root root directory of the Git repository. * @param topics TrackedTopics that are to be updated. */ - public void updateRepository(VirtualFile root, GitRepository.TrackedTopic... topics) { - GitRepository repo = getRepositoryForRoot(root); - if (repo != null) { - repo.update(topics); - } - } + void updateRepository(VirtualFile root, GitRepository.TrackedTopic... topics); - public void updateAllRepositories(GitRepository.TrackedTopic... topics) { - for (VirtualFile root : myRepositories.keySet()) { - updateRepository(root, topics); - } - } - - // note: we are not calling this method during the project startup - it is called anyway by the GitRootTracker - private void updateRepositoriesCollection() { - try { - REPO_LOCK.writeLock().lock(); - final VirtualFile[] roots = myVcsManager.getRootsUnderVcs(myVcs); - // remove repositories that are not in the roots anymore - for (Iterator> iterator = myRepositories.entrySet().iterator(); iterator.hasNext(); ) { - if (!ArrayUtil.contains(iterator.next().getValue().getRoot(), roots)) { - iterator.remove(); - } - } - // add GitRepositories for all roots that don't have correspondent GitRepositories yet. - for (VirtualFile root : roots) { - if (!myRepositories.containsKey(root)) { - if (gitRootOK(root)) { - GitRepository repository = createGitRepository(root); - myRepositories.put(root, repository); - } - else { - LOG.info("Invalid Git root: " + root); - } - } - } - } - finally { - REPO_LOCK.writeLock().unlock(); - } - } - - private static boolean gitRootOK(@NotNull VirtualFile root) { - VirtualFile gitDir = root.findChild(".git"); - return gitDir != null && gitDir.exists(); - } - - private GitRepository createGitRepository(VirtualFile root) { - GitRepository repository = GitRepository.getFullInstance(root, myProject, this); - for (GitRepositoryChangeListener listener : myListeners) { - repository.addListener(listener); - } - return repository; - } - - @Override - public String toString() { - return "GitRepositoryManager{myRepositories: " + myRepositories + '}'; - } + void updateAllRepositories(GitRepository.TrackedTopic... topics); } diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java new file mode 100644 index 000000000000..e3373868c2de --- /dev/null +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java @@ -0,0 +1,192 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea.repo; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.components.AbstractProjectComponent; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.DumbAwareRunnable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ArrayUtil; +import git4idea.GitUtil; +import git4idea.PlatformFacade; +import git4idea.roots.GitRootScanner; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * @author Kirill Likhodedov + */ +public class GitRepositoryManagerImpl extends AbstractProjectComponent implements Disposable, GitRepositoryManager { + + private static final Logger LOG = Logger.getInstance(GitRepositoryManager.class); + + @NotNull private final AbstractVcs myVcs; + @NotNull private final ProjectLevelVcsManager myVcsManager; + + @NotNull private final Map myRepositories = new HashMap(); + @NotNull private final Set myListeners = new HashSet(); + + @NotNull private final ReentrantReadWriteLock REPO_LOCK = new ReentrantReadWriteLock(); + + public GitRepositoryManagerImpl(@NotNull Project project, @NotNull PlatformFacade platformFacade) { + super(project); + myVcsManager = ProjectLevelVcsManager.getInstance(myProject); + myVcs = platformFacade.getVcs(myProject); + } + + @Override + public void initComponent() { + Disposer.register(myProject, this); + GitRootScanner rootScanner = new GitRootScanner(myProject, new DumbAwareRunnable() { + @Override + public void run() { + updateRepositoriesCollection(); + } + }); + Disposer.register(this, rootScanner); + } + + @Override + public void dispose() { + try { + REPO_LOCK.writeLock().lock(); + myRepositories.clear(); + myListeners.clear(); + } + finally { + REPO_LOCK.writeLock().unlock(); + } + } + + @Override + @Nullable + public GitRepository getRepositoryForRoot(@Nullable VirtualFile root) { + if (root == null) { + return null; + } + try { + REPO_LOCK.readLock().lock(); + return myRepositories.get(root); + } + finally { + REPO_LOCK.readLock().unlock(); + } + } + + @Override + @Nullable + public GitRepository getRepositoryForFile(@NotNull VirtualFile file) { + final VirtualFile vcsRoot = myVcsManager.getVcsRootFor(file); + if (vcsRoot == null) { return null; } + return getRepositoryForRoot(vcsRoot); + } + + @Override + @NotNull + public List getRepositories() { + try { + REPO_LOCK.readLock().lock(); + return GitUtil.sortRepositories(myRepositories.values()); + } + finally { + REPO_LOCK.readLock().unlock(); + } + } + + @Override + public boolean moreThanOneRoot() { + return myRepositories.values().size() > 1; + } + + @Override + public void addListenerToAllRepositories(@NotNull GitRepositoryChangeListener listener) { + myListeners.add(listener); + for (GitRepository repo : getRepositories()) { + repo.addListener(listener); + } + } + + @Override + public void updateRepository(VirtualFile root, GitRepository.TrackedTopic... topics) { + GitRepository repo = getRepositoryForRoot(root); + if (repo != null) { + repo.update(topics); + } + } + + @Override + public void updateAllRepositories(GitRepository.TrackedTopic... topics) { + for (VirtualFile root : myRepositories.keySet()) { + updateRepository(root, topics); + } + } + + // note: we are not calling this method during the project startup - it is called anyway by the GitRootTracker + private void updateRepositoriesCollection() { + try { + REPO_LOCK.writeLock().lock(); + final VirtualFile[] roots = myVcsManager.getRootsUnderVcs(myVcs); + // remove repositories that are not in the roots anymore + for (Iterator> iterator = myRepositories.entrySet().iterator(); iterator.hasNext(); ) { + if (!ArrayUtil.contains(iterator.next().getValue().getRoot(), roots)) { + iterator.remove(); + } + } + // add GitRepositories for all roots that don't have correspondent GitRepositories yet. + for (VirtualFile root : roots) { + if (!myRepositories.containsKey(root)) { + if (gitRootOK(root)) { + GitRepository repository = createGitRepository(root); + myRepositories.put(root, repository); + } + else { + LOG.info("Invalid Git root: " + root); + } + } + } + } + finally { + REPO_LOCK.writeLock().unlock(); + } + } + + private static boolean gitRootOK(@NotNull VirtualFile root) { + VirtualFile gitDir = root.findChild(".git"); + return gitDir != null && gitDir.exists(); + } + + private GitRepository createGitRepository(VirtualFile root) { + GitRepository repository = GitRepository.getFullInstance(root, myProject, this); + for (GitRepositoryChangeListener listener : myListeners) { + repository.addListener(listener); + } + return repository; + } + + @Override + public String toString() { + return "GitRepositoryManager{myRepositories: " + myRepositories + '}'; + } + +} diff --git a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java index c6e124bd8a94..b7df75f8fde8 100644 --- a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java +++ b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java @@ -26,6 +26,7 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.*; import com.intellij.util.messages.MessageBusConnection; +import git4idea.GitUtil; import git4idea.commands.Git; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -295,7 +296,7 @@ public class GitUntrackedFilesHolder implements Disposable, BulkFileListener { } private boolean belongsToThisRepository(VirtualFile file) { - final GitRepository repository = GitRepositoryManager.getInstance(myProject).getRepositoryForFile(file); + final GitRepository repository = GitUtil.getRepositoryManager(myProject).getRepositoryForFile(file); return repository != null && repository.getRoot().equals(myRoot); } diff --git a/plugins/git4idea/src/git4idea/rollback/GitRollbackEnvironment.java b/plugins/git4idea/src/git4idea/rollback/GitRollbackEnvironment.java index 82f35fc056f4..b730d38e2ebf 100644 --- a/plugins/git4idea/src/git4idea/rollback/GitRollbackEnvironment.java +++ b/plugins/git4idea/src/git4idea/rollback/GitRollbackEnvironment.java @@ -29,13 +29,12 @@ import com.intellij.vcsUtil.VcsFileUtil; import com.intellij.vcsUtil.VcsUtil; import git4idea.GitUtil; import git4idea.commands.GitCommand; -import git4idea.util.GitFileUtils; import git4idea.commands.GitHandlerUtil; import git4idea.commands.GitSimpleHandler; import git4idea.i18n.GitBundle; import git4idea.repo.GitRepository; -import git4idea.repo.GitRepositoryManager; import git4idea.repo.GitUntrackedFilesHolder; +import git4idea.util.GitFileUtils; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -165,7 +164,7 @@ public class GitRollbackEnvironment implements RollbackEnvironment { } lfs.refreshIoFiles(filesToRefresh); - for (GitRepository repo : GitRepositoryManager.getInstance(myProject).getRepositories()) { + for (GitRepository repo : GitUtil.getRepositoryManager(myProject).getRepositories()) { repo.update(GitRepository.TrackedTopic.ALL_CURRENT); } } @@ -200,7 +199,7 @@ public class GitRollbackEnvironment implements RollbackEnvironment { GitFileUtils.delete(myProject, root, files, "--cached", "-f"); if (toUnversioned) { - final GitRepository repo = GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(root); + final GitRepository repo = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(root); final GitUntrackedFilesHolder untrackedFilesHolder = (repo == null ? null : repo.getUntrackedFilesHolder()); for (FilePath path : files) { final VirtualFile vf = VcsUtil.getVirtualFile(path.getIOFile()); diff --git a/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java b/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java index c0a2791f634e..983e493813cf 100644 --- a/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java +++ b/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java @@ -27,16 +27,16 @@ import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.VcsDirtyScope; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; -import git4idea.commands.Git; import git4idea.GitContentRevision; import git4idea.GitFormatException; import git4idea.GitRevisionNumber; +import git4idea.GitUtil; import git4idea.changes.GitChangeUtils; +import git4idea.commands.Git; import git4idea.commands.GitCommand; import git4idea.commands.GitHandler; import git4idea.commands.GitSimpleHandler; import git4idea.repo.GitRepository; -import git4idea.repo.GitRepositoryManager; import git4idea.repo.GitUntrackedFilesHolder; import org.jetbrains.annotations.NotNull; @@ -91,7 +91,7 @@ class GitNewChangesCollector extends GitChangesCollector { { super(project, changeListManager, dirtyScope, vcsRoot); myGit = git; - myRepository = GitRepositoryManager.getInstance(project).getRepositoryForRoot(vcsRoot); + myRepository = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(vcsRoot); Collection dirtyPaths = dirtyPaths(true); if (!dirtyPaths.isEmpty()) { diff --git a/plugins/git4idea/src/git4idea/ui/GitTagDialog.java b/plugins/git4idea/src/git4idea/ui/GitTagDialog.java index fdfd7ec16365..7c3cf001800b 100644 --- a/plugins/git4idea/src/git4idea/ui/GitTagDialog.java +++ b/plugins/git4idea/src/git4idea/ui/GitTagDialog.java @@ -22,14 +22,15 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.DocumentAdapter; +import git4idea.GitUtil; import git4idea.commands.GitCommand; import git4idea.commands.GitHandlerUtil; import git4idea.commands.GitSimpleHandler; -import git4idea.util.GitUIUtil; -import git4idea.util.StringScanner; import git4idea.i18n.GitBundle; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; +import git4idea.util.GitUIUtil; +import git4idea.util.StringScanner; import org.jetbrains.annotations.NonNls; import javax.swing.*; @@ -201,7 +202,10 @@ public class GitTagDialog extends DialogWrapper { } finally { exceptions.addAll(h.errors()); - GitRepositoryManager.getInstance(myProject).updateRepository(getGitRoot(), GitRepository.TrackedTopic.ALL); + GitRepositoryManager manager = GitUtil.getRepositoryManager(myProject); + if (manager != null) { + manager.updateRepository(getGitRoot(), GitRepository.TrackedTopic.ALL); + } } } finally { diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java index 395488cd219d..f3f8c364d111 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java @@ -32,6 +32,7 @@ import com.intellij.openapi.util.IconLoader; import com.intellij.ui.popup.PopupFactoryImpl; import com.intellij.ui.popup.WizardPopup; import com.intellij.ui.popup.list.ListPopupImpl; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.config.GitVcsSettings; import git4idea.repo.GitRepository; @@ -81,7 +82,7 @@ class GitBranchPopup { private GitBranchPopup(@NotNull Project project, @NotNull GitRepository currentRepository) { myProject = project; myCurrentRepository = currentRepository; - myRepositoryManager = GitRepositoryManager.getInstance(project); + myRepositoryManager = GitUtil.getRepositoryManager(project); myVcs = GitVcs.getInstance(project); myVcsSettings = GitVcsSettings.getInstance(myProject); @@ -193,7 +194,7 @@ class GitBranchPopup { private ActionGroup createActions() { DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); - GitRepositoryManager repositoryManager = GitRepositoryManager.getInstance(myProject); + GitRepositoryManager repositoryManager = myRepositoryManager; if (repositoryManager.moreThanOneRoot()) { if (!myMultiRootBranchConfig.diverged() && userWantsSyncControl()) { @@ -245,7 +246,7 @@ class GitBranchPopup { private DefaultActionGroup createRepositoriesActions() { DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); popupGroup.addSeparator("Repositories"); - for (GitRepository repository : GitRepositoryManager.getInstance(myProject).getRepositories()) { + for (GitRepository repository : myRepositoryManager.getRepositories()) { popupGroup.add(new RootAction(repository, highlightCurrentRepo() ? myCurrentRepository : null)); } return popupGroup; diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchUiUtil.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchUiUtil.java index ba172345a885..cbb17dfc7a05 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchUiUtil.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchUiUtil.java @@ -33,6 +33,7 @@ import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.impl.status.StatusBarUtil; import com.intellij.vcsUtil.VcsUtil; import git4idea.GitBranch; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.config.GitVcsSettings; import git4idea.repo.GitRepository; @@ -163,7 +164,10 @@ public class GitBranchUiUtil { if (project == null) { return null; } - GitRepositoryManager manager = GitRepositoryManager.getInstance(project); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + return null; + } VirtualFile file = getSelectedFile(project); if (file != null) { return manager.getRepositoryForRoot(getVcsRootFor(project, file)); diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java index 6feb64222a0a..88033db621bb 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java @@ -25,10 +25,10 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.StatusBarWidget; import com.intellij.openapi.wm.impl.status.EditorBasedWidget; import com.intellij.util.Consumer; +import git4idea.GitUtil; import git4idea.config.GitVcsSettings; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryChangeListener; -import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; import java.awt.event.MouseEvent; @@ -47,7 +47,7 @@ public class GitBranchWidget extends EditorBasedWidget implements StatusBarWidge public GitBranchWidget(Project project) { super(project); - GitRepositoryManager.getInstance(project).addListenerToAllRepositories(this); + GitUtil.getRepositoryManager(project).addListenerToAllRepositories(this); mySettings = GitVcsSettings.getInstance(project); myMaxString = "Git: Rebasing master"; } @@ -161,7 +161,7 @@ public class GitBranchWidget extends EditorBasedWidget implements StatusBarWidge @NotNull private static String getDisplayableBranchTooltip(GitRepository repo) { String text = GitBranchUiUtil.getDisplayableBranchText(repo); - if (GitRepositoryManager.getInstance(repo.getProject()).getRepositories().size() > 1) { + if (!GitUtil.justOneGitRepository(repo.getProject())) { return text + "\n" + "Root: " + repo.getRoot().getName(); } return text; diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchesAction.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchesAction.java index 3cc34f861b8c..8c1fb1266b27 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchesAction.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchesAction.java @@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import git4idea.GitUtil; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; @@ -36,8 +37,10 @@ public class GitBranchesAction extends DumbAwareAction { public void actionPerformed(AnActionEvent e) { final Project project = e.getData(PlatformDataKeys.PROJECT); assert project != null; - GitRepositoryManager repositoryManager = GitRepositoryManager.getInstance(project); - + GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(project); + if (repositoryManager == null) { + return; + } VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE); GitRepository repository = (file == null ? GitBranchUiUtil.getCurrentRepository(project): diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitCompareBranchesDialog.java b/plugins/git4idea/src/git4idea/ui/branch/GitCompareBranchesDialog.java index f607d62654da..373d675503b0 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitCompareBranchesDialog.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitCompareBranchesDialog.java @@ -19,8 +19,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.IconLoader; import com.intellij.ui.TabbedPaneImpl; +import git4idea.GitUtil; import git4idea.repo.GitRepository; -import git4idea.repo.GitRepositoryManager; import git4idea.util.GitCommitCompareInfo; import git4idea.util.GitUIUtil; import org.jetbrains.annotations.NotNull; @@ -50,7 +50,7 @@ public class GitCompareBranchesDialog extends DialogWrapper { myInitialRepo = initialRepo; String rootString; - if (compareInfo.getRepositories().size() == 1 && GitRepositoryManager.getInstance(myProject).moreThanOneRoot()) { + if (compareInfo.getRepositories().size() == 1 && GitUtil.getRepositoryManager(myProject).moreThanOneRoot()) { rootString = " in root " + GitUIUtil.getShortRepositoryName(initialRepo); } else { diff --git a/plugins/git4idea/src/git4idea/update/GitComplexProcess.java b/plugins/git4idea/src/git4idea/update/GitComplexProcess.java index 607f6a422370..f85cf18f5a8d 100644 --- a/plugins/git4idea/src/git4idea/update/GitComplexProcess.java +++ b/plugins/git4idea/src/git4idea/update/GitComplexProcess.java @@ -18,6 +18,7 @@ package git4idea.update; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.util.continuation.*; +import git4idea.GitUtil; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; import git4idea.util.GitFreezingProcess; @@ -91,7 +92,7 @@ public class GitComplexProcess { myOperation = operation; myFreezeReason = "Local changes are not available until Git " + myTitle + " is finished."; - myRepositoryManager = GitRepositoryManager.getInstance(project); + myRepositoryManager = GitUtil.getRepositoryManager(myProject); myChangeListManager = ChangeListManager.getInstance(myProject); // define tasks that need information from constructor diff --git a/plugins/git4idea/src/git4idea/update/GitFetcher.java b/plugins/git4idea/src/git4idea/update/GitFetcher.java index 1891a93155d4..39da8d8e5a42 100644 --- a/plugins/git4idea/src/git4idea/update/GitFetcher.java +++ b/plugins/git4idea/src/git4idea/update/GitFetcher.java @@ -24,6 +24,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitBranch; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.Notificator; import git4idea.branch.GitBranchUtil; @@ -72,7 +73,7 @@ public class GitFetcher { myProject = project; myProgressIndicator = progressIndicator; myFetchAll = fetchAll; - myRepositoryManager = GitRepositoryManager.getInstance(project); + myRepositoryManager = GitUtil.getRepositoryManager(myProject); myVcs = GitVcs.getInstance(project); } diff --git a/plugins/git4idea/src/git4idea/util/GitFileUtils.java b/plugins/git4idea/src/git4idea/util/GitFileUtils.java index 5873656fede6..e4a8e615aa45 100644 --- a/plugins/git4idea/src/git4idea/util/GitFileUtils.java +++ b/plugins/git4idea/src/git4idea/util/GitFileUtils.java @@ -21,6 +21,7 @@ import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsFileUtil; +import git4idea.GitUtil; import git4idea.commands.GitBinaryHandler; import git4idea.commands.GitCommand; import git4idea.commands.GitSimpleHandler; @@ -116,7 +117,11 @@ public class GitFileUtils { handler.setNoSSH(true); handler.run(); } - final GitRepository repository = GitRepositoryManager.getInstance(project).getRepositoryForRoot(root); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + return; + } + final GitRepository repository = manager.getRepositoryForRoot(root); if (repository != null) { repository.getUntrackedFilesHolder().remove(files); } @@ -145,7 +150,12 @@ public class GitFileUtils { * @throws VcsException in case of git problem */ public static void addPaths(Project project, VirtualFile root, Collection files) throws VcsException { - final GitRepository repository = GitRepositoryManager.getInstance(project).getRepositoryForRoot(root); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + return; + } + + final GitRepository repository = manager.getRepositoryForRoot(root); final GitUntrackedFilesHolder untrackedFilesHolder = (repository == null ? null : repository.getUntrackedFilesHolder()); for (List paths : VcsFileUtil.chunkPaths(root, files)) { diff --git a/plugins/git4idea/src/git4idea/util/GitUIUtil.java b/plugins/git4idea/src/git4idea/util/GitUIUtil.java index bb33b27ab846..1c244924e1bc 100644 --- a/plugins/git4idea/src/git4idea/util/GitUIUtil.java +++ b/plugins/git4idea/src/git4idea/util/GitUIUtil.java @@ -29,11 +29,11 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import git4idea.GitBranch; import git4idea.GitDeprecatedRemote; +import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.config.GitConfigUtil; import git4idea.i18n.GitBundle; import git4idea.repo.GitRepository; -import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -236,7 +236,7 @@ public class GitUIUtil { public void actionPerformed(final ActionEvent e) { VirtualFile root = (VirtualFile)gitRootChooser.getSelectedItem(); assert root != null : "The root must not be null"; - GitRepository repo = GitRepositoryManager.getInstance(project).getRepositoryForRoot(root); + GitRepository repo = GitUtil.getRepositoryManager(project).getRepositoryForRoot(root); assert repo != null : "The repository must not be null"; GitBranch current = repo.getCurrentBranch(); if (current == null) { @@ -329,7 +329,7 @@ public class GitUIUtil { * @param fetchUrl if true, the fetch url is shown instead of push url */ public static void setupRemotes(final Project project, final VirtualFile root, final JComboBox remoteCombobox, final boolean fetchUrl) { - final GitRepository repo = GitRepositoryManager.getInstance(project).getRepositoryForRoot(root); + final GitRepository repo = GitUtil.getRepositoryManager(project).getRepositoryForRoot(root); assert repo != null : "GitRepository can't be null for root " + root; GitBranch gitBranch = repo.getCurrentBranch(); diff --git a/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java b/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java new file mode 100644 index 000000000000..16db16994d10 --- /dev/null +++ b/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea.test; + +import com.intellij.openapi.vfs.VirtualFile; +import git4idea.repo.GitRepository; +import git4idea.repo.GitRepositoryChangeListener; +import git4idea.repo.GitRepositoryManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author Kirill Likhodedov + */ +public class GitTestRepositoryManager implements GitRepositoryManager { + + @Override + public GitRepository getRepositoryForRoot(@Nullable VirtualFile root) { + throw new UnsupportedOperationException(); + } + + @Override + public GitRepository getRepositoryForFile(@NotNull VirtualFile file) { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public List getRepositories() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean moreThanOneRoot() { + throw new UnsupportedOperationException(); + } + + @Override + public void addListenerToAllRepositories(@NotNull GitRepositoryChangeListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void updateRepository(VirtualFile root, GitRepository.TrackedTopic... topics) { + throw new UnsupportedOperationException(); + } + + @Override + public void updateAllRepositories(GitRepository.TrackedTopic... topics) { + throw new UnsupportedOperationException(); + } +} diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCheckoutListener.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCheckoutListener.java index 5c812548caf3..65b9227f2d3c 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubCheckoutListener.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCheckoutListener.java @@ -10,6 +10,7 @@ import com.intellij.tasks.TaskRepository; import com.intellij.tasks.github.GitHubRepository; import com.intellij.tasks.github.GitHubRepositoryType; import com.intellij.tasks.impl.TaskManagerImpl; +import git4idea.GitUtil; import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; @@ -45,7 +46,11 @@ public class GithubCheckoutListener implements CheckoutListener { return null; } // Check if git is already initialized and presence of remote branch - final GitRepository gitRepository = GitRepositoryManager.getInstance(project).getRepositoryForFile(root); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + return null; + } + final GitRepository gitRepository = manager.getRepositoryForFile(root); if (gitRepository == null){ return null; } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java index be7695c83769..31bb529a9f9c 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java @@ -26,6 +26,7 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitBranch; +import git4idea.GitUtil; import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; @@ -64,7 +65,11 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { return false; } - final GitRepository gitRepository = GitRepositoryManager.getInstance(project).getRepositoryForFile(dir); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + return false; + } + final GitRepository gitRepository = manager.getRepositoryForFile(dir); if (gitRepository == null) { return false; } @@ -90,7 +95,11 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { } final VirtualFile root = project.getBaseDir(); - final GitRepository gitRepository = GitRepositoryManager.getInstance(project).getRepositoryForFile(root); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + return; + } + final GitRepository gitRepository = manager.getRepositoryForFile(root); // Check that given repository is properly configured git repository final GitRemote gitRemote = GithubUtil.findGitHubRemoteBranch(gitRepository); final String pushUrl = GithubUtil.getGithubUrl(gitRemote); diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java index 9a18c5e636f0..29a06253faef 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java @@ -23,12 +23,12 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ui.UIUtil; +import git4idea.GitUtil; import git4idea.actions.BasicAction; import git4idea.commands.GitCommand; import git4idea.commands.GitSimpleHandler; @@ -37,8 +37,6 @@ import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; import org.jetbrains.plugins.github.ui.GithubLoginDialog; -import javax.swing.*; - /** * Created by IntelliJ IDEA. * @@ -62,7 +60,14 @@ public class GithubRebaseAction extends DumbAwareAction { return; } - final GitRepository gitRepository = GitRepositoryManager.getInstance(project).getRepositoryForFile(project.getBaseDir()); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + e.getPresentation().setVisible(false); + e.getPresentation().setEnabled(false); + return; + } + + final GitRepository gitRepository = manager.getRepositoryForFile(project.getBaseDir()); if (gitRepository == null){ e.getPresentation().setVisible(false); e.getPresentation().setEnabled(false); @@ -94,7 +99,11 @@ public class GithubRebaseAction extends DumbAwareAction { } final VirtualFile root = project.getBaseDir(); - final GitRepository gitRepository = GitRepositoryManager.getInstance(project).getRepositoryForFile(project.getBaseDir()); + GitRepositoryManager manager = GitUtil.getRepositoryManager(project); + if (manager == null) { + return; + } + final GitRepository gitRepository = manager.getRepositoryForFile(project.getBaseDir()); // Check that given repository is properly configured git repository final GitRemote remote = GithubUtil.findGitHubRemoteBranch(gitRepository); final String pushUrl = GithubUtil.getGithubUrl(remote); From caf03670f8f277427e3c12b6cec12b9edc115543 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 13 Mar 2012 13:24:45 +0400 Subject: [PATCH 3/5] Use light GitRepository instance in Git tests. --- plugins/git4idea/tests/git4idea/test/GitExec.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/tests/git4idea/test/GitExec.java b/plugins/git4idea/tests/git4idea/test/GitExec.java index 6cabf8c9cb3d..31e2a0cc11fa 100644 --- a/plugins/git4idea/tests/git4idea/test/GitExec.java +++ b/plugins/git4idea/tests/git4idea/test/GitExec.java @@ -39,7 +39,7 @@ public class GitExec { public static GitRepository init(@NotNull Project project, @NotNull VirtualFile root) throws IOException { new GitTestRunEnv(new File(root.getPath())).run("init"); root.refresh(false, true); - return GitRepository.getFullInstance(root, project, project); + return GitRepository.getLightInstance(root, project, project); } public static void create(@NotNull GitRepository repository, @NotNull String filePath) { From 333d1b7b39fe475eb71366bef8d60babc678505a Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 13 Mar 2012 13:35:38 +0400 Subject: [PATCH 4/5] IDEA-82647 Don't swap subject and description in "Show Affected Paths" dialog. --- plugins/git4idea/src/git4idea/changes/GitChangeUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java index 4e06200c7d00..789ff3a680d7 100644 --- a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java +++ b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java @@ -404,7 +404,7 @@ public class GitChangeUtils { fullComment = commentSubject; } else { - fullComment = commentBody + "\n\n" + commentSubject; + fullComment = commentSubject + "\n" + commentBody; } GitRevisionNumber thisRevision = new GitRevisionNumber(revisionNumber, commitDate); From 7d179d7fbb03804997f1804fc53a16b09dbf33de Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 13 Mar 2012 14:01:55 +0400 Subject: [PATCH 5/5] GitRootScan: make initial scan (as soon as project is initialized and VCS mappings are ready) --- plugins/git4idea/src/git4idea/roots/GitRootScanner.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/git4idea/src/git4idea/roots/GitRootScanner.java b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java index 047a62cc1c8d..9c0c37bdffca 100644 --- a/plugins/git4idea/src/git4idea/roots/GitRootScanner.java +++ b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java @@ -55,6 +55,7 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis @Override public void run() { myProjectIsInitialized = true; + scanIfReady(); } }); @@ -96,6 +97,7 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis @Override public void directoryMappingChanged() { myMappingsAreReady = true; + scanIfReady(); } private void scanIfReady() {