blob: bfdadef54cc8b4ccfe6c1f5d2a18665d704df7f9 [file] [log] [blame]
/*
* Copyright 2000-2013 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 org.jetbrains.idea.svn.dialogs;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.AbstractVcsHelper;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.WorkingCopyFormat;
import org.jetbrains.idea.svn.api.ClientFactory;
import org.jetbrains.idea.svn.api.EventAction;
import org.jetbrains.idea.svn.api.ProgressEvent;
import org.jetbrains.idea.svn.api.ProgressTracker;
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNException;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SvnFormatWorker extends Task.Backgroundable {
private static final Logger LOG = Logger.getInstance(SvnFormatWorker.class);
private List<Throwable> myExceptions;
private final Project myProject;
@NotNull private final WorkingCopyFormat myNewFormat;
private final List<WCInfo> myWcInfos;
private List<LocalChangeList> myBeforeChangeLists;
private final SvnVcs myVcs;
public SvnFormatWorker(final Project project, @NotNull final WorkingCopyFormat newFormat, final List<WCInfo> wcInfos) {
super(project, SvnBundle.message("action.change.wcopy.format.task.title"), false, DEAF);
myProject = project;
myNewFormat = newFormat;
myExceptions = new ArrayList<Throwable>();
myWcInfos = wcInfos;
myVcs = SvnVcs.getInstance(myProject);
}
public SvnFormatWorker(final Project project, @NotNull final WorkingCopyFormat newFormat, final WCInfo wcInfo) {
this(project, newFormat, Collections.singletonList(wcInfo));
}
public boolean haveStuffToConvert() {
return ! myWcInfos.isEmpty();
}
@Override
public void onCancel() {
onSuccess();
}
@Override
public void onSuccess() {
if (myProject.isDisposed()) {
return;
}
if (! myExceptions.isEmpty()) {
final List<String> messages = new ArrayList<String>();
for (Throwable exception : myExceptions) {
messages.add(exception.getMessage());
}
AbstractVcsHelper.getInstance(myProject)
.showErrors(Collections.singletonList(new VcsException(messages)), SvnBundle.message("action.change.wcopy.format.task.title"));
}
}
public void run(@NotNull final ProgressIndicator indicator) {
ProjectLevelVcsManager.getInstanceChecked(myProject).startBackgroundVcsOperation();
indicator.setIndeterminate(true);
final boolean supportsChangelists = myNewFormat.supportsChangelists();
if (supportsChangelists) {
myBeforeChangeLists = ChangeListManager.getInstance(myProject).getChangeListsCopy();
}
try {
for (WCInfo wcInfo : myWcInfos) {
File path = new File(wcInfo.getPath());
if (! wcInfo.isIsWcRoot()) {
path = SvnUtil.getWorkingCopyRoot(path);
}
try {
String cleanupMessage = SvnBundle.message("action.Subversion.cleanup.progress.text", path.getAbsolutePath());
String upgradeMessage =
SvnBundle.message("action.change.wcopy.format.task.progress.text", path.getAbsolutePath(), wcInfo.getFormat(), myNewFormat);
ProgressTracker handler = createUpgradeHandler(indicator, cleanupMessage, upgradeMessage);
getFactory(path, myNewFormat).createUpgradeClient().upgrade(path, myNewFormat, handler);
} catch (Throwable e) {
myExceptions.add(e);
}
}
}
finally {
ProjectLevelVcsManager.getInstance(myProject).stopBackgroundVcsOperation();
// to map to native
if (supportsChangelists) {
SvnVcs.getInstance(myProject).processChangeLists(myBeforeChangeLists);
}
ApplicationManager.getApplication().getMessageBus().syncPublisher(SvnVcs.WC_CONVERTED).run();
}
}
@NotNull
private ClientFactory getFactory(@NotNull File path, @NotNull WorkingCopyFormat format) throws VcsException {
ClientFactory factory = myVcs.getFactory(path);
ClientFactory otherFactory = myVcs.getOtherFactory(factory);
List<WorkingCopyFormat> factoryFormats = factory.createUpgradeClient().getSupportedFormats();
List<WorkingCopyFormat> otherFactoryFormats = getOtherFactoryFormats(otherFactory);
return factoryFormats.contains(format) || !otherFactoryFormats.contains(format) ? factory : otherFactory;
}
public static List<WorkingCopyFormat> getOtherFactoryFormats(@NotNull ClientFactory otherFactory) {
List<WorkingCopyFormat> result;
try {
result = otherFactory.createUpgradeClient().getSupportedFormats();
}
catch (VcsException e) {
result = ContainerUtil.newArrayList();
LOG.info("Failed to get upgrade formats from other factory", e);
}
return result;
}
private static ProgressTracker createUpgradeHandler(@NotNull final ProgressIndicator indicator,
@NotNull final String cleanupMessage,
@NotNull final String upgradeMessage) {
return new ProgressTracker() {
@Override
public void consume(ProgressEvent event) throws SVNException {
if (event.getFile() != null) {
if (EventAction.UPGRADED_PATH.equals(event.getAction())) {
indicator.setText2("Upgraded path " + VcsUtil.getPathForProgressPresentation(event.getFile()));
}
// fake event indicating cleanup start
if (EventAction.UPDATE_STARTED.equals(event.getAction())) {
indicator.setText(cleanupMessage);
}
// fake event indicating upgrade start
if (EventAction.UPDATE_COMPLETED.equals(event.getAction())) {
indicator.setText(upgradeMessage);
}
}
}
@Override
public void checkCancelled() throws SVNCancelException {
indicator.checkCanceled();
}
};
}
}