IDEA-26360 (Performance and inconsistency issues with svn:externals and "Detect neste...
[fedora-idea.git] / plugins / cvs / cvs-plugin / src / com / intellij / cvsSupport2 / CvsUpdateEnvironment.java
blobdc937e307807c927cd3ffd67607eb49233fca048
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.cvsSupport2;
18 import com.intellij.cvsSupport2.actions.merge.CvsMergeProvider;
19 import com.intellij.cvsSupport2.actions.update.UpdateSettingsOnCvsConfiguration;
20 import com.intellij.cvsSupport2.config.CvsConfiguration;
21 import com.intellij.cvsSupport2.config.DateOrRevisionSettings;
22 import com.intellij.cvsSupport2.cvsExecution.CvsOperationExecutor;
23 import com.intellij.cvsSupport2.cvsExecution.CvsOperationExecutorCallback;
24 import com.intellij.cvsSupport2.cvshandlers.CommandCvsHandler;
25 import com.intellij.cvsSupport2.cvshandlers.CvsHandler;
26 import com.intellij.cvsSupport2.cvshandlers.CvsUpdatePolicy;
27 import com.intellij.cvsSupport2.cvshandlers.UpdateHandler;
28 import com.intellij.cvsSupport2.updateinfo.UpdatedFilesProcessor;
29 import com.intellij.cvsSupport2.util.CvsVfsUtil;
30 import com.intellij.openapi.application.ApplicationManager;
31 import com.intellij.openapi.application.ModalityState;
32 import com.intellij.openapi.cvsIntegration.CvsResult;
33 import com.intellij.openapi.options.Configurable;
34 import com.intellij.openapi.progress.ProgressIndicator;
35 import com.intellij.openapi.project.Project;
36 import com.intellij.openapi.util.Ref;
37 import com.intellij.openapi.util.io.FileUtil;
38 import com.intellij.openapi.vcs.AbstractVcsHelper;
39 import com.intellij.openapi.vcs.FilePath;
40 import com.intellij.openapi.vcs.VcsKey;
41 import com.intellij.openapi.vcs.update.*;
42 import com.intellij.openapi.vfs.VfsUtil;
43 import com.intellij.openapi.vfs.VirtualFile;
44 import org.jetbrains.annotations.NotNull;
46 import java.io.File;
47 import java.util.ArrayList;
48 import java.util.Collection;
49 import java.util.Collections;
50 import java.util.List;
52 public class CvsUpdateEnvironment implements UpdateEnvironment {
53 private final Project myProject;
54 private boolean myLastUpdateWasConfigured = false;
56 public CvsUpdateEnvironment(Project project) {
57 myProject = project;
61 public void fillGroups(UpdatedFiles updatedFiles) {
62 CvsUpdatePolicy.fillGroups(updatedFiles);
65 private static class CvsSequentialUpdateContext implements SequentialUpdatesContext {
66 private final UpdateSettingsOnCvsConfiguration myConfiguration;
67 private final String myUpdateTagName;
68 private final static String error = "merge.wasnt.started.only.update.was.performed";
70 private CvsSequentialUpdateContext(final UpdateSettingsOnCvsConfiguration configuration, final String tagName) {
71 myUpdateTagName = tagName;
72 myConfiguration = configuration;
75 @NotNull
76 public String getMessageWhenInterruptedBeforeStart() {
77 String mergeString = "-j " + myConfiguration.getBranch1ToMergeWith();
78 if (myConfiguration.getBranch2ToMergeWith() != null) {
79 mergeString += " -j " + myConfiguration.getBranch2ToMergeWith();
81 return "Merge (" + mergeString + ") wasn't started, only update (-r " + myUpdateTagName + ") was performed";
84 public boolean shouldFail() {
85 return true;
88 public UpdateSettingsOnCvsConfiguration getConfiguration() {
89 return myConfiguration;
93 private UpdateSettingsOnCvsConfiguration createSettingsAndUpdateContext(final CvsConfiguration cvsConfiguration,
94 @NotNull final Ref<SequentialUpdatesContext> contextRef) {
95 if (contextRef.get() != null) {
96 final CvsSequentialUpdateContext cvsContext = (CvsSequentialUpdateContext) contextRef.get();
97 contextRef.set(null);
98 return cvsContext.getConfiguration();
101 if ((! cvsConfiguration.CLEAN_COPY) && cvsConfiguration.UPDATE_DATE_OR_REVISION_SETTINGS.overridesDefault() &&
102 (cvsConfiguration.MERGING_MODE != CvsConfiguration.DO_NOT_MERGE)) {
103 // split into 2 updates
104 final UpdateSettingsOnCvsConfiguration secondUpdate = new UpdateSettingsOnCvsConfiguration(
105 cvsConfiguration.PRUNE_EMPTY_DIRECTORIES, cvsConfiguration.MERGING_MODE, cvsConfiguration.MERGE_WITH_BRANCH1_NAME,
106 cvsConfiguration.MERGE_WITH_BRANCH2_NAME, cvsConfiguration.CREATE_NEW_DIRECTORIES, cvsConfiguration.UPDATE_KEYWORD_SUBSTITUTION,
107 new DateOrRevisionSettings(), cvsConfiguration.MAKE_NEW_FILES_READONLY, cvsConfiguration.CLEAN_COPY, cvsConfiguration.RESET_STICKY);
108 contextRef.set(new CvsSequentialUpdateContext(secondUpdate, cvsConfiguration.UPDATE_DATE_OR_REVISION_SETTINGS.asString()));
110 return new UpdateSettingsOnCvsConfiguration(
111 cvsConfiguration.PRUNE_EMPTY_DIRECTORIES, CvsConfiguration.DO_NOT_MERGE, null, null, cvsConfiguration.CREATE_NEW_DIRECTORIES,
112 cvsConfiguration.UPDATE_KEYWORD_SUBSTITUTION, cvsConfiguration.UPDATE_DATE_OR_REVISION_SETTINGS,
113 cvsConfiguration.MAKE_NEW_FILES_READONLY, cvsConfiguration.CLEAN_COPY, cvsConfiguration.RESET_STICKY);
114 } else {
115 // usual way
116 return new UpdateSettingsOnCvsConfiguration(cvsConfiguration, cvsConfiguration.CLEAN_COPY, cvsConfiguration.RESET_STICKY);
120 @NotNull
121 public UpdateSession updateDirectories(@NotNull FilePath[] contentRoots, final UpdatedFiles updatedFiles, ProgressIndicator progressIndicator,
122 @NotNull final Ref<SequentialUpdatesContext> contextRef) {
123 CvsConfiguration cvsConfiguration = CvsConfiguration.getInstance(myProject);
124 if (!myLastUpdateWasConfigured) {
125 cvsConfiguration.CLEAN_COPY = false;
126 cvsConfiguration.RESET_STICKY = false;
128 myLastUpdateWasConfigured = false;
130 try {
131 final UpdateSettingsOnCvsConfiguration updateSettings = createSettingsAndUpdateContext(cvsConfiguration, contextRef);
132 final UpdateHandler handler = CommandCvsHandler.createUpdateHandler(contentRoots, updateSettings, myProject, updatedFiles);
133 handler.addCvsListener(new UpdatedFilesProcessor(myProject, updatedFiles));
134 CvsOperationExecutor cvsOperationExecutor = new CvsOperationExecutor(true, myProject, ModalityState.defaultModalityState());
135 cvsOperationExecutor.setShowErrors(false);
136 cvsOperationExecutor.performActionSync(handler, CvsOperationExecutorCallback.EMPTY);
137 final CvsResult result = cvsOperationExecutor.getResult();
138 return createUpdateSessionAdapter(updatedFiles, result);
140 finally {
141 cvsConfiguration.CLEAN_COPY = false;
142 cvsConfiguration.RESET_STICKY = false;
146 private UpdateSessionAdapter createUpdateSessionAdapter(final UpdatedFiles updatedFiles, final CvsResult result) {
147 return new UpdateSessionAdapter(result.getErrorsAndWarnings(), result.isCanceled()) {
148 public void onRefreshFilesCompleted() {
149 final FileGroup mergedWithConflictsGroup = updatedFiles.getGroupById(FileGroup.MERGED_WITH_CONFLICT_ID);
150 final FileGroup binaryMergedGroup = updatedFiles.getGroupById(CvsUpdatePolicy.BINARY_MERGED_ID);
151 if (!mergedWithConflictsGroup.isEmpty() || !binaryMergedGroup.isEmpty()) {
152 Collection<String> paths = new ArrayList<String>();
153 paths.addAll(mergedWithConflictsGroup.getFiles());
154 paths.addAll(binaryMergedGroup.getFiles());
156 final List<VirtualFile> list = invokeManualMerging(paths, myProject);
157 FileGroup mergedGroup = updatedFiles.getGroupById(FileGroup.MERGED_ID);
158 final VcsKey vcsKey = CvsVcs2.getKey();
159 for(VirtualFile mergedFile: list) {
160 String path = FileUtil.toSystemDependentName(mergedFile.getPresentableUrl());
161 mergedWithConflictsGroup.remove(path);
162 binaryMergedGroup.remove(path);
163 mergedGroup.add(path, vcsKey, null);
170 private static List<VirtualFile> invokeManualMerging(Collection<String> paths, Project project) {
171 final List<VirtualFile> readOnlyFiles = new ArrayList<VirtualFile>();
172 final List<VirtualFile> files = new ArrayList<VirtualFile>();
174 for (final String path : paths) {
175 final VirtualFile virtualFile = CvsVfsUtil.findFileByIoFile(new File(path));
176 if (virtualFile != null) {
177 files.add(virtualFile);
178 if (!virtualFile.isWritable()) {
179 readOnlyFiles.add(virtualFile);
184 if (readOnlyFiles.size() > 0) {
185 final CvsHandler editHandler = CommandCvsHandler.createEditHandler(VfsUtil.toVirtualFileArray(readOnlyFiles),
186 CvsConfiguration.getInstance(project).RESERVED_EDIT);
187 new CvsOperationExecutor(true, project, ModalityState.current()).performActionSync(editHandler, CvsOperationExecutorCallback.EMPTY);
188 ApplicationManager.getApplication().runWriteAction(new Runnable() {
189 public void run() {
190 for(VirtualFile file: readOnlyFiles) {
191 file.refresh(false, false);
197 if (! files.isEmpty()) {
198 return AbstractVcsHelper.getInstance(project).showMergeDialog(files, new CvsMergeProvider());
200 return Collections.emptyList();
204 public Configurable createConfigurable(Collection<FilePath> files) {
205 myLastUpdateWasConfigured = true;
206 CvsConfiguration.getInstance(myProject).CLEAN_COPY = false;
207 CvsConfiguration.getInstance(myProject).RESET_STICKY = false;
208 return new UpdateConfigurable(myProject, files);
211 public boolean validateOptions(final Collection<FilePath> roots) {
212 return true;