mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'svn1_8_new'
This commit is contained in:
@@ -18,11 +18,10 @@ package org.jetbrains.idea.svn;
|
||||
import com.intellij.openapi.vcs.EditFileProvider;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNProperty;
|
||||
import org.jetbrains.idea.svn.properties.PropertyClient;
|
||||
import org.tmatesoft.svn.core.wc.SVNPropertyData;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNWCClient;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -38,18 +37,16 @@ public class SvnEditFileProvider implements EditFileProvider {
|
||||
|
||||
public void editFiles(VirtualFile[] files) throws VcsException {
|
||||
File[] ioFiles = new File[files.length];
|
||||
SVNWCClient client = myVCS.createWCClient();
|
||||
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
ioFiles[i] = new File(files[i].getPath());
|
||||
try {
|
||||
SVNPropertyData property = client
|
||||
.doGetProperty(ioFiles[i], SVNProperty.NEEDS_LOCK, SVNRevision.WORKING, SVNRevision.WORKING);
|
||||
if (property == null || property.getValue() == null) {
|
||||
throw new VcsException(SvnBundle.message("exception.text.file.miss.svn", ioFiles[i].getName()));
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
|
||||
PropertyClient client = myVCS.getFactory(ioFiles[i]).createPropertyClient();
|
||||
SVNPropertyData property = client.getProperty(SvnTarget.fromFile(ioFiles[i], SVNRevision.WORKING), SvnPropertyKeys.SVN_NEEDS_LOCK,
|
||||
false, SVNRevision.WORKING);
|
||||
|
||||
if (property == null || property.getValue() == null) {
|
||||
throw new VcsException(SvnBundle.message("exception.text.file.miss.svn", ioFiles[i].getName()));
|
||||
}
|
||||
}
|
||||
SvnUtil.doLockFiles(myVCS.getProject(), myVCS, ioFiles);
|
||||
|
||||
@@ -143,12 +143,18 @@ public class SvnRecursiveStatusWalker {
|
||||
}
|
||||
|
||||
public SvnStatusClientI getClient(final File file) {
|
||||
// TODO: refactor to ClientFactory usage but carefully save all parameters passed in myClient - fileProvider and
|
||||
// TODO: event handler (for cancel support)
|
||||
WorkingCopyFormat format = myVcs.getWorkingCopyFormat(file);
|
||||
|
||||
if (format == WorkingCopyFormat.ONE_DOT_EIGHT) {
|
||||
return myCommandLineClient;
|
||||
}
|
||||
|
||||
if (format == WorkingCopyFormat.ONE_DOT_SIX) {
|
||||
return mySvnClient;
|
||||
}
|
||||
|
||||
// check format
|
||||
if (CheckJavaHL.isPresent() && SvnConfiguration.UseAcceleration.javaHL.equals(myConfiguration17.myUseAcceleration) &&
|
||||
Svn17Detector.is17(myProject, file)) {
|
||||
|
||||
@@ -30,7 +30,10 @@ import com.intellij.openapi.vcs.AbstractVcsHelper;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangesUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.wm.impl.status.StatusBarUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
@@ -55,6 +58,8 @@ import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SvnUtil {
|
||||
// TODO: ASP.NET hack behavior should be supported - http://svn.apache.org/repos/asf/subversion/trunk/notes/asp-dot-net-hack.txt
|
||||
@@ -66,8 +71,25 @@ public class SvnUtil {
|
||||
@NonNls public static final String PATH_TO_LOCK_FILE = SVN_ADMIN_DIR_NAME + "/lock";
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnUtil");
|
||||
|
||||
public static final Pattern ERROR_PATTERN = Pattern.compile("^svn: (E(\\d+)): (.*)$", Pattern.MULTILINE);
|
||||
public static final Pattern WARNING_PATTERN = Pattern.compile("^svn: warning: (W(\\d+)): (.*)$", Pattern.MULTILINE);
|
||||
|
||||
private SvnUtil() { }
|
||||
|
||||
@Nullable
|
||||
public static SVNErrorMessage parseWarning(@NotNull String text) {
|
||||
Matcher matcher = WARNING_PATTERN.matcher(text);
|
||||
SVNErrorMessage error = null;
|
||||
|
||||
// currently treating only first warning
|
||||
if (matcher.find()) {
|
||||
error = SVNErrorMessage
|
||||
.create(SVNErrorCode.getErrorCode(Integer.parseInt(matcher.group(2))), matcher.group(3), SVNErrorMessage.TYPE_WARNING);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
public static boolean isSvnVersioned(final Project project, File parent) {
|
||||
final SVNInfo info = SvnVcs.getInstance(project).getInfo(parent);
|
||||
|
||||
@@ -145,7 +167,7 @@ public class SvnUtil {
|
||||
force = false;
|
||||
}
|
||||
|
||||
final SVNException[] exception = new SVNException[1];
|
||||
final VcsException[] exception = new VcsException[1];
|
||||
final Collection<String> failedLocks = new ArrayList<String>();
|
||||
final int[] count = new int[]{ioFiles.length};
|
||||
final ISVNEventHandler eventHandler = new ISVNEventHandler() {
|
||||
@@ -165,11 +187,8 @@ public class SvnUtil {
|
||||
Runnable command = new Runnable() {
|
||||
public void run() {
|
||||
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
|
||||
SVNWCClient wcClient;
|
||||
|
||||
try {
|
||||
wcClient = activeVcs.createWCClient();
|
||||
wcClient.setEventHandler(eventHandler);
|
||||
if (progress != null) {
|
||||
progress.setText(SvnBundle.message("progress.text.locking.files"));
|
||||
}
|
||||
@@ -180,10 +199,10 @@ public class SvnUtil {
|
||||
if (progress != null) {
|
||||
progress.setText2(SvnBundle.message("progress.text2.processing.file", ioFile.getName()));
|
||||
}
|
||||
wcClient.doLock(new File[]{ioFile}, force, lockMessage);
|
||||
activeVcs.getFactory(ioFile).createLockClient().lock(ioFile, force, lockMessage, eventHandler);
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
catch (VcsException e) {
|
||||
exception[0] = e;
|
||||
}
|
||||
}
|
||||
@@ -207,13 +226,13 @@ public class SvnUtil {
|
||||
|
||||
StatusBarUtil.setStatusBarInfo(project, SvnBundle.message("message.text.files.locked", count[0]));
|
||||
if (exception[0] != null) {
|
||||
throw new VcsException(exception[0]);
|
||||
throw exception[0];
|
||||
}
|
||||
}
|
||||
|
||||
public static void doUnlockFiles(Project project, final SvnVcs activeVcs, final File[] ioFiles) throws VcsException {
|
||||
final boolean force = true;
|
||||
final SVNException[] exception = new SVNException[1];
|
||||
final VcsException[] exception = new VcsException[1];
|
||||
final Collection<String> failedUnlocks = new ArrayList<String>();
|
||||
final int[] count = new int[]{ioFiles.length};
|
||||
final ISVNEventHandler eventHandler = new ISVNEventHandler() {
|
||||
@@ -233,11 +252,8 @@ public class SvnUtil {
|
||||
Runnable command = new Runnable() {
|
||||
public void run() {
|
||||
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
|
||||
SVNWCClient wcClient;
|
||||
|
||||
try {
|
||||
wcClient = activeVcs.createWCClient();
|
||||
wcClient.setEventHandler(eventHandler);
|
||||
if (progress != null) {
|
||||
progress.setText(SvnBundle.message("progress.text.unlocking.files"));
|
||||
}
|
||||
@@ -248,10 +264,10 @@ public class SvnUtil {
|
||||
if (progress != null) {
|
||||
progress.setText2(SvnBundle.message("progress.text2.processing.file", ioFile.getName()));
|
||||
}
|
||||
wcClient.doUnlock(new File[]{ioFile}, force);
|
||||
activeVcs.getFactory(ioFile).createLockClient().unlock(ioFile, force, eventHandler);
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
catch (VcsException e) {
|
||||
exception[0] = e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
public boolean checkCommandLineVersion() {
|
||||
boolean isValid = true;
|
||||
|
||||
if (SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration.myUseAcceleration) || isProject18()) {
|
||||
if (!isProject16() && (SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration.myUseAcceleration) || isProject18())) {
|
||||
isValid = myChecker.checkExecutableAndNotifyIfNeeded();
|
||||
}
|
||||
|
||||
@@ -892,7 +892,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
public boolean fileExistsInVcs(FilePath path) {
|
||||
File file = path.getIOFile();
|
||||
try {
|
||||
SVNStatus status = createStatusClient().doStatus(file, false);
|
||||
SVNStatus status = getFactory(file).createStatusClient().doStatus(file, false);
|
||||
if (status != null) {
|
||||
if (svnStatusIs(status, SVNStatusType.STATUS_ADDED)) {
|
||||
return status.isCopied();
|
||||
@@ -903,7 +903,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
LOG.info(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1341,10 +1341,20 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
}
|
||||
|
||||
public boolean isProject18() {
|
||||
return WorkingCopyFormat.ONE_DOT_EIGHT.equals(getWorkingCopyFormat(new File(getProject().getBaseDir().getPath())));
|
||||
return WorkingCopyFormat.ONE_DOT_EIGHT.equals(getProjectRootFormat());
|
||||
}
|
||||
|
||||
public boolean isProject16() {
|
||||
return WorkingCopyFormat.ONE_DOT_SIX.equals(getProjectRootFormat());
|
||||
}
|
||||
|
||||
private WorkingCopyFormat getProjectRootFormat() {
|
||||
return getWorkingCopyFormat(new File(getProject().getBaseDir().getPath()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects appropriate client factory based on project root directory working copy format.
|
||||
*
|
||||
* Try to avoid usages of this method (for now) as it could not correctly for all cases
|
||||
* detect svn 1.8 working copy format to guarantee command line client.
|
||||
*
|
||||
@@ -1355,18 +1365,23 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
*/
|
||||
@NotNull
|
||||
public ClientFactory getFactory() {
|
||||
// check working copy format of project directory
|
||||
return isProject18() ? cmdClientFactory : getFactoryFromSettings();
|
||||
return getFactory(getProjectRootFormat(), false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClientFactory getFactory(@NotNull File file) {
|
||||
WorkingCopyFormat format = getWorkingCopyFormat(file);
|
||||
return getFactory(getWorkingCopyFormat(file), true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ClientFactory getFactory(@NotNull WorkingCopyFormat format, boolean useProjectRootForUnknown) {
|
||||
boolean is18 = WorkingCopyFormat.ONE_DOT_EIGHT.equals(format);
|
||||
boolean is16 = WorkingCopyFormat.ONE_DOT_SIX.equals(format);
|
||||
boolean isUnknown = WorkingCopyFormat.UNKNOWN.equals(format);
|
||||
|
||||
return is18 ? cmdClientFactory : (isUnknown ? getFactory() : getFactoryFromSettings());
|
||||
return is18
|
||||
? cmdClientFactory
|
||||
: (is16 ? svnKitClientFactory : (useProjectRootForUnknown && isUnknown ? getFactory() : getFactoryFromSettings()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1375,7 +1390,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ClientFactory getFactoryFromSettings() {
|
||||
public ClientFactory getFactoryFromSettings() {
|
||||
return myConfiguration.myUseAcceleration.equals(SvnConfiguration.UseAcceleration.commandLine) ? cmdClientFactory : svnKitClientFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.dialogs.SetPropertyDialog;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.jetbrains.idea.svn.properties.PropertyClient;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNPropertyValue;
|
||||
import org.tmatesoft.svn.core.wc.SVNWCClient;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -73,15 +73,13 @@ public class SetPropertyAction extends BasicAction {
|
||||
String value = dialog.getPropertyValue();
|
||||
boolean recursive = dialog.isRecursive();
|
||||
|
||||
SVNWCClient wcClient = activeVcs.createWCClient();
|
||||
for (int i = 0; i < ioFiles.length; i++) {
|
||||
File ioFile = ioFiles[i];
|
||||
try {
|
||||
wcClient.doSetProperty(ioFile, name, SVNPropertyValue.create(value), false, recursive, null);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
PropertyClient client = activeVcs.getFactory(ioFile).createPropertyClient();
|
||||
|
||||
// TODO: most likely SVNDepth.getInfinityOrEmptyDepth should be used instead of SVNDepth.fromRecursive - to have either "infinity"
|
||||
// TODO: or "empty" depth, and not "infinity" or "files" depth. But previous logic used SVNDepth.fromRecursive implicitly
|
||||
client.setProperty(ioFile, name, SVNPropertyValue.create(value), SVNDepth.fromRecurse(recursive), false);
|
||||
}
|
||||
for(int i = 0; i < file.length; i++) {
|
||||
if (recursive && file[i].isDirectory()) {
|
||||
|
||||
@@ -5,12 +5,14 @@ import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.add.AddClient;
|
||||
import org.jetbrains.idea.svn.annotate.AnnotateClient;
|
||||
import org.jetbrains.idea.svn.change.ChangeListClient;
|
||||
import org.jetbrains.idea.svn.checkout.CheckoutClient;
|
||||
import org.jetbrains.idea.svn.conflict.ConflictClient;
|
||||
import org.jetbrains.idea.svn.content.ContentClient;
|
||||
import org.jetbrains.idea.svn.copy.CopyMoveClient;
|
||||
import org.jetbrains.idea.svn.delete.DeleteClient;
|
||||
import org.jetbrains.idea.svn.history.HistoryClient;
|
||||
import org.jetbrains.idea.svn.integrate.MergeClient;
|
||||
import org.jetbrains.idea.svn.lock.LockClient;
|
||||
import org.jetbrains.idea.svn.portable.SvnStatusClientI;
|
||||
import org.jetbrains.idea.svn.portable.SvnWcClientI;
|
||||
import org.jetbrains.idea.svn.properties.PropertyClient;
|
||||
@@ -37,6 +39,8 @@ public abstract class ClientFactory {
|
||||
protected PropertyClient propertyClient;
|
||||
protected MergeClient mergeClient;
|
||||
protected ChangeListClient changeListClient;
|
||||
protected CheckoutClient checkoutClient;
|
||||
protected LockClient myLockClient;
|
||||
|
||||
protected ClientFactory(@NotNull SvnVcs vcs) {
|
||||
myVcs = vcs;
|
||||
@@ -112,6 +116,16 @@ public abstract class ClientFactory {
|
||||
return prepare(changeListClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CheckoutClient createCheckoutClient() {
|
||||
return prepare(checkoutClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LockClient createLockClient() {
|
||||
return prepare(myLockClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected <T extends SvnClient> T prepare(@NotNull T client) {
|
||||
client.setVcs(myVcs);
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.add.CmdAddClient;
|
||||
import org.jetbrains.idea.svn.annotate.CmdAnnotateClient;
|
||||
import org.jetbrains.idea.svn.change.CmdChangeListClient;
|
||||
import org.jetbrains.idea.svn.checkout.CmdCheckoutClient;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
|
||||
import org.jetbrains.idea.svn.conflict.CmdConflictClient;
|
||||
@@ -13,6 +14,7 @@ import org.jetbrains.idea.svn.copy.CmdCopyMoveClient;
|
||||
import org.jetbrains.idea.svn.delete.CmdDeleteClient;
|
||||
import org.jetbrains.idea.svn.history.CmdHistoryClient;
|
||||
import org.jetbrains.idea.svn.integrate.CmdMergeClient;
|
||||
import org.jetbrains.idea.svn.lock.CmdLockClient;
|
||||
import org.jetbrains.idea.svn.properties.CmdPropertyClient;
|
||||
import org.jetbrains.idea.svn.revert.CmdRevertClient;
|
||||
|
||||
@@ -38,6 +40,8 @@ public class CmdClientFactory extends ClientFactory {
|
||||
propertyClient = new CmdPropertyClient();
|
||||
mergeClient = new CmdMergeClient();
|
||||
changeListClient = new CmdChangeListClient();
|
||||
checkoutClient = new CmdCheckoutClient();
|
||||
myLockClient = new CmdLockClient();
|
||||
statusClient = new SvnCommandLineStatusClient(myVcs.getProject());
|
||||
infoClient = new SvnCommandLineInfoClient(myVcs.getProject());
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.add.SvnKitAddClient;
|
||||
import org.jetbrains.idea.svn.annotate.SvnKitAnnotateClient;
|
||||
import org.jetbrains.idea.svn.change.SvnKitChangeListClient;
|
||||
import org.jetbrains.idea.svn.checkout.SvnKitCheckoutClient;
|
||||
import org.jetbrains.idea.svn.conflict.SvnKitConflictClient;
|
||||
import org.jetbrains.idea.svn.content.SvnKitContentClient;
|
||||
import org.jetbrains.idea.svn.copy.SvnKitCopyMoveClient;
|
||||
import org.jetbrains.idea.svn.delete.SvnKitDeleteClient;
|
||||
import org.jetbrains.idea.svn.history.SvnKitHistoryClient;
|
||||
import org.jetbrains.idea.svn.integrate.SvnKitMergeClient;
|
||||
import org.jetbrains.idea.svn.lock.SvnKitLockClient;
|
||||
import org.jetbrains.idea.svn.portable.SvnkitSvnStatusClient;
|
||||
import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient;
|
||||
import org.jetbrains.idea.svn.properties.SvnKitPropertyClient;
|
||||
@@ -38,6 +40,8 @@ public class SvnKitClientFactory extends ClientFactory {
|
||||
propertyClient = new SvnKitPropertyClient();
|
||||
mergeClient = new SvnKitMergeClient();
|
||||
changeListClient = new SvnKitChangeListClient();
|
||||
checkoutClient = new SvnKitCheckoutClient();
|
||||
myLockClient = new SvnKitLockClient();
|
||||
statusClient = new SvnkitSvnStatusClient(myVcs.createStatusClient());
|
||||
infoClient = new SvnkitSvnWcClient(myVcs);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.jetbrains.idea.svn.checkout;
|
||||
|
||||
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.SVNDepth;
|
||||
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface CheckoutClient extends SvnClient {
|
||||
|
||||
void checkout(@NotNull SvnTarget source,
|
||||
@NotNull File destination,
|
||||
@Nullable SVNRevision revision,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean ignoreExternals,
|
||||
@Nullable WorkingCopyFormat format,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.jetbrains.idea.svn.checkout;
|
||||
|
||||
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.commandLine.BaseUpdateCommandListener;
|
||||
import org.jetbrains.idea.svn.commandLine.CommandUtil;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdCheckoutClient extends BaseSvnClient implements CheckoutClient {
|
||||
@Override
|
||||
public void checkout(@NotNull SvnTarget source,
|
||||
@NotNull File destination,
|
||||
@Nullable SVNRevision revision,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean ignoreExternals,
|
||||
@Nullable WorkingCopyFormat format,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
// TODO: check format
|
||||
|
||||
CommandUtil.put(parameters, source);
|
||||
CommandUtil.put(parameters, destination);
|
||||
CommandUtil.put(parameters, depth);
|
||||
CommandUtil.put(parameters, revision);
|
||||
CommandUtil.put(parameters, ignoreExternals, "--ignore-externals");
|
||||
parameters.add("--force"); // this is to conform to currently used SVNKit behavior - allowUnversionedObstructions
|
||||
|
||||
run(destination, handler, parameters);
|
||||
}
|
||||
|
||||
private void run(@NotNull File destination, @Nullable ISVNEventHandler handler, @NotNull List<String> parameters) throws VcsException {
|
||||
BaseUpdateCommandListener listener = new BaseUpdateCommandListener(destination, handler);
|
||||
|
||||
CommandUtil.execute(myVcs, SvnCommandName.checkout, parameters, null, listener);
|
||||
|
||||
listener.throwWrappedIfException();
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.CheckoutProvider;
|
||||
import com.intellij.openapi.vcs.VcsConfiguration;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
|
||||
import com.intellij.openapi.vcs.update.RefreshVFsSynchronously;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -42,8 +43,8 @@ import org.tmatesoft.svn.core.SVNCancelException;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
@@ -78,24 +79,23 @@ public class SvnCheckoutProvider implements CheckoutProvider {
|
||||
final boolean ignoreExternals,
|
||||
final Listener listener, final WorkingCopyFormat selectedFormat) {
|
||||
final Ref<Boolean> checkoutSuccessful = new Ref<Boolean>();
|
||||
final SVNException[] exception = new SVNException[1];
|
||||
final Exception[] exception = new Exception[1];
|
||||
final Task.Backgroundable checkoutBackgroundTask = new Task.Backgroundable(project,
|
||||
SvnBundle.message("message.title.check.out"), true, VcsConfiguration.getInstance(project).getCheckoutOption()) {
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
SvnWorkingCopyFormatHolder.setPresetFormat(selectedFormat);
|
||||
|
||||
final SVNUpdateClient client = SvnVcs.getInstance(project).createUpdateClient();
|
||||
if (! WorkingCopyFormat.ONE_DOT_SEVEN.equals(selectedFormat)) {
|
||||
client.getOperationsFactory().setPrimaryWcGeneration(SvnWcGeneration.V16);
|
||||
}
|
||||
client.setEventHandler(new CheckoutEventHandler(SvnVcs.getInstance(project), false, ProgressManager.getInstance().getProgressIndicator()));
|
||||
client.setIgnoreExternals(ignoreExternals);
|
||||
SvnVcs vcs = SvnVcs.getInstance(project);
|
||||
// TODO: made this way to preserve existing logic, but probably this check could be omitted as setPresetFormat(selectedFormat) invoked above
|
||||
WorkingCopyFormat format = !WorkingCopyFormat.ONE_DOT_SEVEN.equals(SvnWorkingCopyFormatHolder.getPresetFormat())
|
||||
? WorkingCopyFormat.ONE_DOT_SIX
|
||||
: selectedFormat;
|
||||
ISVNEventHandler handler = new CheckoutEventHandler(vcs, false, ProgressManager.getInstance().getProgressIndicator());
|
||||
ProgressManager.progress(SvnBundle.message("progress.text.checking.out", target.getAbsolutePath()));
|
||||
try {
|
||||
ProgressManager.progress(SvnBundle.message("progress.text.checking.out", target.getAbsolutePath()));
|
||||
if (! WorkingCopyFormat.ONE_DOT_SEVEN.equals(SvnWorkingCopyFormatHolder.getPresetFormat())) {
|
||||
client.getOperationsFactory().setPrimaryWcGeneration(SvnWcGeneration.V16);
|
||||
}
|
||||
client.doCheckout(SVNURL.parseURIEncoded(url), target, SVNRevision.UNDEFINED, revision, depth, true);
|
||||
// TODO: probably rewrite some logic to force ClientFactory provide supported versions (or create special client for that)
|
||||
vcs.getFactoryFromSettings().createCheckoutClient()
|
||||
.checkout(SvnTarget.fromURL(SVNURL.parseURIEncoded(url)), target, revision, depth, ignoreExternals, format, handler);
|
||||
ProgressManager.checkCanceled();
|
||||
checkoutSuccessful.set(Boolean.TRUE);
|
||||
}
|
||||
@@ -104,9 +104,10 @@ public class SvnCheckoutProvider implements CheckoutProvider {
|
||||
catch (SVNException e) {
|
||||
exception[0] = e;
|
||||
}
|
||||
catch (VcsException e) {
|
||||
exception[0] = e;
|
||||
}
|
||||
finally {
|
||||
client.setIgnoreExternals(false);
|
||||
client.setEventHandler(null);
|
||||
SvnWorkingCopyFormatHolder.setPresetFormat(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.jetbrains.idea.svn.checkout;
|
||||
|
||||
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.commandLine.SvnBindException;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
|
||||
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNUpdateClient;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClient {
|
||||
|
||||
@Override
|
||||
public void checkout(@NotNull SvnTarget source,
|
||||
@NotNull File destination,
|
||||
@Nullable SVNRevision revision,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean ignoreExternals,
|
||||
@Nullable WorkingCopyFormat format,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException {
|
||||
assertUrl(source);
|
||||
|
||||
if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format)) {
|
||||
throw new IllegalArgumentException("could not check out 1.8 format with SVNKit");
|
||||
}
|
||||
|
||||
SVNUpdateClient client = myVcs.createUpdateClient();
|
||||
|
||||
// TODO: most likely we should compare directly with WorkingCopyFormat.ONE_DOT_SIX
|
||||
if (!WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
|
||||
client.getOperationsFactory().setPrimaryWcGeneration(SvnWcGeneration.V16);
|
||||
}
|
||||
|
||||
client.setIgnoreExternals(ignoreExternals);
|
||||
client.setEventHandler(handler);
|
||||
|
||||
try {
|
||||
client.doCheckout(source.getURL(), destination, source.getPegRevision(), revision, depth, true);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNEvent;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class BaseUpdateCommandListener extends LineCommandListener {
|
||||
|
||||
@NotNull
|
||||
private final UpdateOutputLineConverter converter;
|
||||
|
||||
@Nullable
|
||||
private final ISVNEventHandler handler;
|
||||
|
||||
@NotNull
|
||||
private final AtomicReference<SVNException> exception;
|
||||
|
||||
public BaseUpdateCommandListener(@NotNull File base, @Nullable ISVNEventHandler handler) {
|
||||
this.handler = handler;
|
||||
this.converter = new UpdateOutputLineConverter(base);
|
||||
exception = new AtomicReference<SVNException>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void baseDirectory(File file) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLineAvailable(String line, Key outputType) {
|
||||
if (ProcessOutputTypes.STDOUT.equals(outputType)) {
|
||||
final SVNEvent event = converter.convert(line);
|
||||
if (event != null) {
|
||||
beforeHandler(event);
|
||||
try {
|
||||
callHandler(event);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
cancel();
|
||||
exception.set(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void callHandler(SVNEvent event) throws SVNException {
|
||||
if (handler != null) {
|
||||
handler.handleEvent(event, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
public void throwIfException() throws SVNException {
|
||||
SVNException e = exception.get();
|
||||
|
||||
if (e != null) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public void throwWrappedIfException() throws VcsException {
|
||||
SVNException e = exception.get();
|
||||
|
||||
if (e != null) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void beforeHandler(@NotNull SVNEvent event) {
|
||||
}
|
||||
}
|
||||
@@ -21,12 +21,12 @@ import com.intellij.util.LineSeparator;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.tmatesoft.svn.core.SVNErrorCode;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
@@ -38,8 +38,6 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class SvnBindException extends VcsException {
|
||||
|
||||
private static final Pattern ERROR_PATTERN = Pattern.compile("^svn: (E(\\d+)): (.*)$", Pattern.MULTILINE);
|
||||
|
||||
private Map<Integer, String> errors = new HashMap<Integer, String>();
|
||||
|
||||
public SvnBindException(String message) {
|
||||
@@ -70,7 +68,7 @@ public class SvnBindException extends VcsException {
|
||||
}
|
||||
|
||||
private void parseErrors(@NotNull String message) {
|
||||
Matcher matcher = ERROR_PATTERN.matcher(message);
|
||||
Matcher matcher = SvnUtil.ERROR_PATTERN.matcher(message);
|
||||
|
||||
while (matcher.find()) {
|
||||
put(Integer.valueOf(matcher.group(2)), matcher.group());
|
||||
|
||||
@@ -143,6 +143,10 @@ public abstract class SvnCommand {
|
||||
return outputAdapter.getOutput().getStdout();
|
||||
}
|
||||
|
||||
public String getErrorOutput() {
|
||||
return outputAdapter.getOutput().getStderr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for process termination
|
||||
* @param timeout
|
||||
|
||||
+32
-52
@@ -15,12 +15,11 @@
|
||||
*/
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnApplicationSettings;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback;
|
||||
@@ -88,54 +87,8 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
|
||||
base = base.isDirectory() ? base : base.getParentFile();
|
||||
|
||||
final List<String> parameters = prepareParameters(paths, revision, depth, allowUnversionedObstructions, depthIsSticky, makeParents);
|
||||
|
||||
final AtomicReference<SVNException> excRef = new AtomicReference<SVNException>();
|
||||
final ISVNEventHandler handler = getEventHandler();
|
||||
final UpdateOutputLineConverter converter = new UpdateOutputLineConverter(base);
|
||||
final BaseUpdateCommandListener listener = createCommandListener(paths, updatedToRevision, base);
|
||||
try {
|
||||
final LineCommandListener listener = new LineCommandListener() {
|
||||
final long[] myRevisions = new long[paths.length];
|
||||
|
||||
@Override
|
||||
public void baseDirectory(File file) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLineAvailable(String line, Key outputType) {
|
||||
if (ProcessOutputTypes.STDOUT.equals(outputType)) {
|
||||
final SVNEvent event = converter.convert(line);
|
||||
if (event != null) {
|
||||
checkForUpdateCompleted(event);
|
||||
try {
|
||||
handler.handleEvent(event, 0.5);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
cancel();
|
||||
excRef.set(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForUpdateCompleted(SVNEvent event) {
|
||||
if (SVNEventAction.UPDATE_COMPLETED.equals(event.getAction())) {
|
||||
final long eventRevision = event.getRevision();
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
final File path = paths[i];
|
||||
if (FileUtil.filesEqual(path, event.getFile())) {
|
||||
myRevisions[i] = eventRevision;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminated(int exitCode) {
|
||||
super.processTerminated(exitCode);
|
||||
updatedToRevision.set(myRevisions);
|
||||
}
|
||||
};
|
||||
SvnLineCommand.runWithAuthenticationAttempt(SvnApplicationSettings.getInstance().getCommandLinePath(),
|
||||
base, info.getURL(), SvnCommandName.up, listener,
|
||||
new IdeaSvnkitBasedAuthenticationCallback(SvnVcs.getInstance(myProject)),
|
||||
@@ -144,13 +97,40 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
|
||||
catch (SvnBindException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e));
|
||||
}
|
||||
if (excRef.get() != null) {
|
||||
throw excRef.get();
|
||||
}
|
||||
|
||||
listener.throwIfException();
|
||||
|
||||
return updatedToRevision.get();
|
||||
}
|
||||
|
||||
private BaseUpdateCommandListener createCommandListener(final File[] paths,
|
||||
final AtomicReference<long[]> updatedToRevision,
|
||||
final File base) {
|
||||
return new BaseUpdateCommandListener(base, getEventHandler()) {
|
||||
final long[] myRevisions = new long[paths.length];
|
||||
|
||||
@Override
|
||||
protected void beforeHandler(@NotNull SVNEvent event) {
|
||||
if (SVNEventAction.UPDATE_COMPLETED.equals(event.getAction())) {
|
||||
final long eventRevision = event.getRevision();
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
final File path = paths[i];
|
||||
if (FileUtil.filesEqual(path, event.getFile())) {
|
||||
myRevisions[i] = eventRevision;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminated(int exitCode) {
|
||||
super.processTerminated(exitCode);
|
||||
updatedToRevision.set(myRevisions);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private List<String> prepareParameters(File[] paths,
|
||||
SVNRevision revision,
|
||||
SVNDepth depth,
|
||||
|
||||
@@ -29,6 +29,7 @@ public enum SvnCommandName {
|
||||
st("st", false),
|
||||
up("up", true),
|
||||
ci("commit", true),
|
||||
checkout("checkout", true),
|
||||
cleanup("cleanup", true),
|
||||
cat("cat", false),
|
||||
add("add", true),
|
||||
@@ -40,9 +41,13 @@ public enum SvnCommandName {
|
||||
resolve("resolve", true),
|
||||
propget("propget", false),
|
||||
proplist("proplist", false),
|
||||
propset("propset", true),
|
||||
propdel("propdel", true),
|
||||
blame("blame", false),
|
||||
merge("merge", true),
|
||||
changelist("changelist", true);
|
||||
changelist("changelist", true),
|
||||
lock("lock", true),
|
||||
unlock("unlock", true);
|
||||
|
||||
private final String myName;
|
||||
private final boolean myWriteable;
|
||||
|
||||
@@ -281,10 +281,28 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
return new Lock();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("token", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
return new LockToken();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("owner", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
return new LockOwner();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("comment", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
return new LockComment();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("created", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
return new Date();
|
||||
return new LockCreated();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("uuid", new Getter<ElementHandlerBase>() {
|
||||
@@ -778,17 +796,76 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
|
||||
private static class Lock extends ElementHandlerBase {
|
||||
private Lock() {
|
||||
super(new String[]{"created"}, new String[]{});
|
||||
super(new String[]{"token", "owner", "comment", "created"}, new String[]{});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
|
||||
// TODO:
|
||||
structure.myLockWrapper = new SVNLockWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
private static class LockToken extends ElementHandlerBase {
|
||||
private LockToken() {
|
||||
super(new String[]{}, new String[]{});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
structure.myLockWrapper.setID(s);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LockOwner extends ElementHandlerBase {
|
||||
private LockOwner() {
|
||||
super(new String[]{}, new String[]{});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
structure.myLockWrapper.setOwner(s);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LockComment extends ElementHandlerBase {
|
||||
private LockComment() {
|
||||
super(new String[]{}, new String[]{});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
structure.myLockWrapper.setComment(s);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LockCreated extends ElementHandlerBase {
|
||||
private LockCreated() {
|
||||
super(new String[]{}, new String[]{});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
structure.myLockWrapper.setCreationDate(SVNDate.parseDate(s));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public class SvnInfoStructure {
|
||||
public String myConflictNew;
|
||||
public String myConflictWorking;
|
||||
public String myPropRejectFile;
|
||||
public SVNLock myLock;
|
||||
public SVNLockWrapper myLockWrapper;
|
||||
public SVNDepth myDepth;
|
||||
public String myChangelistName;
|
||||
public long myWcSize;
|
||||
@@ -65,7 +65,18 @@ public class SvnInfoStructure {
|
||||
public SVNInfo convert() throws SAXException, SVNException {
|
||||
return new IdeaSVNInfo(myFile, myUrl, myRootURL, myRevision, myKind, myUuid, myCommittedRevision, myCommittedDate, myAuthor, mySchedule,
|
||||
myCopyFromURL, myCopyFromRevision, myTextTime, myPropTime, myChecksum, myConflictOld, myConflictNew, myConflictWorking,
|
||||
myPropRejectFile, myLock, myDepth, myChangelistName, myWcSize, createTreeConflict());
|
||||
myPropRejectFile, getLock(), myDepth, myChangelistName, myWcSize, createTreeConflict());
|
||||
}
|
||||
|
||||
private SVNLock getLock() {
|
||||
SVNLock lock = null;
|
||||
|
||||
if (myLockWrapper != null) {
|
||||
myLockWrapper.setPath(relativeUrl);
|
||||
lock = myLockWrapper.create();
|
||||
}
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
private SVNTreeConflictDescription createTreeConflict() throws SAXException, SVNException {
|
||||
|
||||
+15
-4
@@ -53,17 +53,23 @@ public class UpdateOutputLineConverter {
|
||||
|
||||
private final static Pattern ourAtRevision = Pattern.compile(AT_REVISION);
|
||||
private final static Pattern ourUpdatedToRevision = Pattern.compile(UPDATED_TO_REVISION);
|
||||
private final static Pattern ourCheckedOutRevision = Pattern.compile("Checked out revision (\\d+)\\.");
|
||||
|
||||
private final static Pattern ourExternal = Pattern.compile(EXTERNAL);
|
||||
private final static Pattern ourUpdatedExternal = Pattern.compile(UPDATED_EXTERNAL);
|
||||
|
||||
private final static Pattern[] ourCompletePatterns = new Pattern[] {ourAtRevision, ourUpdatedToRevision, ourExternal, ourUpdatedExternal};
|
||||
private final static Pattern ourCheckedOutExternal = Pattern.compile("Checked out external at revision (\\d+)\\.");
|
||||
|
||||
private final static Pattern[] ourCompletePatterns =
|
||||
new Pattern[]{ourAtRevision, ourUpdatedToRevision, ourCheckedOutRevision, ourExternal, ourUpdatedExternal, ourCheckedOutExternal};
|
||||
|
||||
private final File myBase;
|
||||
private File myCurrentFile;
|
||||
|
||||
public UpdateOutputLineConverter(File base) {
|
||||
myBase = base;
|
||||
// checkout output does not have special line like "Updating '.'" on start - so set current file directly
|
||||
// to correctly detect complete event
|
||||
myCurrentFile = base;
|
||||
}
|
||||
|
||||
public SVNEvent convert(final String line) {
|
||||
@@ -82,6 +88,7 @@ public class UpdateOutputLineConverter {
|
||||
return new SVNEvent(myCurrentFile, myCurrentFile == null ? null : (myCurrentFile.isDirectory() ? SVNNodeKind.DIR : SVNNodeKind.FILE),
|
||||
null, -1, null, null, null, null, SVNEventAction.RESTORE, SVNEventAction.RESTORE, null, null, null, null, null);
|
||||
} else if (line.startsWith(SKIPPED)) {
|
||||
// called, for instance, when folder is not working copy
|
||||
myCurrentFile = parseForPath(line);
|
||||
final String comment = parseComment(line);
|
||||
return new SVNEvent(myCurrentFile, myCurrentFile == null ? null : (myCurrentFile.isDirectory() ? SVNNodeKind.DIR : SVNNodeKind.FILE),
|
||||
@@ -97,8 +104,12 @@ public class UpdateOutputLineConverter {
|
||||
final Pattern pattern = ourCompletePatterns[i];
|
||||
final long revision = matchAndGetRevision(pattern, line);
|
||||
if (revision != -1) {
|
||||
return new SVNEvent(myCurrentFile, myCurrentFile == null ? null : (myCurrentFile.isDirectory() ? SVNNodeKind.DIR : SVNNodeKind.FILE),
|
||||
null, revision, null, null, null, null, SVNEventAction.UPDATE_COMPLETED, SVNEventAction.UPDATE_COMPLETED, null, null, null, null, null);
|
||||
// TODO: seems that myCurrentFile will not always be correct - complete update message could be right after complete externals update
|
||||
// TODO: check this and use Stack instead
|
||||
return new SVNEvent(myCurrentFile,
|
||||
myCurrentFile == null ? null : (myCurrentFile.isDirectory() ? SVNNodeKind.DIR : SVNNodeKind.FILE),
|
||||
null, revision, null, null, null, null, SVNEventAction.UPDATE_COMPLETED, SVNEventAction.UPDATE_COMPLETED, null,
|
||||
null, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
|
||||
@@ -32,12 +33,13 @@ import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.IconUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.SvnPropertyKeys;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNPropertyData;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNWCClient;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -263,7 +265,30 @@ public class PropertiesComponent extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private class SetKeywordsAction extends AnAction {
|
||||
private abstract class BasePropertyAction extends AnAction {
|
||||
|
||||
protected void setProperty(@Nullable String property, @Nullable String value, boolean recursive, boolean force) {
|
||||
if (!StringUtil.isEmpty(property)) {
|
||||
try {
|
||||
myVcs.getFactory(myFile).createPropertyClient()
|
||||
.setProperty(myFile, property, value != null ? SVNPropertyValue.create(value) : null,
|
||||
SVNDepth.getInfinityOrEmptyDepth(recursive), force);
|
||||
}
|
||||
catch (VcsException error) {
|
||||
VcsBalloonProblemNotifier
|
||||
.showOverChangesView(myVcs.getProject(), "Can not set property: " + error.getMessage(), MessageType.ERROR);
|
||||
// show error message.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateFileView(boolean recursive) {
|
||||
setFile(myVcs, myFile);
|
||||
updateFileStatus(recursive);
|
||||
}
|
||||
}
|
||||
|
||||
private class SetKeywordsAction extends BasePropertyAction {
|
||||
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setText("Edit Keywords");
|
||||
@@ -276,7 +301,6 @@ public class PropertiesComponent extends JPanel {
|
||||
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
SVNPropertyData propValue = null;
|
||||
try {
|
||||
propValue = myVcs.getFactory(myFile).createPropertyClient()
|
||||
@@ -290,21 +314,13 @@ public class PropertiesComponent extends JPanel {
|
||||
propValue != null ? SVNPropertyValue.getPropertyAsString(propValue.getValue()) : null);
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
String value = dialog.getKeywords();
|
||||
try {
|
||||
wcClient.doSetProperty(myFile, SVNProperty.KEYWORDS, SVNPropertyValue.create(value), false, false, null);
|
||||
}
|
||||
catch (SVNException err) {
|
||||
// show error message
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), "Can not set property: " + err.getMessage(), MessageType.ERROR);
|
||||
}
|
||||
setProperty(SvnPropertyKeys.SVN_KEYWORDS, dialog.getKeywords(), false, false);
|
||||
}
|
||||
setFile(myVcs, myFile);
|
||||
updateFileStatus(false);
|
||||
updateFileView(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class DeletePropertyAction extends AnAction {
|
||||
private class DeletePropertyAction extends BasePropertyAction {
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setText("Delete Property");
|
||||
e.getPresentation().setDescription("Delete selected property");
|
||||
@@ -315,18 +331,12 @@ public class PropertiesComponent extends JPanel {
|
||||
}
|
||||
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
try {
|
||||
myVcs.createWCClient().doSetProperty(myFile, getSelectedPropertyName(), null, true, false, null);
|
||||
} catch (SVNException error) {
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), "Can not set property: " + error.getMessage(), MessageType.ERROR);
|
||||
// show error message.
|
||||
}
|
||||
setFile(myVcs, myFile);
|
||||
updateFileStatus(false);
|
||||
setProperty(getSelectedPropertyName(), null, false, true);
|
||||
updateFileView(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class AddPropertyAction extends AnAction {
|
||||
private class AddPropertyAction extends BasePropertyAction {
|
||||
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setText("Add Property");
|
||||
@@ -344,24 +354,14 @@ public class PropertiesComponent extends JPanel {
|
||||
dialog.show();
|
||||
boolean recursive = false;
|
||||
if (dialog.isOK()) {
|
||||
String name = dialog.getPropertyName();
|
||||
String value = dialog.getPropertyValue();
|
||||
recursive = dialog.isRecursive();
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
try {
|
||||
wcClient.doSetProperty(myFile, name, SVNPropertyValue.create(value), false, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, null, null);
|
||||
}
|
||||
catch (SVNException err) {
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), "Can not set property: " + err.getMessage(), MessageType.ERROR);
|
||||
// show error message
|
||||
}
|
||||
setProperty(dialog.getPropertyName(), dialog.getPropertyValue(), recursive, false);
|
||||
}
|
||||
setFile(myVcs, myFile);
|
||||
updateFileStatus(recursive);
|
||||
updateFileView(recursive);
|
||||
}
|
||||
}
|
||||
|
||||
private class EditPropertyAction extends AnAction {
|
||||
private class EditPropertyAction extends BasePropertyAction {
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setText("Edit Property");
|
||||
e.getPresentation().setDescription("Edit selected property value");
|
||||
@@ -377,20 +377,10 @@ public class PropertiesComponent extends JPanel {
|
||||
dialog.show();
|
||||
boolean recursive = false;
|
||||
if (dialog.isOK()) {
|
||||
String name = dialog.getPropertyName();
|
||||
String value = dialog.getPropertyValue();
|
||||
recursive = dialog.isRecursive();
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
try {
|
||||
wcClient.doSetProperty(myFile, name, SVNPropertyValue.create(value), false, recursive, null);
|
||||
}
|
||||
catch (SVNException err) {
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), "Can not set property: " + err.getMessage(), MessageType.ERROR);
|
||||
// show error message
|
||||
}
|
||||
setProperty(dialog.getPropertyName(), dialog.getPropertyValue(), recursive, false);
|
||||
}
|
||||
setFile(myVcs, myFile);
|
||||
updateFileStatus(recursive);
|
||||
updateFileView(recursive);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,22 +15,26 @@
|
||||
*/
|
||||
package org.jetbrains.idea.svn.dialogs;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.help.HelpManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
import org.jetbrains.idea.svn.SvnPropertyKeys;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.jetbrains.idea.svn.properties.PropertyClient;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNPropertyValue;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNPropertyData;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNWCClient;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
@@ -47,6 +51,9 @@ import java.util.TreeSet;
|
||||
* @author alex
|
||||
*/
|
||||
public class SetPropertyDialog extends DialogWrapper {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.dialogs.SetPropertyDialog");
|
||||
|
||||
private final String myPropertyName;
|
||||
private final File[] myFiles;
|
||||
|
||||
@@ -147,14 +154,8 @@ public class SetPropertyDialog extends DialogWrapper {
|
||||
return;
|
||||
}
|
||||
File file = myFiles[0];
|
||||
SVNPropertyData property;
|
||||
try {
|
||||
SVNWCClient client = myVCS.createWCClient();
|
||||
property = client.doGetProperty(file, name, SVNRevision.WORKING, SVNRevision.WORKING);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
property = null;
|
||||
}
|
||||
SVNPropertyData property = !StringUtil.isEmpty(name) ? getProperty(file, name) : null;
|
||||
|
||||
if (property != null) {
|
||||
myValueText.setText(SVNPropertyValue.getPropertyAsString(property.getValue()));
|
||||
myValueText.selectAll();
|
||||
@@ -164,6 +165,21 @@ public class SetPropertyDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
private SVNPropertyData getProperty(@NotNull File file, @NotNull String name) {
|
||||
SVNPropertyData property;
|
||||
|
||||
try {
|
||||
PropertyClient client = myVCS.getFactory(file).createPropertyClient();
|
||||
property = client.getProperty(SvnTarget.fromFile(file, SVNRevision.WORKING), name, false, SVNRevision.WORKING);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
LOG.info(e);
|
||||
property = null;
|
||||
}
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
protected JComponent createCenterPanel() {
|
||||
fillPropertyNames(myFiles);
|
||||
if (myPropertyName != null) {
|
||||
@@ -189,23 +205,26 @@ public class SetPropertyDialog extends DialogWrapper {
|
||||
if (files.length == 1) {
|
||||
File file = files[0];
|
||||
try {
|
||||
SVNWCClient client = myVCS.createWCClient();
|
||||
client.doGetProperty(file, null, SVNRevision.WORKING, SVNRevision.WORKING, false,
|
||||
new ISVNPropertyHandler() {
|
||||
public void handleProperty(File path, SVNPropertyData property) {
|
||||
String name = property.getName();
|
||||
if (name != null) {
|
||||
names.add(name);
|
||||
}
|
||||
}
|
||||
public void handleProperty(SVNURL url, SVNPropertyData property) {
|
||||
}
|
||||
public void handleProperty(long revision, SVNPropertyData property) {
|
||||
}
|
||||
});
|
||||
ISVNPropertyHandler handler = new ISVNPropertyHandler() {
|
||||
public void handleProperty(File path, SVNPropertyData property) {
|
||||
String name = property.getName();
|
||||
if (name != null) {
|
||||
names.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleProperty(SVNURL url, SVNPropertyData property) {
|
||||
}
|
||||
|
||||
public void handleProperty(long revision, SVNPropertyData property) {
|
||||
}
|
||||
};
|
||||
|
||||
PropertyClient client = myVCS.getFactory(file).createPropertyClient();
|
||||
client.list(SvnTarget.fromFile(file, SVNRevision.WORKING), SVNRevision.WORKING, SVNDepth.EMPTY, handler);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
catch (VcsException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +1,19 @@
|
||||
package org.jetbrains.idea.svn.integrate;
|
||||
|
||||
import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.jetbrains.idea.svn.commandLine.CommandUtil;
|
||||
import org.jetbrains.idea.svn.commandLine.LineCommandListener;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
import org.jetbrains.idea.svn.commandLine.UpdateOutputLineConverter;
|
||||
import org.jetbrains.idea.svn.commandLine.*;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNDiffOptions;
|
||||
import org.tmatesoft.svn.core.wc.SVNEvent;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevisionRange;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
@@ -109,52 +101,10 @@ public class CmdMergeClient extends BaseSvnClient implements MergeClient {
|
||||
}
|
||||
|
||||
private void run(File destination, ISVNEventHandler handler, List<String> parameters) throws VcsException {
|
||||
final AtomicReference<SVNException> excRef = new AtomicReference<SVNException>();
|
||||
final UpdateOutputLineConverter converter = new UpdateOutputLineConverter(destination);
|
||||
LineCommandListener listener = createListener(handler, excRef, converter);
|
||||
BaseUpdateCommandListener listener = new BaseUpdateCommandListener(destination, handler);
|
||||
|
||||
CommandUtil.execute(myVcs, SvnCommandName.merge, parameters, null, listener);
|
||||
|
||||
throwIfException(excRef);
|
||||
}
|
||||
|
||||
private static void throwIfException(AtomicReference<SVNException> exception) throws VcsException {
|
||||
SVNException e = exception.get();
|
||||
|
||||
if (e != null) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static LineCommandListener createListener(@Nullable final ISVNEventHandler handler,
|
||||
@NotNull final AtomicReference<SVNException> excRef,
|
||||
@NotNull final UpdateOutputLineConverter converter) {
|
||||
LineCommandListener result = null;
|
||||
|
||||
if (handler != null) {
|
||||
result = new LineCommandListener() {
|
||||
@Override
|
||||
public void baseDirectory(File file) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLineAvailable(String line, Key outputType) {
|
||||
if (ProcessOutputTypes.STDOUT.equals(outputType)) {
|
||||
final SVNEvent event = converter.convert(line);
|
||||
if (event != null) {
|
||||
try {
|
||||
handler.handleEvent(event, 0.5);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
cancel();
|
||||
excRef.set(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
listener.throwWrappedIfException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.jetbrains.idea.svn.lock;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.jetbrains.idea.svn.commandLine.CommandUtil;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommand;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
import org.tmatesoft.svn.core.SVNErrorMessage;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNNodeKind;
|
||||
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNEvent;
|
||||
import org.tmatesoft.svn.core.wc.SVNEventAction;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdLockClient extends BaseSvnClient implements LockClient {
|
||||
|
||||
@Override
|
||||
public void lock(@NotNull File file, boolean force, @NotNull String message, @Nullable ISVNEventHandler handler) throws VcsException {
|
||||
List<String> parameters = prepareParameters(file, force);
|
||||
|
||||
parameters.add("--message");
|
||||
parameters.add(message);
|
||||
|
||||
SvnCommand command = CommandUtil.execute(myVcs, SvnCommandName.lock, parameters, null);
|
||||
handleCommandCompletion(command, file, SVNEventAction.LOCKED, SVNEventAction.LOCK_FAILED, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlock(@NotNull File file, boolean force, @Nullable ISVNEventHandler handler) throws VcsException {
|
||||
List<String> parameters = prepareParameters(file, force);
|
||||
|
||||
SvnCommand command = CommandUtil.execute(myVcs, SvnCommandName.unlock, parameters, null);
|
||||
handleCommandCompletion(command, file, SVNEventAction.UNLOCKED, SVNEventAction.UNLOCK_FAILED, handler);
|
||||
}
|
||||
|
||||
private static List<String> prepareParameters(@NotNull File file, boolean force) {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
CommandUtil.put(parameters, file);
|
||||
CommandUtil.put(parameters, force, "--force");
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static void handleCommandCompletion(@NotNull SvnCommand command,
|
||||
@NotNull File file,
|
||||
@NotNull SVNEventAction success,
|
||||
@NotNull SVNEventAction failure,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException {
|
||||
// just warning appears in output when can not lock/unlock file for some reason (like, that file is already locked)
|
||||
SVNErrorMessage error = SvnUtil.parseWarning(command.getErrorOutput());
|
||||
|
||||
try {
|
||||
invokeHandler(file, error == null ? success : failure, handler, error);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void invokeHandler(@NotNull File file,
|
||||
@NotNull SVNEventAction action,
|
||||
@Nullable ISVNEventHandler handler,
|
||||
@Nullable SVNErrorMessage error)
|
||||
throws SVNException {
|
||||
if (handler != null) {
|
||||
handler.handleEvent(createEvent(file, action, error), 1);
|
||||
}
|
||||
}
|
||||
|
||||
private static SVNEvent createEvent(@NotNull File file, @NotNull SVNEventAction action, @Nullable SVNErrorMessage error) {
|
||||
return new SVNEvent(file, file.isDirectory() ? SVNNodeKind.DIR : SVNNodeKind.FILE, null, -1, null, null, null, null, action, action,
|
||||
error, null, null, null, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.jetbrains.idea.svn.lock;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.api.SvnClient;
|
||||
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface LockClient extends SvnClient {
|
||||
|
||||
void lock(@NotNull File file,
|
||||
boolean force,
|
||||
@NotNull String message,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException;
|
||||
|
||||
void unlock(@NotNull File file,
|
||||
boolean force,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.jetbrains.idea.svn.lock;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
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.SVNWCClient;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitLockClient extends BaseSvnClient implements LockClient {
|
||||
|
||||
@Override
|
||||
public void lock(@NotNull File file, boolean force, @NotNull String message, @Nullable ISVNEventHandler handler) throws VcsException {
|
||||
try {
|
||||
getClient(handler).doLock(new File[]{file}, force, message);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlock(@NotNull File file, boolean force, @Nullable ISVNEventHandler handler) throws VcsException {
|
||||
try {
|
||||
getClient(handler).doUnlock(new File[]{file}, force);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SVNWCClient getClient(@Nullable ISVNEventHandler handler) {
|
||||
SVNWCClient client = myVcs.createWCClient();
|
||||
|
||||
client.setEventHandler(handler);
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,27 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
|
||||
parseOutput(target, command.getOutput(), handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(@NotNull File file,
|
||||
@NotNull String property,
|
||||
@Nullable SVNPropertyValue value,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean force) throws VcsException {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
boolean isDelete = value == null;
|
||||
|
||||
parameters.add(property);
|
||||
if (!isDelete) {
|
||||
parameters.add(SVNPropertyValue.getPropertyAsString(value));
|
||||
// --force could only be used in "propset" command, but not in "propdel" command
|
||||
CommandUtil.put(parameters, force, "--force");
|
||||
}
|
||||
CommandUtil.put(parameters, file);
|
||||
CommandUtil.put(parameters, depth);
|
||||
|
||||
CommandUtil.execute(myVcs, isDelete ? SvnCommandName.propdel : SvnCommandName.propset, parameters, null);
|
||||
}
|
||||
|
||||
private void fillListParameters(@NotNull SvnTarget target,
|
||||
@Nullable SVNRevision revision,
|
||||
@Nullable SVNDepth depth,
|
||||
|
||||
@@ -5,11 +5,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.api.SvnClient;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNPropertyValue;
|
||||
import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNPropertyData;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
@@ -30,4 +33,10 @@ public interface PropertyClient extends SvnClient {
|
||||
@Nullable SVNRevision revision,
|
||||
@Nullable SVNDepth depth,
|
||||
@Nullable ISVNPropertyHandler handler) throws VcsException;
|
||||
|
||||
void setProperty(@NotNull File file,
|
||||
@NotNull String property,
|
||||
@Nullable SVNPropertyValue value,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean force) throws VcsException;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnBindException;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNPropertyValue;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNPropertyData;
|
||||
@@ -59,6 +61,20 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien
|
||||
runGetProperty(target, null, revision, depth, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(@NotNull File file,
|
||||
@NotNull String property,
|
||||
@Nullable SVNPropertyValue value,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean force) throws VcsException {
|
||||
try {
|
||||
myVcs.createWCClient().doSetProperty(file, property, value, force, depth, null, null);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void runGetProperty(@NotNull SvnTarget target,
|
||||
@Nullable String property,
|
||||
@Nullable SVNRevision revision,
|
||||
|
||||
Reference in New Issue
Block a user