Merge branch 'svn1_8_new'

This commit is contained in:
Konstantin Kolosovsky
2013-09-30 14:20:05 +04:00
16 changed files with 419 additions and 47 deletions
@@ -101,6 +101,10 @@ public enum WorkingCopyFormat {
return myFormat;
}
public boolean isOrGreater(@NotNull WorkingCopyFormat format) {
return myVersion.isOrGreaterThan(format.getVersion().major, format.getVersion().minor);
}
@NotNull
public static WorkingCopyFormat from(@NotNull Version version) {
WorkingCopyFormat result = UNKNOWN;
@@ -3,10 +3,17 @@ package org.jetbrains.idea.svn.api;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.WorkingCopyFormat;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
import org.tmatesoft.svn.core.wc.SVNEvent;
import org.tmatesoft.svn.core.wc.SVNEventAction;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
import java.util.Collection;
/**
@@ -56,4 +63,20 @@ public abstract class BaseSvnClient implements SvnClient {
String.format("%s format is not supported. Supported formats are: %s.", format.getName(), StringUtil.join(supported, ",")));
}
}
protected static void callHandler(@Nullable ISVNEventHandler handler, @NotNull SVNEvent event) throws VcsException {
if (handler != null) {
try {
handler.handleEvent(event, 0);
}
catch (SVNException e) {
throw new SvnBindException(e);
}
}
}
@NotNull
protected static SVNEvent createEvent(@NotNull File path, @Nullable SVNEventAction action) {
return new SVNEvent(path, null, null, 0, null, null, null, null, action, null, null, null, null, null, null);
}
}
@@ -22,6 +22,7 @@ import org.jetbrains.idea.svn.portable.SvnWcClientI;
import org.jetbrains.idea.svn.properties.PropertyClient;
import org.jetbrains.idea.svn.revert.RevertClient;
import org.jetbrains.idea.svn.update.RelocateClient;
import org.jetbrains.idea.svn.upgrade.UpgradeClient;
/**
* @author Konstantin Kolosovsky.
@@ -51,6 +52,7 @@ public abstract class ClientFactory {
protected VersionClient myVersionClient;
protected ImportClient myImportClient;
protected ExportClient myExportClient;
protected UpgradeClient myUpgradeClient;
protected ClientFactory(@NotNull SvnVcs vcs) {
myVcs = vcs;
@@ -166,6 +168,11 @@ public abstract class ClientFactory {
return prepare(myExportClient);
}
@NotNull
public UpgradeClient createUpgradeClient() {
return prepare(myUpgradeClient);
}
@NotNull
protected <T extends SvnClient> T prepare(@NotNull T client) {
client.setVcs(myVcs);
@@ -23,6 +23,7 @@ import org.jetbrains.idea.svn.update.UpdateClient;
import org.jetbrains.idea.svn.properties.CmdPropertyClient;
import org.jetbrains.idea.svn.revert.CmdRevertClient;
import org.jetbrains.idea.svn.update.CmdRelocateClient;
import org.jetbrains.idea.svn.upgrade.CmdUpgradeClient;
/**
* @author Konstantin Kolosovsky.
@@ -53,6 +54,7 @@ public class CmdClientFactory extends ClientFactory {
myVersionClient = new CmdVersionClient();
myImportClient = new CmdImportClient();
myExportClient = new CmdExportClient();
myUpgradeClient = new CmdUpgradeClient();
statusClient = new SvnCommandLineStatusClient(myVcs);
infoClient = new SvnCommandLineInfoClient(myVcs);
}
@@ -0,0 +1,21 @@
package org.jetbrains.idea.svn.api;
import org.jetbrains.annotations.NotNull;
import org.tmatesoft.svn.core.SVNURL;
/**
* @author Konstantin Kolosovsky.
*/
public class Repository {
@NotNull private final SVNURL myUrl;
public Repository(@NotNull SVNURL url) {
myUrl = url;
}
@NotNull
public SVNURL getUrl() {
return myUrl;
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient;
import org.jetbrains.idea.svn.properties.SvnKitPropertyClient;
import org.jetbrains.idea.svn.revert.SvnKitRevertClient;
import org.jetbrains.idea.svn.update.SvnKitRelocateClient;
import org.jetbrains.idea.svn.upgrade.SvnKitUpgradeClient;
/**
* @author Konstantin Kolosovsky.
@@ -53,6 +54,7 @@ public class SvnKitClientFactory extends ClientFactory {
myVersionClient = new SvnKitVersionClient();
myImportClient = new SvnKitImportClient();
myExportClient = new SvnKitExportClient();
myUpgradeClient = new SvnKitUpgradeClient();
statusClient = new SvnkitSvnStatusClient(myVcs, null);
infoClient = new SvnkitSvnWcClient(myVcs);
}
@@ -63,6 +63,7 @@ import java.util.concurrent.atomic.AtomicReference;
public class SvnCheckoutProvider implements CheckoutProvider {
public void doCheckout(@NotNull final Project project, Listener listener) {
// TODO: Several dialogs is invoked while dialog.show() - seems code should be rewritten to be more transparent
CheckoutDialog dialog = new CheckoutDialog(project, listener);
dialog.show();
}
@@ -308,8 +309,9 @@ public class SvnCheckoutProvider implements CheckoutProvider {
private WorkingCopyFormat displayUpgradeDialog(@NotNull WorkingCopyFormat defaultSelection) {
final UpgradeFormatDialog dialog = new UpgradeFormatDialog(myProject, myPath, false);
dialog.startLoading();
final ModalityState dialogState = ModalityState.any();
dialog.startLoading();
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
@@ -331,7 +333,7 @@ public class SvnCheckoutProvider implements CheckoutProvider {
dialog.stopLoading();
}
}
}, ModalityState.stateForComponent(dialog.getWindow()));
}, dialogState);
}
});
@@ -24,7 +24,7 @@ import java.util.List;
*/
public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClient {
private static final List<WorkingCopyFormat> SUPPORTED_FORMATS;
public static final List<WorkingCopyFormat> SUPPORTED_FORMATS;
static {
List<WorkingCopyFormat> supportedFormats = new ArrayList<WorkingCopyFormat>();
@@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.RootUrlInfo;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.api.Repository;
import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
@@ -215,19 +216,15 @@ public class CommandUtil {
}
private static SVNURL resolveRepositoryUrl(@NotNull SvnVcs vcs, @NotNull SvnCommandName name, @NotNull SvnTarget target) {
RootUrlInfo rootInfo = target.isFile()
? vcs.getSvnFileUrlMapping().getWcRootForFilePath(target.getFile())
: vcs.getSvnFileUrlMapping().getWcRootForUrl(target.getURL().toDecodedString());
SVNURL repositoryUrl = rootInfo != null ? rootInfo.getRepositoryUrlUrl() : null;
UrlMappingRepositoryProvider urlMappingProvider = new UrlMappingRepositoryProvider(vcs, target);
InfoCommandRepositoryProvider infoCommandProvider = new InfoCommandRepositoryProvider(vcs, target);
// resolve repository url using "svn info" command except the case when that command is executing right now.
if (repositoryUrl == null && !SvnCommandName.info.equals(name)) {
SVNInfo info = getInfo(vcs, target);
repositoryUrl = info != null ? info.getRepositoryRootURL() : null;
Repository repository = urlMappingProvider.get();
if (repository == null && !SvnCommandName.info.equals(name)) {
repository = infoCommandProvider.get();
}
return repositoryUrl;
return repository != null ? repository.getUrl() : null;
}
@NotNull
@@ -296,4 +293,67 @@ public class CommandUtil {
}
return contentsStatus;
}
public interface RepositoryProvider {
@Nullable
Repository get();
}
public static abstract class BaseRepositoryProvider implements RepositoryProvider {
@NotNull protected final SvnVcs myVcs;
@NotNull protected final SvnTarget myTarget;
protected BaseRepositoryProvider(@NotNull SvnVcs vcs, @NotNull SvnTarget target) {
myVcs = vcs;
myTarget = target;
}
}
public static class UrlMappingRepositoryProvider extends BaseRepositoryProvider {
public UrlMappingRepositoryProvider(@NotNull SvnVcs vcs, @NotNull SvnTarget target) {
super(vcs, target);
}
@Nullable
@Override
public Repository get() {
RootUrlInfo rootInfo = null;
if (!myVcs.getProject().isDefault()) {
rootInfo = myTarget.isFile()
? myVcs.getSvnFileUrlMapping().getWcRootForFilePath(myTarget.getFile())
: myVcs.getSvnFileUrlMapping().getWcRootForUrl(myTarget.getURL().toDecodedString());
}
return rootInfo != null ? new Repository(rootInfo.getRepositoryUrlUrl()) : null;
}
}
public static class InfoCommandRepositoryProvider extends BaseRepositoryProvider {
public InfoCommandRepositoryProvider(@NotNull SvnVcs vcs, @NotNull SvnTarget target) {
super(vcs, target);
}
@Nullable
@Override
public Repository get() {
Repository result;
if (myTarget.isURL()) {
// TODO: Also could still execute info when target is url - either to use info for authentication or to just get correct repository
// TODO: url in case of "read" operations are allowed anonymously.
result = new Repository(myTarget.getURL());
}
else {
SVNInfo info = getInfo(myVcs, myTarget);
result = info != null ? new Repository(info.getRepositoryRootURL()) : null;
}
return result;
}
}
}
@@ -49,7 +49,8 @@ public enum SvnCommandName {
lock("lock", true),
unlock("unlock", true),
importFolder("import", false),
export("export", false);
export("export", false),
upgrade("upgrade", true);
private final String myName;
private final boolean myWriteable;
@@ -17,12 +17,14 @@ package org.jetbrains.idea.svn.dialogs;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vcs.ObjectsConvertor;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
@@ -61,11 +63,13 @@ import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.*;
import java.util.List;
public class CopiesPanel {
private static final Logger LOG = Logger.getInstance(CopiesPanel.class);
private final Project myProject;
private MessageBusConnection myConnection;
private SvnVcs myVcs;
@@ -98,6 +102,7 @@ public class CopiesPanel {
@Override
public void run() {
final List<WCInfo> infoList = myVcs.getAllWcInfos();
final List<WorkingCopyFormat> supportedFormats = getSupportedFormats();
Runnable runnable = new Runnable() {
@Override
public void run() {
@@ -117,7 +122,7 @@ public class CopiesPanel {
myCurrentInfoList = newList;
}
Collections.sort(infoList, WCComparator.getInstance());
updateList(infoList);
updateList(infoList, supportedFormats);
myRefreshLabel.setEnabled(true);
SwingUtilities.invokeLater(focus);
}
@@ -178,7 +183,7 @@ public class CopiesPanel {
return myRefreshLabel;
}
private void updateList(final List<WCInfo> infoList) {
private void updateList(@NotNull final List<WCInfo> infoList, @NotNull final List<WorkingCopyFormat> supportedFormats) {
myPanel.removeAll();
final Insets nullIndent = new Insets(1, 3, 1, 0);
final GridBagConstraints gb =
@@ -217,7 +222,7 @@ public class CopiesPanel {
SVNDepth.INFINITY, false, null, wcInfo.getFormat());
}
} else if (CHANGE_FORMAT.equals(e.getDescription())) {
changeFormat(wcInfo);
changeFormat(wcInfo, supportedFormats);
} else if (MERGE_FROM.equals(e.getDescription())) {
if (! checkRoot(root, wcInfo.getPath(), " invoke Merge From")) return;
mergeFrom(wcInfo, root, editorPane);
@@ -237,7 +242,7 @@ public class CopiesPanel {
}
});
editorPane.setBorder(null);
editorPane.setText(formatWc(wcInfo));
editorPane.setText(formatWc(wcInfo, supportedFormats));
final JPanel copyPanel = new JPanel(new GridBagLayout());
@@ -263,14 +268,14 @@ public class CopiesPanel {
}
@SuppressWarnings("MethodMayBeStatic")
private String formatWc(WCInfo info) {
private String formatWc(@NotNull WCInfo info, @NotNull List<WorkingCopyFormat> supportedFormats) {
final StringBuilder sb = new StringBuilder().append("<html><head>").append(UIUtil.getCssFontDeclaration(UIUtil.getLabelFont()))
.append("</head><body><table bgColor=\"").append(ColorUtil.toHex(UIUtil.getPanelBackground())).append("\">");
sb.append("<tr valign=\"top\"><td colspan=\"3\"><b>").append(info.getPath()).append("</b></td></tr>");
sb.append("<tr valign=\"top\"><td>URL:</td><td colspan=\"2\">").append(info.getRootUrl()).append("</td></tr>");
if (! WorkingCopyFormat.ONE_DOT_SEVEN.equals(info.getFormat())) {
// can convert
Collection<WorkingCopyFormat> upgradeFormats = getUpgradeFormats(info, supportedFormats);
if (upgradeFormats.size() > 1) {
sb.append("<tr valign=\"top\"><td>Format:</td><td>").append(info.getFormat().getName()).append("</td><td><a href=\"").
append(CHANGE_FORMAT).append("\">Change</a></td></tr>");
} else {
@@ -302,6 +307,33 @@ public class CopiesPanel {
return sb.toString();
}
@NotNull
private List<WorkingCopyFormat> getSupportedFormats() {
List<WorkingCopyFormat> result = Collections.emptyList();
try {
result = myVcs.getFactory().createUpgradeClient().getSupportedFormats();
}
catch (VcsException e) {
LOG.info(e);
}
return result;
}
public static Set<WorkingCopyFormat> getUpgradeFormats(@NotNull WCInfo info, @NotNull List<WorkingCopyFormat> supportedFormats) {
Set<WorkingCopyFormat> canUpgradeTo = EnumSet.noneOf(WorkingCopyFormat.class);
for (WorkingCopyFormat format : supportedFormats) {
if (format.isOrGreater(info.getFormat())) {
canUpgradeTo.add(format);
}
}
canUpgradeTo.add(info.getFormat());
return canUpgradeTo;
}
private void mergeFrom(@NotNull final WCInfo wcInfo, @NotNull final VirtualFile root, @Nullable final Component mergeLabel) {
SelectBranchPopup.showForBranchRoot(myProject, root, new SelectBranchPopup.BranchSelectedCallback() {
@Override
@@ -338,8 +370,10 @@ public class CopiesPanel {
});
}
private void changeFormat(final WCInfo wcInfo) {
private void changeFormat(@NotNull final WCInfo wcInfo, @NotNull final List<WorkingCopyFormat> supportedFormats) {
ChangeFormatDialog dialog = new ChangeFormatDialog(myProject, new File(wcInfo.getPath()), false, ! wcInfo.isIsWcRoot());
dialog.setSupported(supportedFormats);
dialog.setData(wcInfo.getFormat());
dialog.show();
if (! dialog.isOK()) {
@@ -37,7 +37,6 @@ import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
import org.tmatesoft.svn.core.wc.SVNEvent;
import org.tmatesoft.svn.core.wc.SVNEventAction;
import org.tmatesoft.svn.core.wc.SVNWCClient;
import java.io.File;
import java.util.ArrayList;
@@ -122,20 +121,7 @@ public class SvnFormatWorker extends Task.Backgroundable {
if (supportsChangelists) {
myBeforeChangeLists = ChangeListManager.getInstance(myProject).getChangeListsCopy();
}
final SVNWCClient wcClient = myVcs.createWCClient();
wcClient.setEventHandler(new ISVNEventHandler() {
@Override
public void handleEvent(SVNEvent event, double progress) throws SVNException {
if (SVNEventAction.UPGRADED_PATH.equals(event.getAction()) && event.getFile() != null) {
indicator.setText2("Upgraded path " + VcsUtil.getPathForProgressPresentation(event.getFile()));
}
}
@Override
public void checkCancelled() throws SVNCancelException {
indicator.checkCanceled();
}
});
try {
for (WCInfo wcInfo : myWcInfos) {
File path = new File(wcInfo.getPath());
@@ -143,13 +129,13 @@ public class SvnFormatWorker extends Task.Backgroundable {
path = SvnUtil.getWorkingCopyRoot(path);
}
try {
if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(myNewFormat)) {
indicator.setText(SvnBundle.message("action.Subversion.cleanup.progress.text", path.getAbsolutePath()));
wcClient.doCleanup(path);
}
indicator.setText(SvnBundle.message("action.change.wcopy.format.task.progress.text", path.getAbsolutePath(),
SvnUtil.formatRepresentation(wcInfo.getFormat()), SvnUtil.formatRepresentation(myNewFormat)));
wcClient.doSetWCFormat(path, myNewFormat.getFormat());
String cleanupMessage = SvnBundle.message("action.Subversion.cleanup.progress.text", path.getAbsolutePath());
String upgradeMessage = SvnBundle.message("action.change.wcopy.format.task.progress.text", path.getAbsolutePath(),
SvnUtil.formatRepresentation(wcInfo.getFormat()),
SvnUtil.formatRepresentation(myNewFormat));
ISVNEventHandler handler = createUpgradeHandler(indicator, cleanupMessage, upgradeMessage);
myVcs.getFactory(path).createUpgradeClient().upgrade(path, myNewFormat, handler);
} catch (Throwable e) {
myExceptions.add(e);
}
@@ -166,4 +152,32 @@ public class SvnFormatWorker extends Task.Backgroundable {
ApplicationManager.getApplication().getMessageBus().syncPublisher(SvnVcs.WC_CONVERTED).run();
}
}
private static ISVNEventHandler createUpgradeHandler(@NotNull final ProgressIndicator indicator,
@NotNull final String cleanupMessage,
@NotNull final String upgradeMessage) {
return new ISVNEventHandler() {
@Override
public void handleEvent(SVNEvent event, double progress) throws SVNException {
if (event.getFile() != null) {
if (SVNEventAction.UPGRADED_PATH.equals(event.getAction())) {
indicator.setText2("Upgraded path " + VcsUtil.getPathForProgressPresentation(event.getFile()));
}
// fake event indicating cleanup start
if (SVNEventAction.UPDATE_STARTED.equals(event.getAction())) {
indicator.setText(cleanupMessage);
}
// fake event indicating upgrade start
if (SVNEventAction.UPDATE_COMPLETED.equals(event.getAction())) {
indicator.setText(upgradeMessage);
}
}
}
@Override
public void checkCancelled() throws SVNCancelException {
indicator.checkCanceled();
}
};
}
}
@@ -60,8 +60,7 @@ public class CmdRevertClient extends BaseSvnClient implements RevertClient {
String statusMessage = matcher.group(1);
String path = matcher.group(2);
return new SVNEvent(new File(path), null, null, 0, null, null, null, null, createAction(statusMessage), null, null, null, null, null,
null);
return createEvent(new File(path), createAction(statusMessage));
}
@Nullable
@@ -0,0 +1,118 @@
package org.jetbrains.idea.svn.upgrade;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.util.containers.Convertor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.WorkingCopyFormat;
import org.jetbrains.idea.svn.api.BaseSvnClient;
import org.jetbrains.idea.svn.api.FileStatusResultParser;
import org.jetbrains.idea.svn.commandLine.CommandUtil;
import org.jetbrains.idea.svn.commandLine.LineCommandListener;
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
import org.tmatesoft.svn.core.wc.SVNEvent;
import org.tmatesoft.svn.core.wc.SVNEventAction;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Konstantin Kolosovsky.
*/
public class CmdUpgradeClient extends BaseSvnClient implements UpgradeClient {
private static final String STATUS = "\\s*(.+?)\\s*";
private static final String PATH = "\\s*\'(.*?)\'\\s*";
private static final Pattern CHANGED_PATH = Pattern.compile(STATUS + PATH);
@Override
public void upgrade(@NotNull File path, @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException {
validateFormat(format, getSupportedFormats());
// fake event indicating upgrade start
callHandler(handler, createEvent(path, SVNEventAction.UPDATE_COMPLETED));
List<String> parameters = new ArrayList<String>();
CommandUtil.put(parameters, path);
// TODO: Add general possibility to invoke "handler.checkCancelled" (process should be killed). But currently upgrade process is not
// TODO: cancellable from UI - and this makes sense.
// for 1.8 - no output
// for 1.7 - output in format "Upgraded '<path>'"
FileStatusResultParser parser = new FileStatusResultParser(CHANGED_PATH, handler, new UpgradeStatusConvertor());
UpgradeLineCommandListener listener = new UpgradeLineCommandListener(parser);
CommandUtil.execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.upgrade, parameters, listener);
listener.throwIfException();
}
@Override
public List<WorkingCopyFormat> getSupportedFormats() throws VcsException {
List<WorkingCopyFormat> result = new ArrayList<WorkingCopyFormat>();
result.add(WorkingCopyFormat.from(myFactory.createVersionClient().getVersion()));
return result;
}
private static class UpgradeStatusConvertor implements Convertor<Matcher, SVNEvent> {
public SVNEvent convert(@NotNull Matcher matcher) {
String statusMessage = matcher.group(1);
String path = matcher.group(2);
return createEvent(new File(path), createAction(statusMessage));
}
@Nullable
public static SVNEventAction createAction(@NotNull String code) {
SVNEventAction result = null;
if ("Upgraded".equals(code)) {
result = SVNEventAction.UPGRADED_PATH;
}
return result;
}
}
private static class UpgradeLineCommandListener extends LineCommandListener {
@NotNull private final FileStatusResultParser parser;
@NotNull private final AtomicReference<VcsException> exception;
private UpgradeLineCommandListener(@NotNull FileStatusResultParser parser) {
this.parser = parser;
exception = new AtomicReference<VcsException>();
}
@Override
public void onLineAvailable(String line, Key outputType) {
if (ProcessOutputTypes.STDOUT.equals(outputType)) {
try {
parser.onLine(line);
}
catch (VcsException e) {
exception.set(e);
}
}
}
public void throwIfException() throws VcsException {
VcsException e = exception.get();
if (e != null) {
throw e;
}
}
}
}
@@ -0,0 +1,64 @@
package org.jetbrains.idea.svn.upgrade;
import com.intellij.openapi.vcs.VcsException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.WorkingCopyFormat;
import org.jetbrains.idea.svn.api.BaseSvnClient;
import org.jetbrains.idea.svn.checkout.SvnKitCheckoutClient;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
import org.tmatesoft.svn.core.wc.SVNEventAction;
import org.tmatesoft.svn.core.wc.SVNWCClient;
import java.io.File;
import java.util.List;
/**
* @author Konstantin Kolosovsky.
*/
public class SvnKitUpgradeClient extends BaseSvnClient implements UpgradeClient {
@Override
public void upgrade(@NotNull File path, @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException {
validateFormat(format, getSupportedFormats());
SVNWCClient client = myVcs.createWCClient();
client.setEventHandler(handler);
try {
cleanupIfNecessary(path, format, client, handler);
upgrade(path, format, client, handler);
}
catch (SVNException e) {
throw new SvnBindException(e);
}
}
@Override
public List<WorkingCopyFormat> getSupportedFormats() throws VcsException {
return SvnKitCheckoutClient.SUPPORTED_FORMATS;
}
private static void cleanupIfNecessary(@NotNull File path,
@NotNull WorkingCopyFormat format,
@NotNull SVNWCClient client,
@Nullable ISVNEventHandler handler) throws SVNException, VcsException {
// cleanup is executed only for SVNKit as it could handle both 1.6 and 1.7 formats
if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
// fake event indicating cleanup start
callHandler(handler, createEvent(path, SVNEventAction.UPDATE_STARTED));
client.doCleanup(path);
}
}
private static void upgrade(@NotNull File path,
@NotNull WorkingCopyFormat format,
@NotNull SVNWCClient client,
@Nullable ISVNEventHandler handler) throws SVNException, VcsException {
// fake event indicating upgrade start
callHandler(handler, createEvent(path, SVNEventAction.UPDATE_COMPLETED));
client.doSetWCFormat(path, format.getFormat());
}
}
@@ -0,0 +1,21 @@
package org.jetbrains.idea.svn.upgrade;
import com.intellij.openapi.vcs.VcsException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.WorkingCopyFormat;
import org.jetbrains.idea.svn.api.SvnClient;
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
import java.io.File;
import java.util.List;
/**
* @author Konstantin Kolosovsky.
*/
public interface UpgradeClient extends SvnClient {
void upgrade(@NotNull File path, @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException;
List<WorkingCopyFormat> getSupportedFormats() throws VcsException;
}