| /* |
| * Copyright 2000-2009 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 com.intellij.openapi.vcs.update; |
| |
| import com.intellij.history.Label; |
| import com.intellij.history.LocalHistory; |
| import com.intellij.history.LocalHistoryAction; |
| import com.intellij.ide.errorTreeView.HotfixData; |
| import com.intellij.openapi.actionSystem.AnActionEvent; |
| import com.intellij.openapi.actionSystem.Presentation; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.options.Configurable; |
| import com.intellij.openapi.progress.*; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.project.ex.ProjectManagerEx; |
| import com.intellij.openapi.ui.MessageType; |
| import com.intellij.openapi.util.Ref; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vcs.*; |
| import com.intellij.openapi.vcs.actions.AbstractVcsAction; |
| import com.intellij.openapi.vcs.actions.DescindingFilesFilter; |
| import com.intellij.openapi.vcs.actions.VcsContext; |
| import com.intellij.openapi.vcs.changes.RemoteRevisionsCache; |
| import com.intellij.openapi.vcs.changes.VcsAnnotationRefresher; |
| import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; |
| import com.intellij.openapi.vcs.changes.VcsDirtyScopeManagerImpl; |
| import com.intellij.openapi.vcs.changes.committed.CommittedChangesCache; |
| import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx; |
| import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; |
| import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; |
| import com.intellij.openapi.vfs.VfsUtil; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.openapi.vfs.VirtualFileManager; |
| import com.intellij.util.Consumer; |
| import com.intellij.util.WaitForProgressToShow; |
| import com.intellij.util.ui.OptionsDialog; |
| import com.intellij.vcsUtil.VcsUtil; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.io.File; |
| import java.util.*; |
| |
| public abstract class AbstractCommonUpdateAction extends AbstractVcsAction { |
| private final boolean myAlwaysVisible; |
| private final static Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.update.AbstractCommonUpdateAction"); |
| |
| private final ActionInfo myActionInfo; |
| private final ScopeInfo myScopeInfo; |
| |
| protected AbstractCommonUpdateAction(ActionInfo actionInfo, ScopeInfo scopeInfo, boolean alwaysVisible) { |
| myActionInfo = actionInfo; |
| myScopeInfo = scopeInfo; |
| myAlwaysVisible = alwaysVisible; |
| } |
| |
| private String getCompleteActionName(VcsContext dataContext) { |
| return myActionInfo.getActionName(myScopeInfo.getScopeName(dataContext, myActionInfo)); |
| } |
| |
| protected void actionPerformed(final VcsContext context) { |
| final Project project = context.getProject(); |
| |
| boolean showUpdateOptions = myActionInfo.showOptions(project); |
| |
| LOG.debug(String.format("project: %s, show update options: %s", project, showUpdateOptions)); |
| |
| if (project != null) { |
| try { |
| final FilePath[] filePaths = myScopeInfo.getRoots(context, myActionInfo); |
| final FilePath[] roots = DescindingFilesFilter.filterDescindingFiles(filterRoots(filePaths, context), project); |
| if (roots.length == 0) { |
| LOG.debug("No roots found."); |
| return; |
| } |
| |
| final Map<AbstractVcs, Collection<FilePath>> vcsToVirtualFiles = createVcsToFilesMap(roots, project); |
| |
| for (AbstractVcs vcs : vcsToVirtualFiles.keySet()) { |
| final UpdateEnvironment updateEnvironment = myActionInfo.getEnvironment(vcs); |
| if ((updateEnvironment != null) && (! updateEnvironment.validateOptions(vcsToVirtualFiles.get(vcs)))) { |
| // messages already shown |
| LOG.debug("Options not valid for files: " + vcsToVirtualFiles); |
| return; |
| } |
| } |
| |
| if (showUpdateOptions || OptionsDialog.shiftIsPressed(context.getModifiers())) { |
| showOptionsDialog(vcsToVirtualFiles, project, context); |
| } |
| |
| if (ApplicationManager.getApplication().isDispatchThread()) { |
| ApplicationManager.getApplication().saveAll(); |
| } |
| Task.Backgroundable task = new Updater(project, roots, vcsToVirtualFiles); |
| if (ApplicationManager.getApplication().isUnitTestMode()) { |
| task.run(new EmptyProgressIndicator()); |
| } |
| else { |
| ProgressManager.getInstance().run(task); |
| } |
| } |
| catch (ProcessCanceledException e1) { |
| //ignore |
| } |
| } |
| } |
| |
| private boolean canGroupByChangelist(final Set<AbstractVcs> abstractVcses) { |
| if (myActionInfo.canGroupByChangelist()) { |
| for(AbstractVcs vcs: abstractVcses) { |
| if (vcs.getCachingCommittedChangesProvider() != null) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| private static boolean someSessionWasCanceled(List<UpdateSession> updateSessions) { |
| for (UpdateSession updateSession : updateSessions) { |
| if (updateSession.isCanceled()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private static String getAllFilesAreUpToDateMessage(FilePath[] roots) { |
| if (roots.length == 1 && !roots[0].isDirectory()) { |
| return VcsBundle.message("message.text.file.is.up.to.date"); |
| } |
| else { |
| return VcsBundle.message("message.text.all.files.are.up.to.date"); |
| } |
| } |
| |
| private void showOptionsDialog(final Map<AbstractVcs, Collection<FilePath>> updateEnvToVirtualFiles, final Project project, |
| final VcsContext dataContext) { |
| LinkedHashMap<Configurable, AbstractVcs> envToConfMap = createConfigurableToEnvMap(updateEnvToVirtualFiles); |
| LOG.debug("configurables map: " + envToConfMap); |
| if (!envToConfMap.isEmpty()) { |
| UpdateOrStatusOptionsDialog dialogOrStatus = myActionInfo.createOptionsDialog(project, envToConfMap, |
| myScopeInfo.getScopeName(dataContext, |
| myActionInfo)); |
| dialogOrStatus.show(); |
| if (!dialogOrStatus.isOK()) { |
| throw new ProcessCanceledException(); |
| } |
| } |
| } |
| |
| private LinkedHashMap<Configurable, AbstractVcs> createConfigurableToEnvMap(Map<AbstractVcs, Collection<FilePath>> updateEnvToVirtualFiles) { |
| LinkedHashMap<Configurable, AbstractVcs> envToConfMap = new LinkedHashMap<Configurable, AbstractVcs>(); |
| for (AbstractVcs vcs : updateEnvToVirtualFiles.keySet()) { |
| Configurable configurable = myActionInfo.getEnvironment(vcs).createConfigurable(updateEnvToVirtualFiles.get(vcs)); |
| if (configurable != null) { |
| envToConfMap.put(configurable, vcs); |
| } |
| } |
| return envToConfMap; |
| } |
| |
| private Map<AbstractVcs,Collection<FilePath>> createVcsToFilesMap(FilePath[] roots, Project project) { |
| HashMap<AbstractVcs, Collection<FilePath>> resultPrep = new HashMap<AbstractVcs, Collection<FilePath>>(); |
| |
| for (FilePath file : roots) { |
| AbstractVcs vcs = VcsUtil.getVcsFor(project, file); |
| if (vcs != null) { |
| UpdateEnvironment updateEnvironment = myActionInfo.getEnvironment(vcs); |
| if (updateEnvironment != null) { |
| if (!resultPrep.containsKey(vcs)) resultPrep.put(vcs, new HashSet<FilePath>()); |
| resultPrep.get(vcs).add(file); |
| } |
| } |
| } |
| |
| final Map<AbstractVcs, Collection<FilePath>> result = new HashMap<AbstractVcs, Collection<FilePath>>(); |
| for (Map.Entry<AbstractVcs, Collection<FilePath>> entry : resultPrep.entrySet()) { |
| final AbstractVcs vcs = entry.getKey(); |
| final List<FilePath> paths = new ArrayList<FilePath>(entry.getValue()); |
| result.put(vcs, vcs.filterUniqueRoots(paths, ObjectsConvertor.FILEPATH_TO_VIRTUAL)); |
| } |
| |
| return result; |
| } |
| |
| @NotNull |
| private FilePath[] filterRoots(FilePath[] roots, VcsContext vcsContext) { |
| final ArrayList<FilePath> result = new ArrayList<FilePath>(); |
| final Project project = vcsContext.getProject(); |
| for (FilePath file : roots) { |
| AbstractVcs vcs = VcsUtil.getVcsFor(project, file); |
| if (vcs != null) { |
| if (!myScopeInfo.filterExistsInVcs() || AbstractVcs.fileInVcsByFileStatus(project, file)) { |
| UpdateEnvironment updateEnvironment = myActionInfo.getEnvironment(vcs); |
| if (updateEnvironment != null) { |
| result.add(file); |
| } |
| } |
| else { |
| final VirtualFile virtualFile = file.getVirtualFile(); |
| if (virtualFile != null && virtualFile.isDirectory()) { |
| final VirtualFile[] vcsRoots = ProjectLevelVcsManager.getInstance(vcsContext.getProject()).getAllVersionedRoots(); |
| for(VirtualFile vcsRoot: vcsRoots) { |
| if (VfsUtil.isAncestor(virtualFile, vcsRoot, false)) { |
| result.add(file); |
| } |
| } |
| } |
| } |
| } |
| } |
| return result.toArray(new FilePath[result.size()]); |
| } |
| |
| protected abstract boolean filterRootsBeforeAction(); |
| |
| protected void update(VcsContext vcsContext, Presentation presentation) { |
| Project project = vcsContext.getProject(); |
| |
| if (project != null) { |
| final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project); |
| final boolean underVcs = vcsManager.hasActiveVcss(); |
| if (! underVcs) { |
| presentation.setVisible(false); |
| return; |
| } |
| |
| String actionName = getCompleteActionName(vcsContext); |
| if (myActionInfo.showOptions(project) || OptionsDialog.shiftIsPressed(vcsContext.getModifiers())) { |
| actionName += "..."; |
| } |
| |
| presentation.setText(actionName); |
| |
| presentation.setVisible(true); |
| presentation.setEnabled(true); |
| |
| if (supportingVcsesAreEmpty(vcsManager, myActionInfo)) { |
| presentation.setVisible(myAlwaysVisible); |
| presentation.setEnabled(false); |
| return; |
| } |
| |
| if (filterRootsBeforeAction()) { |
| FilePath[] roots = filterRoots(myScopeInfo.getRoots(vcsContext, myActionInfo), vcsContext); |
| if (roots.length == 0) { |
| presentation.setVisible(myAlwaysVisible); |
| presentation.setEnabled(false); |
| return; |
| } |
| } |
| |
| if (presentation.isVisible() && presentation.isEnabled() && |
| vcsManager.isBackgroundVcsOperationRunning()) { |
| presentation.setEnabled(false); |
| } |
| } else { |
| presentation.setVisible(false); |
| presentation.setEnabled(false); |
| } |
| } |
| |
| protected boolean forceSyncUpdate(final AnActionEvent e) { |
| return true; |
| } |
| |
| private static boolean supportingVcsesAreEmpty(final ProjectLevelVcsManager vcsManager, final ActionInfo actionInfo) { |
| final AbstractVcs[] allActiveVcss = vcsManager.getAllActiveVcss(); |
| for (AbstractVcs activeVcs : allActiveVcss) { |
| if (actionInfo.getEnvironment(activeVcs) != null) return false; |
| } |
| return true; |
| } |
| |
| private class Updater extends Task.Backgroundable { |
| private final Project myProject; |
| private final ProjectLevelVcsManagerEx myProjectLevelVcsManager; |
| private UpdatedFiles myUpdatedFiles; |
| private final FilePath[] myRoots; |
| private final Map<AbstractVcs, Collection<FilePath>> myVcsToVirtualFiles; |
| private final Map<HotfixData, List<VcsException>> myGroupedExceptions; |
| private final List<UpdateSession> myUpdateSessions; |
| private int myUpdateNumber; |
| |
| // vcs name, context object |
| private final Map<AbstractVcs, SequentialUpdatesContext> myContextInfo; |
| private final VcsDirtyScopeManager myDirtyScopeManager; |
| |
| private Label myBefore; |
| private Label myAfter; |
| |
| public Updater(final Project project, final FilePath[] roots, final Map<AbstractVcs, Collection<FilePath>> vcsToVirtualFiles) { |
| super(project, getTemplatePresentation().getText(), true, VcsConfiguration.getInstance(project).getUpdateOption()); |
| myProject = project; |
| myProjectLevelVcsManager = ProjectLevelVcsManagerEx.getInstanceEx(project); |
| myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject); |
| myRoots = roots; |
| myVcsToVirtualFiles = vcsToVirtualFiles; |
| |
| myUpdatedFiles = UpdatedFiles.create(); |
| myGroupedExceptions = new HashMap<HotfixData, List<VcsException>>(); |
| myUpdateSessions = new ArrayList<UpdateSession>(); |
| |
| // create from outside without any context; context is created by vcses |
| myContextInfo = new HashMap<AbstractVcs, SequentialUpdatesContext>(); |
| myUpdateNumber = 1; |
| } |
| |
| private void reset() { |
| myUpdatedFiles = UpdatedFiles.create(); |
| myGroupedExceptions.clear(); |
| myUpdateSessions.clear(); |
| ++ myUpdateNumber; |
| } |
| |
| private void suspendIfNeeded() { |
| if (! myActionInfo.canChangeFileStatus()) { |
| // i.e. for update but not for integrate or status |
| ((VcsDirtyScopeManagerImpl) myDirtyScopeManager).suspendMe(); |
| } |
| } |
| |
| private void releaseIfNeeded() { |
| if (! myActionInfo.canChangeFileStatus()) { |
| // i.e. for update but not for integrate or status |
| ((VcsDirtyScopeManagerImpl) myDirtyScopeManager).reanimate(); |
| } |
| } |
| |
| public void run(@NotNull final ProgressIndicator indicator) { |
| suspendIfNeeded(); |
| try { |
| runImpl(); |
| } catch (Throwable t) { |
| releaseIfNeeded(); |
| if (t instanceof Error) { |
| throw ((Error) t); |
| } else if (t instanceof RuntimeException) { |
| throw ((RuntimeException) t); |
| } |
| throw new RuntimeException(t); |
| } |
| } |
| |
| private void runImpl() { |
| ProjectManagerEx.getInstanceEx().blockReloadingProjectOnExternalChanges(); |
| myProjectLevelVcsManager.startBackgroundVcsOperation(); |
| |
| myBefore = LocalHistory.getInstance().putSystemLabel(myProject, "Before update"); |
| |
| ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); |
| |
| try { |
| int toBeProcessed = myVcsToVirtualFiles.size(); |
| int processed = 0; |
| for (AbstractVcs vcs : myVcsToVirtualFiles.keySet()) { |
| final UpdateEnvironment updateEnvironment = myActionInfo.getEnvironment(vcs); |
| updateEnvironment.fillGroups(myUpdatedFiles); |
| Collection<FilePath> files = myVcsToVirtualFiles.get(vcs); |
| |
| final SequentialUpdatesContext context = myContextInfo.get(vcs); |
| final Ref<SequentialUpdatesContext> refContext = new Ref<SequentialUpdatesContext>(context); |
| |
| // actual update |
| UpdateSession updateSession = |
| updateEnvironment.updateDirectories(files.toArray(new FilePath[files.size()]), myUpdatedFiles, progressIndicator, refContext); |
| |
| myContextInfo.put(vcs, refContext.get()); |
| processed++; |
| if (progressIndicator != null) { |
| progressIndicator.setFraction((double)processed / (double)toBeProcessed); |
| progressIndicator.setText2(""); |
| } |
| final List<VcsException> exceptionList = updateSession.getExceptions(); |
| gatherExceptions(vcs, exceptionList); |
| myUpdateSessions.add(updateSession); |
| } |
| } finally { |
| try { |
| ProgressManager.progress(VcsBundle.message("progress.text.synchronizing.files")); |
| doVfsRefresh(); |
| } finally { |
| myProjectLevelVcsManager.stopBackgroundVcsOperation(); |
| if (!myProject.isDisposed()) { |
| myProject.getMessageBus().syncPublisher(UpdatedFilesListener.UPDATED_FILES). |
| consume(UpdatedFilesReverseSide.getPathsFromUpdatedFiles(myUpdatedFiles)); |
| } |
| } |
| } |
| } |
| |
| private void gatherExceptions(final AbstractVcs vcs, final List<VcsException> exceptionList) { |
| final VcsExceptionsHotFixer fixer = vcs.getVcsExceptionsHotFixer(); |
| if (fixer == null) { |
| putExceptions(null, exceptionList); |
| } else { |
| putExceptions(fixer.groupExceptions(ActionType.update, exceptionList)); |
| } |
| } |
| |
| private void putExceptions(final Map<HotfixData, List<VcsException>> map) { |
| for (Map.Entry<HotfixData, List<VcsException>> entry : map.entrySet()) { |
| putExceptions(entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| private void putExceptions(final HotfixData key, @NotNull final List<VcsException> list) { |
| if (list.isEmpty()) return; |
| List<VcsException> exceptionList = myGroupedExceptions.get(key); |
| if (exceptionList == null) { |
| exceptionList = new ArrayList<VcsException>(); |
| myGroupedExceptions.put(key, exceptionList); |
| } |
| exceptionList.addAll(list); |
| } |
| |
| private void doVfsRefresh() { |
| final String actionName = VcsBundle.message("local.history.update.from.vcs"); |
| final LocalHistoryAction action = LocalHistory.getInstance().startAction(actionName); |
| try { |
| LOG.info("Calling refresh files after update for roots: " + Arrays.toString(myRoots)); |
| RefreshVFsSynchronously.updateAllChanged(myUpdatedFiles); |
| notifyAnnotations(); |
| } |
| finally { |
| action.finish(); |
| if ((! myProject.isOpen()) || myProject.isDisposed()) { |
| LocalHistory.getInstance().putSystemLabel(myProject, actionName); |
| } |
| } |
| } |
| |
| private void notifyAnnotations() { |
| final VcsAnnotationRefresher refresher = myProject.getMessageBus().syncPublisher(VcsAnnotationRefresher.LOCAL_CHANGES_CHANGED); |
| UpdateFilesHelper.iterateFileGroupFilesDeletedOnServerFirst(myUpdatedFiles, new UpdateFilesHelper.Callback() { |
| @Override |
| public void onFile(String filePath, String groupId) { |
| refresher.dirty(filePath); |
| } |
| }); |
| } |
| |
| private String prepareNotificationWithUpdateInfo() { |
| StringBuffer text = new StringBuffer(); |
| final List<FileGroup> groups = myUpdatedFiles.getTopLevelGroups(); |
| for (FileGroup group : groups) { |
| appendGroup(text, group); |
| } |
| return text.toString(); |
| } |
| |
| private void appendGroup(final StringBuffer text, final FileGroup group) { |
| final int s = group.getFiles().size(); |
| if (s > 0) { |
| text.append("\n"); |
| text.append(s).append(" ").append(StringUtil.pluralize("File", s)).append(" ").append(group.getUpdateName()); |
| } |
| |
| final List<FileGroup> list = group.getChildren(); |
| for (FileGroup g : list) { |
| appendGroup(text, g); |
| } |
| } |
| |
| public void onSuccess() { |
| try { |
| onSuccessImpl(false); |
| } finally { |
| releaseIfNeeded(); |
| } |
| } |
| |
| private void onSuccessImpl(final boolean wasCanceled) { |
| if ((! myProject.isOpen()) || myProject.isDisposed()) { |
| ProjectManagerEx.getInstanceEx().unblockReloadingProjectOnExternalChanges(); |
| return; |
| } |
| boolean continueChain = false; |
| for (SequentialUpdatesContext context : myContextInfo.values()) { |
| continueChain |= (context != null) && (context.shouldFail()); |
| } |
| final boolean continueChainFinal = continueChain; |
| |
| final boolean someSessionWasCancelled = wasCanceled || someSessionWasCanceled(myUpdateSessions); |
| // here text conflicts might be interactively resolved |
| for (final UpdateSession updateSession : myUpdateSessions) { |
| updateSession.onRefreshFilesCompleted(); |
| } |
| // only after conflicts are resolved, put a label |
| myAfter = LocalHistory.getInstance().putSystemLabel(myProject, "After update"); |
| |
| if (myActionInfo.canChangeFileStatus()) { |
| final List<VirtualFile> files = new ArrayList<VirtualFile>(); |
| final RemoteRevisionsCache revisionsCache = RemoteRevisionsCache.getInstance(myProject); |
| revisionsCache.invalidate(myUpdatedFiles); |
| UpdateFilesHelper.iterateFileGroupFiles(myUpdatedFiles, new UpdateFilesHelper.Callback() { |
| public void onFile(final String filePath, final String groupId) { |
| @NonNls final String path = VfsUtil.pathToUrl(filePath.replace(File.separatorChar, '/')); |
| final VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(path); |
| if (file != null) { |
| files.add(file); |
| } |
| } |
| }); |
| myDirtyScopeManager.filesDirty(files, null); |
| } |
| |
| final boolean updateSuccess = (! someSessionWasCancelled) && (myGroupedExceptions.isEmpty()); |
| |
| WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { |
| public void run() { |
| if (myProject.isDisposed()) { |
| ProjectManagerEx.getInstanceEx().unblockReloadingProjectOnExternalChanges(); |
| return; |
| } |
| if (! myGroupedExceptions.isEmpty()) { |
| if (continueChainFinal) { |
| gatherContextInterruptedMessages(); |
| } |
| AbstractVcsHelper.getInstance(myProject).showErrors(myGroupedExceptions, VcsBundle.message("message.title.vcs.update.errors", |
| getTemplatePresentation().getText())); |
| } else if (someSessionWasCancelled) { |
| ProgressManager.progress(VcsBundle.message("progress.text.updating.canceled")); |
| } else { |
| ProgressManager.progress(VcsBundle.message("progress.text.updating.done")); |
| } |
| |
| final boolean noMerged = myUpdatedFiles.getGroupById(FileGroup.MERGED_WITH_CONFLICT_ID).isEmpty(); |
| if (myUpdatedFiles.isEmpty() && myGroupedExceptions.isEmpty()) { |
| if (someSessionWasCancelled) { |
| VcsBalloonProblemNotifier.showOverChangesView(myProject, VcsBundle.message("progress.text.updating.canceled"), MessageType.WARNING); |
| } else { |
| VcsBalloonProblemNotifier.showOverChangesView(myProject, getAllFilesAreUpToDateMessage(myRoots), MessageType.INFO); |
| } |
| } |
| else if (! myUpdatedFiles.isEmpty()) { |
| final UpdateInfoTree tree = showUpdateTree(continueChainFinal && updateSuccess && noMerged, someSessionWasCancelled); |
| final CommittedChangesCache cache = CommittedChangesCache.getInstance(myProject); |
| cache.processUpdatedFiles(myUpdatedFiles, new Consumer<List<CommittedChangeList>>() { |
| @Override |
| public void consume(List<CommittedChangeList> incomingChangeLists) { |
| tree.setChangeLists(incomingChangeLists); |
| } |
| }); |
| |
| if (someSessionWasCancelled) { |
| VcsBalloonProblemNotifier.showOverChangesView(myProject, "VCS Update Incomplete" + prepareNotificationWithUpdateInfo(), MessageType.WARNING); |
| } else { |
| VcsBalloonProblemNotifier.showOverChangesView(myProject, "VCS Update Finished" + prepareNotificationWithUpdateInfo(), MessageType.INFO); |
| } |
| } |
| |
| ProjectManagerEx.getInstanceEx().unblockReloadingProjectOnExternalChanges(); |
| |
| if (continueChainFinal && updateSuccess) { |
| if (!noMerged) { |
| showContextInterruptedError(); |
| } else { |
| // trigger next update; for CVS when updating from several branches simultaneously |
| reset(); |
| ProgressManager.getInstance().run(Updater.this); |
| } |
| } |
| } |
| }, null, myProject); |
| } |
| |
| private void showContextInterruptedError() { |
| gatherContextInterruptedMessages(); |
| AbstractVcsHelper.getInstance(myProject).showErrors(myGroupedExceptions, |
| VcsBundle.message("message.title.vcs.update.errors", getTemplatePresentation().getText())); |
| } |
| |
| private void gatherContextInterruptedMessages() { |
| for (Map.Entry<AbstractVcs, SequentialUpdatesContext> entry : myContextInfo.entrySet()) { |
| final SequentialUpdatesContext context = entry.getValue(); |
| if ((context == null) || (! context.shouldFail())) continue; |
| final VcsException exception = new VcsException(context.getMessageWhenInterruptedBeforeStart()); |
| gatherExceptions(entry.getKey(), Collections.singletonList(exception)); |
| } |
| } |
| |
| @NotNull |
| private UpdateInfoTree showUpdateTree(final boolean willBeContinued, final boolean wasCanceled) { |
| RestoreUpdateTree restoreUpdateTree = RestoreUpdateTree.getInstance(myProject); |
| restoreUpdateTree.registerUpdateInformation(myUpdatedFiles, myActionInfo); |
| final String text = getTemplatePresentation().getText() + ((willBeContinued || (myUpdateNumber > 1)) ? ("#" + myUpdateNumber) : ""); |
| final UpdateInfoTree updateInfoTree = myProjectLevelVcsManager.showUpdateProjectInfo(myUpdatedFiles, text, myActionInfo, wasCanceled); |
| |
| updateInfoTree.setBefore(myBefore); |
| updateInfoTree.setAfter(myAfter); |
| |
| updateInfoTree.setCanGroupByChangeList(canGroupByChangelist(myVcsToVirtualFiles.keySet())); |
| return updateInfoTree; |
| } |
| |
| public void onCancel() { |
| try { |
| onSuccessImpl(true); |
| } finally { |
| releaseIfNeeded(); |
| } |
| } |
| } |
| } |