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:
Generated
-1
@@ -16,7 +16,6 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/ant/jps-plugin/ant-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/ant/jps-plugin/ant-jps-plugin.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jps/antLayout/antlayout.iml" filepath="$PROJECT_DIR$/jps/antLayout/antlayout.iml" group="jps" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" group="plugins/GAE" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/svn4idea/bindSvn/bindSvn.iml" filepath="$PROJECT_DIR$/plugins/svn4idea/bindSvn/bindSvn.iml" group="plugins/VCS" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/boot/boot.iml" filepath="$PROJECT_DIR$/platform/boot/boot.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" filepath="$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/build/build.iml" filepath="$PROJECT_DIR$/build/build.iml" />
|
||||
|
||||
@@ -323,9 +323,6 @@ public def layoutCommunityPlugins(String home) {
|
||||
}
|
||||
|
||||
layoutPlugin("svn4idea") {
|
||||
jar("bindSvn.jar") {
|
||||
module("bindSvn")
|
||||
}
|
||||
fileset(dir: "$home/plugins/svn4idea/lib", excludes: "**/svnkitsrc.zip")
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ public class StringUtil extends StringUtilRt {
|
||||
|
||||
@NonNls private static final String VOWELS = "aeiouy";
|
||||
@NonNls private static final Pattern EOL_SPLIT_PATTERN = Pattern.compile(" *(\r|\n|\r\n)+ *");
|
||||
@NonNls private static final Pattern EOL_SPLIT_PATTERN_WITH_EMPTY = Pattern.compile(" *(\r|\n|\r\n) *");
|
||||
|
||||
public static final NotNullFunction<String, String> QUOTER = new NotNullFunction<String, String>() {
|
||||
@Override
|
||||
@@ -2132,7 +2133,19 @@ public class StringUtil extends StringUtilRt {
|
||||
*/
|
||||
@NotNull
|
||||
public static String[] splitByLines(@NotNull String string) {
|
||||
return EOL_SPLIT_PATTERN.split(string);
|
||||
return splitByLines(string, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits string by lines. If several line separators are in a row corresponding empty lines
|
||||
* are also added to result if {@code excludeEmptyStrings} is {@code false}.
|
||||
*
|
||||
* @param string String to split
|
||||
* @return array of strings
|
||||
*/
|
||||
@NotNull
|
||||
public static String[] splitByLines(@NotNull String string, boolean excludeEmptyStrings) {
|
||||
return (excludeEmptyStrings ? EOL_SPLIT_PATTERN : EOL_SPLIT_PATTERN_WITH_EMPTY).split(string);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="platform-api" />
|
||||
<orderEntry type="module" module-name="vcs-api" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/javahl.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$MODULE_DIR$/lib/javahlsrc.zip!/src" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,925 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn;
|
||||
|
||||
import org.tigris.subversion.javahl.*;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Irina.Chernushina
|
||||
* Date: 2/5/13
|
||||
* Time: 3:08 PM
|
||||
*/
|
||||
public class SvnBindClient implements SVNClientInterface {
|
||||
private final String myExecutablePath;
|
||||
private CommitEventHandler myHandler;
|
||||
private AuthenticationCallback myAuthenticationCallback;
|
||||
|
||||
public SvnBindClient(String path) {
|
||||
myExecutablePath = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getVersion() {
|
||||
// todo real version
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAdminDirectoryName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdminDirectory(String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastPath() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Status singleStatus(String path, boolean onServer) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Status[] status(String path, boolean descend, boolean onServer, boolean getAll) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Status[] status(String path, boolean descend, boolean onServer, boolean getAll, boolean noIgnore) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Status[] status(String path, boolean descend, boolean onServer, boolean getAll, boolean noIgnore, boolean ignoreExternals)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void status(String path,
|
||||
int depth,
|
||||
boolean onServer,
|
||||
boolean getAll,
|
||||
boolean noIgnore,
|
||||
boolean ignoreExternals,
|
||||
String[] changelists,
|
||||
StatusCallback callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DirEntry[] list(String url, Revision revision, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DirEntry[] list(String url, Revision revision, Revision pegRevision, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void list(String url,
|
||||
Revision revision,
|
||||
Revision pegRevision,
|
||||
int depth,
|
||||
int direntFields,
|
||||
boolean fetchLocks,
|
||||
ListCallback callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void username(String username) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void password(String password) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrompt(PromptUserPassword prompt) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogMessage[] logMessages(String path, Revision revisionStart, Revision revisionEnd) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogMessage[] logMessages(String path, Revision revisionStart, Revision revisionEnd, boolean stopOnCopy) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogMessage[] logMessages(String path, Revision revisionStart, Revision revisionEnd, boolean stopOnCopy, boolean discoverPath)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogMessage[] logMessages(String path,
|
||||
Revision revisionStart,
|
||||
Revision revisionEnd,
|
||||
boolean stopOnCopy,
|
||||
boolean discoverPath,
|
||||
long limit) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logMessages(String path,
|
||||
Revision pegRevision,
|
||||
Revision revisionStart,
|
||||
Revision revisionEnd,
|
||||
boolean stopOnCopy,
|
||||
boolean discoverPath,
|
||||
boolean includeMergedRevisions,
|
||||
String[] revProps,
|
||||
long limit,
|
||||
LogMessageCallback callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logMessages(String path,
|
||||
Revision pegRevision,
|
||||
RevisionRange[] ranges,
|
||||
boolean stopOnCopy,
|
||||
boolean discoverPath,
|
||||
boolean includeMergedRevisions,
|
||||
String[] revProps,
|
||||
long limit,
|
||||
LogMessageCallback callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long checkout(String moduleName, String destPath, Revision revision, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long checkout(String moduleName,
|
||||
String destPath,
|
||||
Revision revision,
|
||||
Revision pegRevision,
|
||||
boolean recurse,
|
||||
boolean ignoreExternals) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long checkout(String moduleName,
|
||||
String destPath,
|
||||
Revision revision,
|
||||
Revision pegRevision,
|
||||
int depth,
|
||||
boolean ignoreExternals,
|
||||
boolean allowUnverObstructions) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notification(Notify notify) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notification2(Notify2 notify) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConflictResolver(ConflictResolverCallback listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgressListener(ProgressListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitMessageHandler(CommitMessage messageHandler) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String[] path, String message, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String[] path, String message, boolean force, boolean keepLocal, Map revpropTable) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revert(String path, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revert(String path, int depth, String[] changelists) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(String path, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(String path, boolean recurse, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(String path, int depth, boolean force, boolean noIgnores, boolean addParents) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long update(String path, Revision revision, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] update(String[] path, Revision revision, boolean recurse, boolean ignoreExternals) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long update(String path,
|
||||
Revision revision,
|
||||
int depth,
|
||||
boolean depthIsSticky,
|
||||
boolean ignoreExternals,
|
||||
boolean allowUnverObstructions) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] update(String[] path,
|
||||
Revision revision,
|
||||
int depth,
|
||||
boolean depthIsSticky,
|
||||
boolean ignoreExternals,
|
||||
boolean allowUnverObstructions) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long commit(String[] path, String message, boolean recurse) throws ClientException {
|
||||
return commit(path, message, recurse? 3 : 0, false, false, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long commit(String[] path, String message, boolean recurse, boolean noUnlock) throws ClientException {
|
||||
return commit(path, message, recurse? 3 : 0, noUnlock, false, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long commit(String[] path,
|
||||
String message,
|
||||
int depth,
|
||||
boolean noUnlock,
|
||||
boolean keepChangelist,
|
||||
String[] changelists,
|
||||
Map revpropTable) throws ClientException {
|
||||
final long commit = new SvnCommitRunner(myExecutablePath, myHandler, myAuthenticationCallback).
|
||||
commit(path, message, depth, noUnlock, keepChangelist, changelists, revpropTable);
|
||||
if (commit < 0) {
|
||||
throw new BindClientException("Wrong committed revision number: " + commit, null, -1);
|
||||
}
|
||||
return commit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy(CopySource[] sources,
|
||||
String destPath,
|
||||
String message,
|
||||
boolean copyAsChild,
|
||||
boolean makeParents,
|
||||
boolean ignoreExternals,
|
||||
Map revpropTable) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy(CopySource[] sources, String destPath, String message, boolean copyAsChild, boolean makeParents, Map revpropTable)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy(String srcPath, String destPath, String message, Revision revision) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(String[] srcPaths,
|
||||
String destPath,
|
||||
String message,
|
||||
boolean force,
|
||||
boolean moveAsChild,
|
||||
boolean makeParents,
|
||||
Map revpropTable) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(String srcPath, String destPath, String message, Revision ignored, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(String srcPath, String destPath, String message, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mkdir(String[] path, String message, boolean makeParents, Map revpropTable) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mkdir(String[] path, String message) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup(String path) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(String path, int depth, int conflictResult) throws SubversionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolved(String path, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long doExport(String srcPath, String destPath, Revision revision, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long doExport(String srcPath,
|
||||
String destPath,
|
||||
Revision revision,
|
||||
Revision pegRevision,
|
||||
boolean force,
|
||||
boolean ignoreExternals,
|
||||
boolean recurse,
|
||||
String nativeEOL) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long doExport(String srcPath,
|
||||
String destPath,
|
||||
Revision revision,
|
||||
Revision pegRevision,
|
||||
boolean force,
|
||||
boolean ignoreExternals,
|
||||
int depth,
|
||||
String nativeEOL) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long doSwitch(String path, String url, Revision revision, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long doSwitch(String path,
|
||||
String url,
|
||||
Revision revision,
|
||||
Revision pegRevision,
|
||||
int depth,
|
||||
boolean depthIsSticky,
|
||||
boolean ignoreExternals,
|
||||
boolean allowUnverObstructions) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doImport(String path, String url, String message, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doImport(String path,
|
||||
String url,
|
||||
String message,
|
||||
int depth,
|
||||
boolean noIgnore,
|
||||
boolean ignoreUnknownNodeTypes,
|
||||
Map revpropTable) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] suggestMergeSources(String path, Revision pegRevision) throws SubversionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(String path1, Revision revision1, String path2, Revision revision2, String localPath, boolean force, boolean recurse)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(String path1,
|
||||
Revision revision1,
|
||||
String path2,
|
||||
Revision revision2,
|
||||
String localPath,
|
||||
boolean force,
|
||||
boolean recurse,
|
||||
boolean ignoreAncestry,
|
||||
boolean dryRun) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(String path1,
|
||||
Revision revision1,
|
||||
String path2,
|
||||
Revision revision2,
|
||||
String localPath,
|
||||
boolean force,
|
||||
int depth,
|
||||
boolean ignoreAncestry,
|
||||
boolean dryRun,
|
||||
boolean recordOnly) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(String path,
|
||||
Revision pegRevision,
|
||||
Revision revision1,
|
||||
Revision revision2,
|
||||
String localPath,
|
||||
boolean force,
|
||||
boolean recurse,
|
||||
boolean ignoreAncestry,
|
||||
boolean dryRun) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(String path,
|
||||
Revision pegRevision,
|
||||
RevisionRange[] revisions,
|
||||
String localPath,
|
||||
boolean force,
|
||||
int depth,
|
||||
boolean ignoreAncestry,
|
||||
boolean dryRun,
|
||||
boolean recordOnly) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeReintegrate(String path, Revision pegRevision, String localPath, boolean dryRun) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mergeinfo getMergeinfo(String path, Revision pegRevision) throws SubversionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getMergeinfoLog(int kind,
|
||||
String pathOrUrl,
|
||||
Revision pegRevision,
|
||||
String mergeSourceUrl,
|
||||
Revision srcPegRevision,
|
||||
boolean discoverChangedPaths,
|
||||
int depth,
|
||||
String[] revProps,
|
||||
LogMessageCallback callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getMergeinfoLog(int kind,
|
||||
String pathOrUrl,
|
||||
Revision pegRevision,
|
||||
String mergeSourceUrl,
|
||||
Revision srcPegRevision,
|
||||
boolean discoverChangedPaths,
|
||||
String[] revProps,
|
||||
LogMessageCallback callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diff(String target1, Revision revision1, String target2, Revision revision2, String outFileName, boolean recurse)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diff(String target1,
|
||||
Revision revision1,
|
||||
String target2,
|
||||
Revision revision2,
|
||||
String outFileName,
|
||||
boolean recurse,
|
||||
boolean ignoreAncestry,
|
||||
boolean noDiffDeleted,
|
||||
boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diff(String target1,
|
||||
Revision revision1,
|
||||
String target2,
|
||||
Revision revision2,
|
||||
String relativeToDir,
|
||||
String outFileName,
|
||||
int depth,
|
||||
String[] changelists,
|
||||
boolean ignoreAncestry,
|
||||
boolean noDiffDeleted,
|
||||
boolean force,
|
||||
boolean copiesAsAdds) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diff(String target1,
|
||||
Revision revision1,
|
||||
String target2,
|
||||
Revision revision2,
|
||||
String relativeToDir,
|
||||
String outFileName,
|
||||
int depth,
|
||||
String[] changelists,
|
||||
boolean ignoreAncestry,
|
||||
boolean noDiffDeleted,
|
||||
boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diff(String target,
|
||||
Revision pegRevision,
|
||||
Revision startRevision,
|
||||
Revision endRevision,
|
||||
String outFileName,
|
||||
boolean recurse,
|
||||
boolean ignoreAncestry,
|
||||
boolean noDiffDeleted,
|
||||
boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diff(String target,
|
||||
Revision pegRevision,
|
||||
Revision startRevision,
|
||||
Revision endRevision,
|
||||
String relativeToDir,
|
||||
String outFileName,
|
||||
int depth,
|
||||
String[] changelists,
|
||||
boolean ignoreAncestry,
|
||||
boolean noDiffDeleted,
|
||||
boolean force,
|
||||
boolean copiesAsAdds) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diff(String target,
|
||||
Revision pegRevision,
|
||||
Revision startRevision,
|
||||
Revision endRevision,
|
||||
String relativeToDir,
|
||||
String outFileName,
|
||||
int depth,
|
||||
String[] changelists,
|
||||
boolean ignoreAncestry,
|
||||
boolean noDiffDeleted,
|
||||
boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffSummarize(String target1,
|
||||
Revision revision1,
|
||||
String target2,
|
||||
Revision revision2,
|
||||
int depth,
|
||||
String[] changelists,
|
||||
boolean ignoreAncestry,
|
||||
DiffSummaryReceiver receiver) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffSummarize(String target,
|
||||
Revision pegRevision,
|
||||
Revision startRevision,
|
||||
Revision endRevision,
|
||||
int depth,
|
||||
String[] changelists,
|
||||
boolean ignoreAncestry,
|
||||
DiffSummaryReceiver receiver) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyData[] properties(String path) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyData[] properties(String path, Revision revision) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyData[] properties(String path, Revision revision, Revision pegRevision) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void properties(String path, Revision revision, Revision pegRevision, int depth, String[] changelists, ProplistCallback callback)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertySet(String path, String name, String value, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertySet(String path, String name, String value, boolean recurse, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertySet(String path, String name, byte[] value, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertySet(String path, String name, byte[] value, boolean recurse, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertySet(String path, String name, String value, int depth, String[] changelists, boolean force, Map revpropTable)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyRemove(String path, String name, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyRemove(String path, String name, int depth, String[] changelists) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyCreate(String path, String name, String value, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyCreate(String path, String name, String value, boolean recurse, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyCreate(String path, String name, byte[] value, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyCreate(String path, String name, byte[] value, boolean recurse, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyCreate(String path, String name, String value, int depth, String[] changelists, boolean force)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyData revProperty(String path, String name, Revision rev) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyData[] revProperties(String path, Revision rev) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRevProperty(String path, String name, Revision rev, String value, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRevProperty(String path, String name, Revision rev, String value, String originalValue, boolean force)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyData propertyGet(String path, String name) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyData propertyGet(String path, String name, Revision revision) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyData propertyGet(String path, String name, Revision revision, Revision pegRevision) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] fileContent(String path, Revision revision) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] fileContent(String path, Revision revision, Revision pegRevision) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamFileContent(String path, Revision revision, Revision pegRevision, int bufferSize, OutputStream stream)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relocate(String from, String to, String path, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] blame(String path, Revision revisionStart, Revision revisionEnd) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blame(String path, Revision revisionStart, Revision revisionEnd, BlameCallback callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blame(String path, Revision pegRevision, Revision revisionStart, Revision revisionEnd, BlameCallback callback)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blame(String path,
|
||||
Revision pegRevision,
|
||||
Revision revisionStart,
|
||||
Revision revisionEnd,
|
||||
boolean ignoreMimeType,
|
||||
boolean includeMergedRevisions,
|
||||
BlameCallback2 callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blame(String path,
|
||||
Revision pegRevision,
|
||||
Revision revisionStart,
|
||||
Revision revisionEnd,
|
||||
boolean ignoreMimeType,
|
||||
boolean includeMergedRevisions,
|
||||
BlameCallback3 callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfigDirectory(String configDir) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigDirectory() throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelOperation() throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Info info(String path) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToChangelist(String[] paths, String changelist, int depth, String[] changelists) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromChangelists(String[] paths, int depth, String[] changelists) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getChangelists(String rootPath, String[] changelists, int depth, ChangelistCallback callback) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock(String[] path, String comment, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlock(String[] path, boolean force) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Info2[] info2(String pathOrUrl, Revision revision, Revision pegRevision, boolean recurse) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info2(String pathOrUrl, Revision revision, Revision pegRevision, int depth, String[] changelists, InfoCallback callback)
|
||||
throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersionInfo(String path, String trailUrl, boolean lastChanged) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(String path) throws ClientException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void setHandler(CommitEventHandler handler) {
|
||||
myHandler = handler;
|
||||
}
|
||||
|
||||
public void setAuthenticationCallback(AuthenticationCallback authenticationCallback) {
|
||||
myAuthenticationCallback = authenticationCallback;
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn.status;
|
||||
|
||||
import org.apache.subversion.javahl.types.Lock;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Irina.Chernushina
|
||||
* Date: 2/21/12
|
||||
* Time: 2:33 PM
|
||||
*/
|
||||
public class LockWrapper {
|
||||
private String myPath;
|
||||
private String myID;
|
||||
private String myOwner;
|
||||
private String myComment;
|
||||
private Date myCreationDate;
|
||||
private Date myExpirationDate;
|
||||
|
||||
public LockWrapper(String path, String ID, String owner, String comment, Date creationDate, Date expirationDate) {
|
||||
myPath = path;
|
||||
myID = ID;
|
||||
myOwner = owner;
|
||||
myComment = comment;
|
||||
myCreationDate = creationDate;
|
||||
myExpirationDate = expirationDate;
|
||||
}
|
||||
|
||||
public LockWrapper() {
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return myPath;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
myPath = path;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return myID;
|
||||
}
|
||||
|
||||
public void setID(String ID) {
|
||||
myID = ID;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return myOwner;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
myOwner = owner;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return myComment;
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
myComment = comment;
|
||||
}
|
||||
|
||||
public Date getCreationDate() {
|
||||
return myCreationDate;
|
||||
}
|
||||
|
||||
public void setCreationDate(Date creationDate) {
|
||||
myCreationDate = creationDate;
|
||||
}
|
||||
|
||||
public Date getExpirationDate() {
|
||||
return myExpirationDate;
|
||||
}
|
||||
|
||||
public void setExpirationDate(Date expirationDate) {
|
||||
myExpirationDate = expirationDate;
|
||||
}
|
||||
|
||||
public org.tigris.subversion.javahl.Lock create() {
|
||||
final Date creation = getCreationDate();
|
||||
final Date expiration = getExpirationDate();
|
||||
final Lock newLock = new Lock(getOwner(), getPath(), getID(), getComment(), creation == null ? 0 : creation.getTime(),
|
||||
expiration == null ? 0 : expiration.getTime());
|
||||
try {
|
||||
final Constructor<org.tigris.subversion.javahl.Lock> constructor = org.tigris.subversion.javahl.Lock.class.getConstructor(Lock.class);
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance(newLock);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.tigris.subversion.javahl;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Irina.Chernushina
|
||||
* Date: 2/25/13
|
||||
* Time: 6:29 PM
|
||||
*/
|
||||
public class BindClientException extends ClientException {
|
||||
private Throwable myCause;
|
||||
|
||||
public BindClientException(String message, String source, int aprError) {
|
||||
super(message, source, aprError);
|
||||
}
|
||||
|
||||
public BindClientException(org.apache.subversion.javahl.ClientException ex) {
|
||||
super(ex);
|
||||
}
|
||||
|
||||
public static BindClientException create(@NotNull final Throwable t, final int code) {
|
||||
final BindClientException exception = new BindClientException(t.getMessage(), null, code);
|
||||
exception.myCause = t;
|
||||
return exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable getCause() {
|
||||
return myCause;
|
||||
}
|
||||
}
|
||||
@@ -49,11 +49,9 @@ public class ForNestedRootChecker {
|
||||
|
||||
private static class UrlConstructor {
|
||||
final SvnVcs myVcs;
|
||||
final SVNWCClient myClient;
|
||||
|
||||
private UrlConstructor(final SvnVcs vcs) {
|
||||
myVcs = vcs;
|
||||
myClient = myVcs.createWCClient();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -123,52 +123,31 @@ public class RootsToWorkingCopies implements VcsListener {
|
||||
|
||||
@Nullable
|
||||
private WorkingCopy calculateRoot(final VirtualFile root) {
|
||||
File workingCopyRoot = SvnUtil.getWorkingCopyRootNew(new File(root.getPath()));
|
||||
WorkingCopy workingCopy = null;
|
||||
final File ioFile = new File(root.getPath());
|
||||
File workingCopyRoot = null;
|
||||
try {
|
||||
workingCopyRoot = SVNWCUtil.getWorkingCopyRoot(ioFile, true);
|
||||
if (workingCopyRoot != null) {
|
||||
// ok to use low-level 1.6 API, 1.7 is checked below
|
||||
SVNWCAccess wcAccess = SVNWCAccess.newInstance(null);
|
||||
try {
|
||||
wcAccess.probeOpen(workingCopyRoot, false, 0);
|
||||
SVNEntry entry = wcAccess.getVersionedEntry(workingCopyRoot, false);
|
||||
final SVNURL url = entry.getSVNURL();
|
||||
if (url != null) {
|
||||
workingCopy = new WorkingCopy(workingCopyRoot, url, false);
|
||||
}
|
||||
} finally {
|
||||
wcAccess.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
}
|
||||
if (workingCopy == null) {
|
||||
workingCopyRoot = SvnUtil.getWcCopyRootIf17(ioFile, null);
|
||||
if (workingCopyRoot != null) {
|
||||
final SVNInfo svnInfo;
|
||||
try {
|
||||
svnInfo = SvnVcs.getInstance(myProject).createWCClient().doInfo(workingCopyRoot, SVNRevision.UNDEFINED);
|
||||
workingCopy = new WorkingCopy(workingCopyRoot, svnInfo.getURL(), true);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
}
|
||||
|
||||
if (workingCopyRoot != null) {
|
||||
final SVNInfo svnInfo = myVcs.getInfo(workingCopyRoot);
|
||||
|
||||
if (svnInfo != null && svnInfo.getURL() != null) {
|
||||
workingCopy = new WorkingCopy(workingCopyRoot, svnInfo.getURL(), true);
|
||||
}
|
||||
}
|
||||
|
||||
return registerWorkingCopy(root, workingCopy);
|
||||
}
|
||||
|
||||
private WorkingCopy registerWorkingCopy(@NotNull VirtualFile root, @Nullable WorkingCopy resolvedWorkingCopy) {
|
||||
synchronized (myLock) {
|
||||
if (workingCopy == null) {
|
||||
if (resolvedWorkingCopy == null) {
|
||||
myRootMapping.remove(root);
|
||||
myUnversioned.add(root);
|
||||
} else {
|
||||
myUnversioned.remove(root);
|
||||
myRootMapping.put(root, workingCopy);
|
||||
myRootMapping.put(root, resolvedWorkingCopy);
|
||||
}
|
||||
}
|
||||
return workingCopy;
|
||||
return resolvedWorkingCopy;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
* Date: 10/19/12
|
||||
* Time: 12:09 PM
|
||||
*/
|
||||
// TODO: Such locking functionality is not required anymore. Likely to be removed (together with SvnProxies).
|
||||
public abstract class SvnAbstractWriteOperationLocks {
|
||||
private final long myTimeout;
|
||||
private final static Map<String, Lock> myLockMap = new HashMap<String, Lock>();
|
||||
|
||||
@@ -350,7 +350,9 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
|
||||
}
|
||||
SvnInteractiveAuthenticationProvider.clearCallState();
|
||||
try {
|
||||
// start svnkit authentication cycle
|
||||
SvnVcs.getInstance(project).createWCClient(manager).doInfo(url, SVNRevision.UNDEFINED, SVNRevision.HEAD);
|
||||
//SvnVcs.getInstance(project).getInfo(url, SVNRevision.HEAD, manager);
|
||||
} catch (SVNAuthenticationException e) {
|
||||
log(e);
|
||||
return false;
|
||||
|
||||
@@ -537,6 +537,7 @@ dialog.show.svn.map.table.version14.text=1.4
|
||||
dialog.show.svn.map.table.version15.text=1.5
|
||||
dialog.show.svn.map.table.version16.text=1.6
|
||||
dialog.show.svn.map.table.version17.text=1.7
|
||||
dialog.show.svn.map.table.version18.text=1.8
|
||||
action.change.wcopy.format.task.title=Convert working copy format
|
||||
action.change.wcopy.format.task.progress.text=Converting working copy at {0} format from {1} to {2}
|
||||
action.change.wcopy.format.after.change.settings=Selected working copy format ({0}) is older than upgrade mode selected in Project Settings ({1}).\
|
||||
|
||||
@@ -85,7 +85,7 @@ public class SvnChangeProvider implements ChangeProvider {
|
||||
statusReceiver.addListener(context);
|
||||
statusReceiver.addListener(nestedCopiesBuilder);
|
||||
|
||||
final SvnRecursiveStatusWalker walker = new SvnRecursiveStatusWalker(myVcs.getProject(), statusReceiver.getMulticaster(), partner);
|
||||
final SvnRecursiveStatusWalker walker = new SvnRecursiveStatusWalker(myVcs, statusReceiver.getMulticaster(), partner);
|
||||
|
||||
for (FilePath path : zipper.getRecursiveDirs()) {
|
||||
walker.go(path, SVNDepth.INFINITY);
|
||||
@@ -180,7 +180,7 @@ public class SvnChangeProvider implements ChangeProvider {
|
||||
public void getChanges(final FilePath path, final boolean recursive, final ChangelistBuilder builder) throws SVNException {
|
||||
final SvnChangeProviderContext context = new SvnChangeProviderContext(myVcs, builder, null);
|
||||
final StatusWalkerPartnerImpl partner = new StatusWalkerPartnerImpl(myVcs, ProgressManager.getInstance().getProgressIndicator());
|
||||
final SvnRecursiveStatusWalker walker = new SvnRecursiveStatusWalker(myVcs.getProject(), context, partner);
|
||||
final SvnRecursiveStatusWalker walker = new SvnRecursiveStatusWalker(myVcs, context, partner);
|
||||
walker.go(path, recursive ? SVNDepth.INFINITY : SVNDepth.IMMEDIATES);
|
||||
processCopiedAndDeleted(context, null);
|
||||
}
|
||||
|
||||
@@ -259,23 +259,15 @@ class SvnChangeProviderContext implements StatusReceiver {
|
||||
|
||||
public void addModifiedNotSavedChange(final VirtualFile file) throws SVNException {
|
||||
final FilePath filePath = new FilePathImpl(file);
|
||||
final SVNInfo svnInfo;
|
||||
try {
|
||||
svnInfo = myVcs.createWCClient().doInfo(new File(file.getPath()), SVNRevision.UNDEFINED);
|
||||
final SVNInfo svnInfo = myVcs.getInfo(file);
|
||||
|
||||
if (svnInfo != null) {
|
||||
final SVNStatus svnStatus = new SVNStatus();
|
||||
svnStatus.setRevision(svnInfo.getRevision());
|
||||
myChangelistBuilder.processChangeInList(
|
||||
createChange(SvnContentRevision.createBaseRevision(myVcs, filePath, svnInfo.getRevision()), CurrentContentRevision.create(filePath),
|
||||
FileStatus.MODIFIED, svnStatus), (String)null, SvnVcs.getKey());
|
||||
}
|
||||
catch (SVNException e) {
|
||||
final SVNErrorCode errorCode = e.getErrorMessage().getErrorCode();
|
||||
if (SVNErrorCode.WC_PATH_NOT_FOUND.equals(errorCode) ||
|
||||
SVNErrorCode.UNVERSIONED_RESOURCE.equals(errorCode) || SVNErrorCode.WC_NOT_WORKING_COPY.equals(errorCode)) {
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
final SVNStatus svnStatus = new SVNStatus();
|
||||
svnStatus.setRevision(svnInfo.getRevision());
|
||||
myChangelistBuilder.processChangeInList(createChange(SvnContentRevision.createBaseRevision(myVcs, filePath, svnInfo.getRevision()),
|
||||
CurrentContentRevision.create(filePath), FileStatus.MODIFIED, svnStatus), (String) null,
|
||||
SvnVcs.getKey());
|
||||
}
|
||||
|
||||
private void checkSwitched(final FilePath filePath, final ChangelistBuilder builder, final SVNStatus status,
|
||||
|
||||
@@ -176,11 +176,9 @@ public class SvnChangelistListener implements ChangeListListener {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getCurrentMapping(final Project project, final File file) {
|
||||
final SvnVcs vcs = SvnVcs.getInstance(project);
|
||||
final SVNStatusClient statusClient = vcs.createStatusClient();
|
||||
public static String getCurrentMapping(final SvnVcs vcs, final File file) {
|
||||
try {
|
||||
final SVNStatus status = statusClient.doStatus(file, false);
|
||||
final SVNStatus status = vcs.getFactory(file).createStatusClient().doStatus(file, false);
|
||||
return status == null ? null : status.getChangelistName();
|
||||
}
|
||||
catch (SVNException e) {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="2ae3a" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="2ae3a" layout-manager="GridLayoutManager" row-count="5" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<tabbedpane title="General"/>
|
||||
@@ -29,7 +29,7 @@
|
||||
<grid id="a4729" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -87,7 +87,7 @@
|
||||
</grid>
|
||||
<component id="df054" class="javax.swing.JCheckBox" binding="myUseDefaultCheckBox">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="checkbox.configure.use.system.default.configuration.directory"/>
|
||||
@@ -96,7 +96,7 @@
|
||||
<grid id="137aa" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -123,36 +123,29 @@
|
||||
</grid>
|
||||
<hspacer id="e8f24">
|
||||
<constraints>
|
||||
<grid row="5" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<vspacer id="aa6b2">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="300b5" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Subversion 1.7 Acceleration"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="12735" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="3ecd1" class="com.intellij.ui.components.JBCheckBox" binding="myWithCommandLineClient">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="with command line client:"/>
|
||||
<margin top="2" left="3" bottom="2" right="3"/>
|
||||
<text value="Use command line client:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="44a8" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myCommandLineClient">
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNStatus;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -113,7 +114,8 @@ public class SvnContentRevision implements ContentRevision, MarkerVcsContentRevi
|
||||
if (lock.exists()) {
|
||||
throw new VcsException("Can not access file base revision contents: administrative area is locked");
|
||||
}
|
||||
return SvnUtil.getFileContents(myVcs, file.getPath(), false, myUseBaseRevision ? SVNRevision.BASE : myRevision, SVNRevision.UNDEFINED);
|
||||
return SvnUtil.getFileContents(myVcs, SvnTarget.fromFile(file), myUseBaseRevision ? SVNRevision.BASE : myRevision,
|
||||
SVNRevision.UNDEFINED);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.jetbrains.idea.svn;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.actions.VcsContextFactory;
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision;
|
||||
import com.intellij.openapi.vcs.diff.DiffMixin;
|
||||
@@ -26,8 +27,10 @@ import com.intellij.openapi.vcs.history.VcsRevisionDescription;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionDescriptionImpl;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
|
||||
import org.jetbrains.idea.svn.history.LatestExistentSearcher;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNPropertyValue;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
|
||||
@@ -43,19 +46,12 @@ public class SvnDiffProvider implements DiffProvider, DiffMixin {
|
||||
}
|
||||
|
||||
public VcsRevisionNumber getCurrentRevision(VirtualFile file) {
|
||||
final SVNWCClient client = myVcs.createWCClient();
|
||||
try {
|
||||
final SVNInfo svnInfo = client.doInfo(new File(file.getPresentableUrl()), SVNRevision.UNDEFINED);
|
||||
if (svnInfo == null) return null;
|
||||
if (SVNRevision.UNDEFINED.equals(svnInfo.getCommittedRevision()) && svnInfo.getCopyFromRevision() != null) {
|
||||
return new SvnRevisionNumber(svnInfo.getCopyFromRevision());
|
||||
}
|
||||
return new SvnRevisionNumber(svnInfo.getRevision());
|
||||
}
|
||||
catch (SVNException e) {
|
||||
LOG.debug(e); // most likely the file is unversioned
|
||||
return null;
|
||||
final SVNInfo svnInfo = myVcs.getInfo(new File(file.getPresentableUrl()));
|
||||
if (svnInfo == null) return null;
|
||||
if (SVNRevision.UNDEFINED.equals(svnInfo.getCommittedRevision()) && svnInfo.getCopyFromRevision() != null) {
|
||||
return new SvnRevisionNumber(svnInfo.getCopyFromRevision());
|
||||
}
|
||||
return new SvnRevisionNumber(svnInfo.getRevision());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,53 +61,36 @@ public class SvnDiffProvider implements DiffProvider, DiffMixin {
|
||||
}
|
||||
|
||||
private VcsRevisionDescription getCurrentRevisionDescription(File path) {
|
||||
final SVNWCClient client = myVcs.createWCClient();
|
||||
try {
|
||||
final SVNInfo svnInfo = client.doInfo(path, SVNRevision.UNDEFINED);
|
||||
|
||||
if (svnInfo.getCommittedRevision().equals(SVNRevision.UNDEFINED) && ! svnInfo.getCopyFromRevision().equals(SVNRevision.UNDEFINED) &&
|
||||
final SVNInfo svnInfo = myVcs.getInfo(path);
|
||||
if (svnInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (svnInfo.getCommittedRevision().equals(SVNRevision.UNDEFINED) && !svnInfo.getCopyFromRevision().equals(SVNRevision.UNDEFINED) &&
|
||||
svnInfo.getCopyFromURL() != null) {
|
||||
SVNURL copyUrl = svnInfo.getCopyFromURL();
|
||||
String localPath = myVcs.getSvnFileUrlMapping().getLocalPath(copyUrl.toString());
|
||||
if (localPath != null) {
|
||||
return getCurrentRevisionDescription(new File(localPath));
|
||||
}
|
||||
SVNURL copyUrl = svnInfo.getCopyFromURL();
|
||||
String localPath = myVcs.getSvnFileUrlMapping().getLocalPath(copyUrl.toString());
|
||||
if (localPath != null) {
|
||||
return getCurrentRevisionDescription(new File(localPath));
|
||||
}
|
||||
final String message = getProperties(client, path);
|
||||
}
|
||||
|
||||
try {
|
||||
final String message = getCommitMessage(path);
|
||||
return new VcsRevisionDescriptionImpl(new SvnRevisionNumber(svnInfo.getCommittedRevision()), svnInfo.getCommittedDate(),
|
||||
svnInfo.getAuthor(), message);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
catch (VcsException e) {
|
||||
LOG.debug(e); // most likely the file is unversioned
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getProperties(SVNWCClient client, File path) throws SVNException {
|
||||
final String[] message = new String[1];
|
||||
client.doGetRevisionProperty(path, null, SVNRevision.BASE, new ISVNPropertyHandler() {
|
||||
@Override
|
||||
public void handleProperty(File path, SVNPropertyData property) throws SVNException {
|
||||
handle(property);
|
||||
}
|
||||
private String getCommitMessage(File path) throws VcsException {
|
||||
SVNPropertyData property =
|
||||
myVcs.getFactory(path).createPropertyClient().getProperty(path, COMMIT_MESSAGE, true, null, SVNRevision.BASE);
|
||||
|
||||
@Override
|
||||
public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
|
||||
handle(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
|
||||
handle(property);
|
||||
}
|
||||
|
||||
private void handle(SVNPropertyData data) {
|
||||
if (COMMIT_MESSAGE.equals(data.getName())) {
|
||||
message[0] = data.getValue().getString();
|
||||
}
|
||||
}
|
||||
});
|
||||
return message[0];
|
||||
return property != null ? SVNPropertyValue.getPropertyAsString(property.getValue()) : null;
|
||||
}
|
||||
|
||||
private static ItemLatestState defaultResult() {
|
||||
@@ -135,18 +114,45 @@ public class SvnDiffProvider implements DiffProvider, DiffMixin {
|
||||
return SvnContentRevision.createBaseRevision(myVcs, filePath, svnRevision);
|
||||
}
|
||||
}
|
||||
|
||||
// not clear why we need it, with remote check..
|
||||
final SVNStatusClient client = myVcs.createStatusClient();
|
||||
try {
|
||||
final SVNStatus svnStatus = client.doStatus(new File(selectedFile.getPresentableUrl()), false, false);
|
||||
if (svnRevision.equals(svnStatus.getRevision())) {
|
||||
SVNStatus svnStatus = getFileStatus(new File(selectedFile.getPresentableUrl()), false);
|
||||
if (svnStatus != null && svnRevision.equals(svnStatus.getRevision())) {
|
||||
return SvnContentRevision.createBaseRevision(myVcs, filePath, svnRevision);
|
||||
}
|
||||
}
|
||||
return SvnContentRevision.createRemote(myVcs, filePath, svnRevision);
|
||||
}
|
||||
|
||||
private SVNStatus getFileStatus(File file, boolean remote) {
|
||||
WorkingCopyFormat format = myVcs.getWorkingCopyFormat(file);
|
||||
|
||||
return WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) ? getStatusCommandLine(file, remote) : getStatusWithSvnKit(file, remote);
|
||||
}
|
||||
|
||||
private SVNStatus getStatusWithSvnKit(File file, boolean remote) {
|
||||
SVNStatus result = null;
|
||||
|
||||
try {
|
||||
result = myVcs.createStatusClient().doStatus(file, remote, false);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
LOG.debug(e); // most likely the file is unversioned
|
||||
}
|
||||
return SvnContentRevision.createRemote(myVcs, filePath, svnRevision);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private SVNStatus getStatusCommandLine(File file, boolean remote) {
|
||||
SVNStatus result = null;
|
||||
|
||||
try {
|
||||
result = new SvnCommandLineStatusClient(myVcs.getProject()).doStatus(file, remote, false);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ItemLatestState getLastRevision(FilePath filePath) {
|
||||
@@ -159,36 +165,29 @@ public class SvnDiffProvider implements DiffProvider, DiffMixin {
|
||||
}
|
||||
|
||||
private ItemLatestState getLastRevision(final File file) {
|
||||
final SVNStatusClient client = myVcs.createStatusClient();
|
||||
try {
|
||||
final SVNStatus svnStatus = client.doStatus(file, true);
|
||||
if (svnStatus == null || itemExists(svnStatus) && SVNRevision.UNDEFINED.equals(svnStatus.getRemoteRevision())) {
|
||||
// IDEADEV-21785 (no idea why this can happen)
|
||||
final SVNInfo info = myVcs.createWCClient().doInfo(file, SVNRevision.HEAD);
|
||||
if (info == null || info.getURL() == null) {
|
||||
LOG.info("No SVN status returned for " + file.getPath());
|
||||
return defaultResult();
|
||||
}
|
||||
return createResult(info.getCommittedRevision(), true, false);
|
||||
final SVNStatus svnStatus = getFileStatus(file, true);
|
||||
if (svnStatus == null || itemExists(svnStatus) && SVNRevision.UNDEFINED.equals(svnStatus.getRemoteRevision())) {
|
||||
// IDEADEV-21785 (no idea why this can happen)
|
||||
final SVNInfo info = myVcs.getInfo(file, SVNRevision.HEAD);
|
||||
if (info == null || info.getURL() == null) {
|
||||
LOG.info("No SVN status returned for " + file.getPath());
|
||||
return defaultResult();
|
||||
}
|
||||
final boolean exists = itemExists(svnStatus);
|
||||
if (! exists) {
|
||||
// get really latest revision
|
||||
final LatestExistentSearcher searcher = new LatestExistentSearcher(myVcs, svnStatus.getURL());
|
||||
final long revision = searcher.getDeletionRevision();
|
||||
return createResult(info.getCommittedRevision(), true, false);
|
||||
}
|
||||
final boolean exists = itemExists(svnStatus);
|
||||
if (! exists) {
|
||||
// get really latest revision
|
||||
final LatestExistentSearcher searcher = new LatestExistentSearcher(myVcs, svnStatus.getURL());
|
||||
final long revision = searcher.getDeletionRevision();
|
||||
|
||||
return createResult(SVNRevision.create(revision), exists, false);
|
||||
}
|
||||
final SVNRevision remoteRevision = svnStatus.getRemoteRevision();
|
||||
if (remoteRevision != null) {
|
||||
return createResult(remoteRevision, exists, false);
|
||||
}
|
||||
return createResult(svnStatus.getRevision(), exists, false);
|
||||
return createResult(SVNRevision.create(revision), exists, false);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
LOG.debug(e); // most likely the file is unversioned
|
||||
return defaultResult();
|
||||
final SVNRevision remoteRevision = svnStatus.getRemoteRevision();
|
||||
if (remoteRevision != null) {
|
||||
return createResult(remoteRevision, exists, false);
|
||||
}
|
||||
return createResult(svnStatus.getRevision(), exists, false);
|
||||
}
|
||||
|
||||
private boolean itemExists(SVNStatus svnStatus) {
|
||||
|
||||
@@ -44,10 +44,7 @@ import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.vcsUtil.ActionWithTempFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.tmatesoft.svn.core.SVNErrorCode;
|
||||
import org.tmatesoft.svn.core.SVNErrorMessage;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNNodeKind;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
|
||||
@@ -160,10 +157,10 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
|
||||
private class UUIDHelper {
|
||||
private final SVNWCClient myWcClient;
|
||||
private final SvnVcs myVcs;
|
||||
|
||||
private UUIDHelper(final SvnVcs vcs) {
|
||||
myWcClient = vcs.createWCClient();
|
||||
myVcs = vcs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,7 +172,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
final SVNInfo info1 = new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
myT = myWcClient.doInfo(new File(dir.getPath()), SVNRevision.UNDEFINED);
|
||||
myT = myVcs.getInfo(new File(dir.getPath()));
|
||||
}
|
||||
}.compute();
|
||||
if (info1 == null || info1.getRepositoryUUID() == null) {
|
||||
@@ -244,10 +241,11 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
long srcTime = src.lastModified();
|
||||
try {
|
||||
final boolean isUndo = isUndo(vcs);
|
||||
final String list = isUndo ? null : SvnChangelistListener.getCurrentMapping(vcs.getProject(), src);
|
||||
final String list = isUndo ? null : SvnChangelistListener.getCurrentMapping(vcs, src);
|
||||
|
||||
final boolean is17 = SvnUtil.is17CopyPart(src);
|
||||
if (is17) {
|
||||
WorkingCopyFormat format = vcs.getWorkingCopyFormat(src);
|
||||
final boolean is17OrLater = WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) || WorkingCopyFormat.ONE_DOT_SEVEN.equals(format);
|
||||
if (is17OrLater) {
|
||||
SVNStatus srcStatus = getFileStatus(vcs, src);
|
||||
final File toDir = dst.getParentFile();
|
||||
SVNStatus dstStatus = getFileStatus(vcs, toDir);
|
||||
@@ -283,29 +281,18 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
ourStatusesForUndoMove.add(SVNStatusType.STATUS_ADDED);
|
||||
}
|
||||
|
||||
private boolean for17move(SvnVcs vcs, final File src, final File dst, boolean undo, SVNStatus srcStatus) throws SVNException {
|
||||
private boolean for17move(final SvnVcs vcs, final File src, final File dst, boolean undo, SVNStatus srcStatus) throws SVNException {
|
||||
if (srcStatus != null && srcStatus.getCopyFromURL() == null) {
|
||||
undo = false;
|
||||
}
|
||||
if (undo) {
|
||||
myUndoingMove = true;
|
||||
final SVNWCClient wcClient = vcs.createWCClient();
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
wcClient.doRevert(dst, true);
|
||||
}
|
||||
}.execute();
|
||||
createRevertAction(vcs, dst, true).execute();
|
||||
copyUnversionedMembersOfDirectory(src, dst);
|
||||
if (srcStatus == null || SvnVcs.svnStatusIsUnversioned(srcStatus)) {
|
||||
FileUtil.delete(src);
|
||||
} else {
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
wcClient.doRevert(src, true);
|
||||
}
|
||||
}.execute();
|
||||
createRevertAction(vcs, src, true).execute();
|
||||
}
|
||||
restoreFromUndoStorage(dst);
|
||||
} else {
|
||||
@@ -317,15 +304,9 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
copyFileOrDir(src, dst);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
final SVNWCClient wcClient = vcs.createWCClient();
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
wcClient.doDelete(src, true, false);
|
||||
}
|
||||
}.execute();
|
||||
createDeleteAction(vcs, src, true).execute();
|
||||
return false;
|
||||
}
|
||||
moveFileWithSvn(vcs, src, dst);
|
||||
@@ -333,13 +314,16 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void moveFileWithSvn(SvnVcs vcs, File src, final File dst) throws SVNException {
|
||||
final SVNCopyClient copyClient = vcs.createCopyClient();
|
||||
final SVNCopySource svnCopySource = new SVNCopySource(SVNRevision.UNDEFINED, SVNRevision.WORKING, src);
|
||||
public static void moveFileWithSvn(final SvnVcs vcs, final File src, final File dst) throws SVNException {
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
copyClient.doCopy(new SVNCopySource[]{svnCopySource}, dst, true, false, true);
|
||||
try {
|
||||
vcs.getFactory(src).createCopyMoveClient().copy(src, dst, false, true);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
wrapAndThrow(e);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@@ -357,7 +341,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
copyFileOrDir(src, dst);
|
||||
}
|
||||
catch (IOException e) {
|
||||
exc[0] = new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
exc[0] = new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -464,7 +448,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
* deleted: do nothing, return true (strange)
|
||||
*/
|
||||
public boolean delete(VirtualFile file) throws IOException {
|
||||
SvnVcs vcs = getVCS(file);
|
||||
final SvnVcs vcs = getVCS(file);
|
||||
if (vcs != null && SvnUtil.isAdminDirectory(file)) {
|
||||
return true;
|
||||
}
|
||||
@@ -476,12 +460,8 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioFile.getParentFile())) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (SVNWCUtil.isWorkingCopyRoot(ioFile)) {
|
||||
return false;
|
||||
}
|
||||
} catch (SVNException e) {
|
||||
//
|
||||
if (SvnUtil.isWorkingCopyRoot(ioFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SVNStatus status = getFileStatus(vcs, ioFile);
|
||||
@@ -507,13 +487,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
if (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_ADDED)) {
|
||||
try {
|
||||
final SVNWCClient wcClient = vcs.createWCClient();
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
wcClient.doRevert(ioFile, false);
|
||||
}
|
||||
}.execute();
|
||||
createRevertAction(vcs, ioFile, false).execute();
|
||||
}
|
||||
catch (SVNException e) {
|
||||
// ignore
|
||||
@@ -529,6 +503,41 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private RepeatSvnActionThroughBusy createRevertAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean recursive) {
|
||||
return new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
try {
|
||||
vcs.getFactory(file).createRevertClient().revert(new File[]{file}, SVNDepth.fromRecurse(recursive), null);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
wrapAndThrow(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private RepeatSvnActionThroughBusy createDeleteAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean force) {
|
||||
return new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
try {
|
||||
vcs.getFactory(file).createDeleteClient().delete(file, force);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
wrapAndThrow(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void wrapAndThrow(VcsException e) throws SVNException {
|
||||
// TODO: probably we should wrap into new exception only if e.getCause is not SVNException
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_GENERAL, e), e);
|
||||
}
|
||||
|
||||
private boolean isAboveSourceOfCopyOrMove(final Project p, File ioFile) {
|
||||
for (MovedFileInfo file : myMovedFiles) {
|
||||
if (FileUtil.isAncestor(ioFile, file.mySrc, false)) return true;
|
||||
@@ -583,7 +592,6 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioDir) && ! pendingAdd) {
|
||||
return false;
|
||||
}
|
||||
final SVNWCClient wcClient = vcs.createWCClient();
|
||||
final File targetFile = new File(ioDir, name);
|
||||
SVNStatus status = getFileStatus(vcs, targetFile);
|
||||
|
||||
@@ -603,12 +611,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
try {
|
||||
if (isUndo(vcs)) {
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
wcClient.doRevert(targetFile, false);
|
||||
}
|
||||
}.execute();
|
||||
createRevertAction(vcs, targetFile, false).execute();
|
||||
return true;
|
||||
}
|
||||
myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(dir, name, null, recursive));
|
||||
@@ -759,8 +762,6 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final SVNWCClient wcClient = vcs.createWCClient();
|
||||
final SVNCopyClient copyClient = vcs.createCopyClient();
|
||||
for(VirtualFile file: filesToProcess) {
|
||||
final File ioFile = new File(file.getPath());
|
||||
try {
|
||||
@@ -771,11 +772,15 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
protected void executeInternal() throws VcsException {
|
||||
try {
|
||||
// not recursive
|
||||
final SVNCopySource[] copySource = {new SVNCopySource(SVNRevision.WORKING, SVNRevision.WORKING, copyFrom)};
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
copyClient.doCopy(copySource, ioFile, false, true, true);
|
||||
try {
|
||||
vcs.getFactory(copyFrom).createCopyMoveClient().copy(copyFrom, ioFile, true, false);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
wrapAndThrow(e);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@@ -793,7 +798,12 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
wcClient.doAdd(ioFile, true, false, false, true);
|
||||
try {
|
||||
vcs.getFactory(ioFile).createAddClient().add(ioFile, null, false, false, true, null);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
wrapAndThrow(e);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
@@ -915,17 +925,11 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
final List<VcsException> exceptions) {
|
||||
return new Runnable() {
|
||||
public void run() {
|
||||
final SVNWCClient wcClient = vcs.createWCClient();
|
||||
for(FilePath file: filesToProcess) {
|
||||
VirtualFile vFile = file.getVirtualFile(); // for deleted directories
|
||||
final File ioFile = new File(file.getPath());
|
||||
try {
|
||||
new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
wcClient.doDelete(ioFile, true, false);
|
||||
}
|
||||
}.execute();
|
||||
createDeleteAction(vcs, ioFile, true).execute();
|
||||
if (vFile != null && vFile.isValid() && vFile.isDirectory()) {
|
||||
vFile.refresh(true, true);
|
||||
VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(vFile);
|
||||
@@ -978,18 +982,15 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
private void fillDeletedFiles(Project project, List<Pair<FilePath, WorkingCopyFormat>> deletedFiles, Collection<FilePath> deleteAnyway)
|
||||
throws SVNException {
|
||||
final SvnVcs vcs = SvnVcs.getInstance(project);
|
||||
final SVNStatusClient sc = vcs.createStatusClient();
|
||||
final Collection<File> files = myDeletedFiles.remove(project);
|
||||
for (final File file : files) {
|
||||
boolean isAdded = false;
|
||||
final SVNStatus status;
|
||||
status = new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
myT = sc.doStatus(file, false);
|
||||
}
|
||||
}.compute();
|
||||
isAdded = SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus());
|
||||
final SVNStatus status = new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
myT = vcs.getFactory(file).createStatusClient().doStatus(file, false);
|
||||
}
|
||||
}.compute();
|
||||
boolean isAdded = SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus());
|
||||
final FilePath filePath = VcsContextFactory.SERVICE.getInstance().createFilePathOn(file);
|
||||
if (isAdded) {
|
||||
deleteAnyway.add(filePath);
|
||||
@@ -1034,18 +1035,12 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SVNStatus getFileStatus(SvnVcs vcs, File file) {
|
||||
SVNStatusClient stClient = vcs.createStatusClient();
|
||||
return getFileStatus(file, stClient);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SVNStatus getFileStatus(final File file, final SVNStatusClient stClient) {
|
||||
private static SVNStatus getFileStatus(@NotNull final SvnVcs vcs, @NotNull final File file) {
|
||||
try {
|
||||
return new RepeatSvnActionThroughBusy() {
|
||||
@Override
|
||||
protected void executeImpl() throws SVNException {
|
||||
myT = stClient.doStatus(file, false);
|
||||
myT = vcs.getFactory(file).createStatusClient().doStatus(file, false);
|
||||
}
|
||||
}.compute();
|
||||
}
|
||||
|
||||
@@ -312,8 +312,8 @@ public class SvnFileUrlMappingImpl implements SvnFileUrlMapping, PersistentState
|
||||
LOG.info("Error: cannot find repository URL for versioned folder: " + foundRoot.getFile().getPath());
|
||||
} else {
|
||||
myRepositoryRoots.register(repoRoot);
|
||||
myTopRoots.add(new RootUrlInfo(repoRoot, foundRoot.getInfo().getURL(),
|
||||
SvnFormatSelector.getWorkingCopyFormat(new File(foundRoot.getFile().getPath())), foundRoot.getFile(), vcsRoot));
|
||||
myTopRoots.add(new RootUrlInfo(repoRoot, foundRoot.getInfo().getURL(), SvnFormatSelector.findRootAndGetFormat(
|
||||
new File(foundRoot.getFile().getPath())), foundRoot.getFile(), vcsRoot));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -541,8 +541,9 @@ public class SvnFileUrlMappingImpl implements SvnFileUrlMapping, PersistentState
|
||||
final SVNInfo svnInfo = vcs.getInfo(copyRoot);
|
||||
if ((svnInfo == null) || (svnInfo.getRepositoryRootURL() == null)) continue;
|
||||
|
||||
final RootUrlInfo info = new RootUrlInfo(svnInfo.getRepositoryRootURL(), svnInfo.getURL(),
|
||||
SvnFormatSelector.getWorkingCopyFormat(svnInfo.getFile()), copyRoot, vcsRoot);
|
||||
final RootUrlInfo info =
|
||||
new RootUrlInfo(svnInfo.getRepositoryRootURL(), svnInfo.getURL(), SvnFormatSelector.findRootAndGetFormat(svnInfo.getFile()),
|
||||
copyRoot, vcsRoot);
|
||||
mapping.add(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.jetbrains.idea.svn;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.WaitForProgressToShow;
|
||||
@@ -37,6 +38,9 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class SvnFormatSelector implements ISVNAdminAreaFactorySelector {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnFormatSelector");
|
||||
|
||||
public Collection getEnabledFactories(File path, Collection factories, boolean writeAccess) throws SVNException {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
return factories;
|
||||
@@ -145,7 +149,19 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector {
|
||||
return newMode[0];
|
||||
}
|
||||
|
||||
public static WorkingCopyFormat findRootAndGetFormat(final File path) {
|
||||
File root = SvnUtil.getWorkingCopyRootNew(path);
|
||||
|
||||
return root != null ? getWorkingCopyFormat(root) : WorkingCopyFormat.UNKNOWN;
|
||||
}
|
||||
|
||||
public static WorkingCopyFormat getWorkingCopyFormat(final File path) {
|
||||
WorkingCopyFormat format = SvnUtil.getFormat(path);
|
||||
|
||||
return WorkingCopyFormat.UNKNOWN.equals(format) ? detectWithSvnKit(path) : format;
|
||||
}
|
||||
|
||||
private static WorkingCopyFormat detectWithSvnKit(File path) {
|
||||
try {
|
||||
final SvnWcGeneration svnWcGeneration = SvnOperationFactory.detectWcGeneration(path, true);
|
||||
if (SvnWcGeneration.V17.equals(svnWcGeneration)) return WorkingCopyFormat.ONE_DOT_SEVEN;
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
* Date: 10/19/12
|
||||
* Time: 4:22 PM
|
||||
*/
|
||||
// TODO: Likely to be removed (together with SvnAbstractWriteOperationLocks).
|
||||
public class SvnProxies {
|
||||
private final SvnAbstractWriteOperationLocks myLocks;
|
||||
private final AtomicReference<LearningProxy<SVNChangelistClientI, SVNException>> myChangelist;
|
||||
|
||||
@@ -47,13 +47,15 @@ import java.util.LinkedList;
|
||||
public class SvnRecursiveStatusWalker {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnRecursiveStatusWalker");
|
||||
private final StatusWalkerPartner myPartner;
|
||||
private final SvnVcs myVcs;
|
||||
private final Project myProject;
|
||||
private final StatusReceiver myReceiver;
|
||||
private final LinkedList<MyItem> myQueue;
|
||||
private final MyHandler myHandler;
|
||||
|
||||
public SvnRecursiveStatusWalker(final Project project, final StatusReceiver receiver, final StatusWalkerPartner partner) {
|
||||
myProject = project;
|
||||
public SvnRecursiveStatusWalker(final SvnVcs vcs, final StatusReceiver receiver, final StatusWalkerPartner partner) {
|
||||
myVcs = vcs;
|
||||
myProject = vcs.getProject();
|
||||
myReceiver = receiver;
|
||||
myPartner = partner;
|
||||
myQueue = new LinkedList<MyItem>();
|
||||
@@ -61,7 +63,7 @@ public class SvnRecursiveStatusWalker {
|
||||
}
|
||||
|
||||
public void go(final FilePath rootPath, final SVNDepth depth) throws SVNException {
|
||||
final MyItem root = new MyItem(myProject, rootPath, depth, myPartner.createStatusClient(), false);
|
||||
final MyItem root = new MyItem(myVcs, rootPath, depth, myPartner.createStatusClient(), false);
|
||||
myQueue.add(root);
|
||||
|
||||
while (! myQueue.isEmpty()) {
|
||||
@@ -83,7 +85,7 @@ public class SvnRecursiveStatusWalker {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
final SVNStatus status = item.getClient().doStatus(ioFile, false, false);
|
||||
final SVNStatus status = item.getClient(ioFile).doStatus(ioFile, false, false);
|
||||
myReceiver.process(path, status);
|
||||
} catch (SVNException e) {
|
||||
handleStatusException(item, path, e);
|
||||
@@ -115,18 +117,20 @@ public class SvnRecursiveStatusWalker {
|
||||
private final Project myProject;
|
||||
private final FilePath myPath;
|
||||
private final SVNDepth myDepth;
|
||||
private final SVNStatusClient myClient;
|
||||
private final SvnStatusClientI mySvnClient;
|
||||
private final SvnStatusClientI myCommandLineClient;
|
||||
private final boolean myIsInnerCopyRoot;
|
||||
private final SvnConfiguration myConfiguration17;
|
||||
private final SvnVcs myVcs;
|
||||
|
||||
private MyItem(Project project, FilePath path, SVNDepth depth, SVNStatusClient client, boolean isInnerCopyRoot) {
|
||||
myProject = project;
|
||||
private MyItem(SvnVcs vcs, FilePath path, SVNDepth depth, SVNStatusClient client, boolean isInnerCopyRoot) {
|
||||
myVcs = vcs;
|
||||
myProject = vcs.getProject();
|
||||
myConfiguration17 = SvnConfiguration.getInstance(myProject);
|
||||
myPath = path;
|
||||
myDepth = depth;
|
||||
myClient = client;
|
||||
mySvnClient = new SvnkitSvnStatusClient(client);
|
||||
myCommandLineClient = new SvnCommandLineStatusClient(myProject);
|
||||
myIsInnerCopyRoot = isInnerCopyRoot;
|
||||
}
|
||||
|
||||
@@ -138,20 +142,20 @@ public class SvnRecursiveStatusWalker {
|
||||
return myDepth;
|
||||
}
|
||||
|
||||
public SvnStatusClientI getClient() {
|
||||
return mySvnClient;
|
||||
}
|
||||
|
||||
public SvnStatusClientI getClient(final File file) {
|
||||
if (! SVNDepth.INFINITY.equals(myDepth)) {
|
||||
return mySvnClient;
|
||||
WorkingCopyFormat format = myVcs.getWorkingCopyFormat(file);
|
||||
|
||||
if (format == WorkingCopyFormat.ONE_DOT_EIGHT) {
|
||||
return myCommandLineClient;
|
||||
}
|
||||
|
||||
// check format
|
||||
if (CheckJavaHL.isPresent() && SvnConfiguration.UseAcceleration.javaHL.equals(myConfiguration17.myUseAcceleration) &&
|
||||
Svn17Detector.is17(myProject, file)) {
|
||||
return new JavaHLSvnStatusClient(myProject);
|
||||
} else if (SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration17.myUseAcceleration) && Svn17Detector.is17(myProject, file)) {
|
||||
return new SvnCommandLineStatusClient(myProject);
|
||||
} else if (SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration17.myUseAcceleration)) {
|
||||
// apply command line disregarding working copy format
|
||||
return myCommandLineClient;
|
||||
}
|
||||
return mySvnClient;
|
||||
}
|
||||
@@ -186,7 +190,7 @@ public class SvnRecursiveStatusWalker {
|
||||
return true;
|
||||
}
|
||||
if (file.isDirectory() && new File(file, SVNFileUtil.getAdminDirectoryName()).exists()) {
|
||||
final MyItem childItem = new MyItem(myProject, path, newDepth, myPartner.createStatusClient(), true);
|
||||
final MyItem childItem = new MyItem(myVcs, path, newDepth, myPartner.createStatusClient(), true);
|
||||
myQueue.add(childItem);
|
||||
} else if (vf != null) {
|
||||
myReceiver.processUnversioned(vf);
|
||||
@@ -228,12 +232,13 @@ public class SvnRecursiveStatusWalker {
|
||||
}
|
||||
|
||||
public void checkIfCopyRootWasReported(@Nullable final SVNStatus ioFileStatus, final File ioFile) {
|
||||
if (! myMetCurrentItem && FileUtil.filesEqual(ioFile, myCurrentItem.getPath().getIOFile())) {
|
||||
File itemFile = myCurrentItem.getPath().getIOFile();
|
||||
if (! myMetCurrentItem && FileUtil.filesEqual(ioFile, itemFile)) {
|
||||
myMetCurrentItem = true;
|
||||
SVNStatus statusInner;
|
||||
try {
|
||||
statusInner = ioFileStatus != null ? ioFileStatus :
|
||||
myCurrentItem.getClient().doStatus(myCurrentItem.getPath().getIOFile(), false);
|
||||
myCurrentItem.getClient(itemFile).doStatus(itemFile, false);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
LOG.info(e);
|
||||
@@ -294,7 +299,7 @@ public class SvnRecursiveStatusWalker {
|
||||
//myReceiver.processUnversioned(vFile);
|
||||
//processRecursively(vFile, myCurrentItem.getDepth());
|
||||
} else {
|
||||
final MyItem childItem = new MyItem(myProject, new FilePathImpl(vFile), SVNDepth.INFINITY,
|
||||
final MyItem childItem = new MyItem(myVcs, new FilePathImpl(vFile), SVNDepth.INFINITY,
|
||||
myPartner.createStatusClient(), true);
|
||||
myQueue.add(childItem);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.io.File;
|
||||
* Date: 10/23/12
|
||||
* Time: 2:31 PM
|
||||
*/
|
||||
// TODO: Used only in SvnLockingTest which is not required anymore. Likely to be removed.
|
||||
public class SvnTestWriteOperationLocks extends SvnAbstractWriteOperationLocks {
|
||||
private final WorkingCopy myWorkingCopy;
|
||||
|
||||
|
||||
@@ -30,21 +30,19 @@ 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.vcs.impl.ContentRevisionCache;
|
||||
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.vfs.*;
|
||||
import com.intellij.openapi.wm.impl.status.StatusBarUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.api.ClientFactory;
|
||||
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
|
||||
import org.jetbrains.idea.svn.dialogs.LockDialog;
|
||||
import org.tmatesoft.sqljet.core.SqlJetException;
|
||||
import org.tmatesoft.sqljet.core.table.SqlJetDb;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
|
||||
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
|
||||
@@ -53,14 +51,14 @@ import org.tmatesoft.svn.core.io.SVNCapability;
|
||||
import org.tmatesoft.svn.core.io.SVNRepository;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.*;
|
||||
|
||||
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
|
||||
// TODO: Remember this when moving out SVNKit classes.
|
||||
@NonNls public static final String SVN_ADMIN_DIR_NAME = SVNFileUtil.getAdminDirectoryName();
|
||||
@NonNls public static final String ENTRIES_FILE_NAME = "entries";
|
||||
@NonNls public static final String WC_DB_FILE_NAME = "wc.db";
|
||||
@@ -71,13 +69,9 @@ public class SvnUtil {
|
||||
private SvnUtil() { }
|
||||
|
||||
public static boolean isSvnVersioned(final Project project, File parent) {
|
||||
try {
|
||||
final SVNInfo info = SvnVcs.getInstance(project).createWCClient().doInfo(parent, SVNRevision.UNDEFINED);
|
||||
return info != null;
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return false;
|
||||
}
|
||||
final SVNInfo info = SvnVcs.getInstance(project).getInfo(parent);
|
||||
|
||||
return info != null;
|
||||
}
|
||||
|
||||
public static Collection<VirtualFile> crawlWCRoots(final Project project, File path, SvnWCRootCrawler callback, ProgressIndicator progress) {
|
||||
@@ -123,15 +117,8 @@ public class SvnUtil {
|
||||
|
||||
@Nullable
|
||||
public static String getExactLocation(final SvnVcs vcs, File path) {
|
||||
try {
|
||||
SVNWCClient wcClient = vcs.createWCClient();
|
||||
SVNInfo info = wcClient.doInfo(path, SVNRevision.UNDEFINED);
|
||||
if (info != null && info.getURL() != null) {
|
||||
return info.getURL().toString();
|
||||
}
|
||||
}
|
||||
catch (SVNException ignored) { }
|
||||
return null;
|
||||
SVNInfo info = vcs.getInfo(path);
|
||||
return info != null && info.getURL() != null ? info.getURL().toString() : null;
|
||||
}
|
||||
|
||||
public static Map<String, File> getLocationInfoForModule(final SvnVcs vcs, File path, ProgressIndicator progress) {
|
||||
@@ -288,7 +275,9 @@ public class SvnUtil {
|
||||
}
|
||||
|
||||
public static String formatRepresentation(final WorkingCopyFormat format) {
|
||||
if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
|
||||
if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format)) {
|
||||
return SvnBundle.message("dialog.show.svn.map.table.version18.text");
|
||||
} else if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
|
||||
return SvnBundle.message("dialog.show.svn.map.table.version17.text");
|
||||
} else if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) {
|
||||
return SvnBundle.message("dialog.show.svn.map.table.version16.text");
|
||||
@@ -352,6 +341,54 @@ public class SvnUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets working copy internal format. Works for 1.7 and 1.8.
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public static WorkingCopyFormat getFormat(final File path) {
|
||||
int format = 0;
|
||||
File dbFile = resolveDatabase(path);
|
||||
|
||||
if (dbFile != null) {
|
||||
SqlJetDb db = null;
|
||||
try {
|
||||
db = SqlJetDb.open(dbFile, false);
|
||||
format = db.getOptions().getUserVersion();
|
||||
}
|
||||
catch (SqlJetException e) {
|
||||
LOG.error(e);
|
||||
} finally {
|
||||
if (db != null) {
|
||||
try {
|
||||
db.close();
|
||||
}
|
||||
catch (SqlJetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return WorkingCopyFormat.getInstance(format);
|
||||
}
|
||||
|
||||
private static File resolveDatabase(final File path) {
|
||||
File dbFile = getWcDb(path);
|
||||
File result = null;
|
||||
|
||||
try {
|
||||
if (dbFile.exists() && dbFile.isFile()) {
|
||||
result = dbFile;
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
LOG.error("Failed to access working copy database", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class LocationsCrawler implements SvnWCRootCrawler {
|
||||
private final SvnVcs myVcs;
|
||||
private final Map<String, File> myLocations;
|
||||
@@ -371,15 +408,9 @@ public class SvnUtil {
|
||||
oldText = progress.getText();
|
||||
progress.setText(SvnBundle.message("progress.text.discovering.location", root.getAbsolutePath()));
|
||||
}
|
||||
try {
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
SVNInfo info = wcClient.doInfo(root, SVNRevision.UNDEFINED);
|
||||
if (info != null && info.getURL() != null) {
|
||||
myLocations.put(info.getURL().toString(), info.getFile());
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
SVNInfo info = myVcs.getInfo(root);
|
||||
if (info != null && info.getURL() != null) {
|
||||
myLocations.put(info.getURL().toString(), info.getFile());
|
||||
}
|
||||
if (progress != null) {
|
||||
progress.setText(oldText);
|
||||
@@ -389,20 +420,15 @@ public class SvnUtil {
|
||||
|
||||
@Nullable
|
||||
public static String getRepositoryUUID(final SvnVcs vcs, final File file) {
|
||||
final SVNWCClient client = vcs.createWCClient();
|
||||
try {
|
||||
final SVNInfo info = client.doInfo(file, SVNRevision.UNDEFINED);
|
||||
return (info == null) ? null : info.getRepositoryUUID();
|
||||
} catch (SVNException e) {
|
||||
return null;
|
||||
}
|
||||
final SVNInfo info = vcs.getInfo(file);
|
||||
return info != null ? info.getRepositoryUUID() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getRepositoryUUID(final SvnVcs vcs, final SVNURL url) {
|
||||
final SVNWCClient client = vcs.createWCClient();
|
||||
try {
|
||||
final SVNInfo info = client.doInfo(url, SVNRevision.UNDEFINED, SVNRevision.UNDEFINED);
|
||||
final SVNInfo info = vcs.getInfo(url, SVNRevision.UNDEFINED);
|
||||
|
||||
return (info == null) ? null : info.getRepositoryUUID();
|
||||
} catch (SVNException e) {
|
||||
return null;
|
||||
@@ -411,19 +437,14 @@ public class SvnUtil {
|
||||
|
||||
@Nullable
|
||||
public static SVNURL getRepositoryRoot(final SvnVcs vcs, final File file) {
|
||||
final SVNWCClient client = vcs.createWCClient();
|
||||
try {
|
||||
final SVNInfo info = client.doInfo(file, SVNRevision.UNDEFINED);
|
||||
return (info == null) ? null : info.getRepositoryRootURL();
|
||||
} catch (SVNException e) {
|
||||
return null;
|
||||
}
|
||||
final SVNInfo info = vcs.getInfo(file);
|
||||
return info != null ? info.getRepositoryRootURL() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SVNURL getRepositoryRoot(final SvnVcs vcs, final String url) {
|
||||
try {
|
||||
return getRepositoryRoot(vcs, SVNURL.parseURIEncoded(url), true);
|
||||
return getRepositoryRoot(vcs, SVNURL.parseURIEncoded(url));
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return null;
|
||||
@@ -431,18 +452,14 @@ public class SvnUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SVNURL getRepositoryRoot(final SvnVcs vcs, final SVNURL url, boolean allowRemote) throws SVNException {
|
||||
final SVNWCClient client = vcs.createWCClient();
|
||||
SVNInfo info = client.doInfo(url, SVNRevision.UNDEFINED, SVNRevision.HEAD);
|
||||
public static SVNURL getRepositoryRoot(final SvnVcs vcs, final SVNURL url) throws SVNException {
|
||||
SVNInfo info = vcs.getInfo(url, SVNRevision.HEAD);
|
||||
|
||||
return (info == null) ? null : info.getRepositoryRootURL();
|
||||
}
|
||||
|
||||
public static boolean isWorkingCopyRoot(final File file) {
|
||||
try {
|
||||
return SVNWCUtil.isWorkingCopyRoot(file);
|
||||
} catch (SVNException e) {
|
||||
return false;
|
||||
}
|
||||
return FileUtil.filesEqual(file, getWorkingCopyRootNew(file));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -548,17 +565,9 @@ public class SvnUtil {
|
||||
}
|
||||
|
||||
public static SVNDepth getDepth(final SvnVcs vcs, final File file) {
|
||||
final SVNWCClient client = vcs.createWCClient();
|
||||
try {
|
||||
final SVNInfo svnInfo = client.doInfo(file, SVNRevision.UNDEFINED);
|
||||
if (svnInfo != null) {
|
||||
return svnInfo.getDepth();
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
}
|
||||
return SVNDepth.UNKNOWN;
|
||||
SVNInfo info = vcs.getInfo(file);
|
||||
|
||||
return info != null && info.getDepth() != null ? info.getDepth() : SVNDepth.UNKNOWN;
|
||||
}
|
||||
|
||||
public static boolean seemsLikeVersionedDir(final VirtualFile file) {
|
||||
@@ -590,21 +599,17 @@ public class SvnUtil {
|
||||
}
|
||||
|
||||
public static SVNURL getCommittedURL(final SvnVcs vcs, final File file) {
|
||||
final File root = getWorkingCopyRoot(file);
|
||||
if (root == null) return null;
|
||||
return getUrl(vcs, root);
|
||||
final File root = getWorkingCopyRootNew(file);
|
||||
|
||||
return root == null ? null : getUrl(vcs, root);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SVNURL getUrl(final SvnVcs vcs, final File file) {
|
||||
try {
|
||||
final SVNInfo info = vcs.createWCClient().doInfo(file, SVNRevision.UNDEFINED);
|
||||
return info == null ? null : info.getURL(); // todo for moved items?
|
||||
}
|
||||
catch (SVNException e) {
|
||||
LOG.debug(e);
|
||||
return null;
|
||||
}
|
||||
// todo for moved items?
|
||||
final SVNInfo info = vcs.getInfo(file);
|
||||
|
||||
return info == null ? null : info.getURL();
|
||||
}
|
||||
|
||||
public static boolean doesRepositorySupportMergeInfo(final SvnVcs vcs, final SVNURL url) {
|
||||
@@ -648,17 +653,9 @@ public class SvnUtil {
|
||||
|
||||
@Nullable
|
||||
public static File getWcCopyRootIf17(final File file, @Nullable final File upperBound) {
|
||||
File current = file;
|
||||
boolean wcDbFound = false;
|
||||
while (current != null) {
|
||||
File wcDb;
|
||||
if ((wcDb = getWcDb(current)).exists() && ! wcDb.isDirectory()) {
|
||||
wcDbFound = true;
|
||||
break;
|
||||
}
|
||||
current = current.getParentFile();
|
||||
}
|
||||
if (! wcDbFound) return null;
|
||||
File current = getParentWithDb(file);
|
||||
if (current == null) return null;
|
||||
|
||||
while (current != null) {
|
||||
try {
|
||||
final SvnWcGeneration svnWcGeneration = SvnOperationFactory.detectWcGeneration(current, false);
|
||||
@@ -674,6 +671,40 @@ public class SvnUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that deals also with 1.8 working copies.
|
||||
* TODO: Should be renamed when all parts updated for 1.8.
|
||||
*
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public static File getWorkingCopyRootNew(final File file) {
|
||||
File current = getParentWithDb(file);
|
||||
if (current == null) return getWorkingCopyRoot(file);
|
||||
|
||||
WorkingCopyFormat format = getFormat(current);
|
||||
|
||||
return WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) || WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)
|
||||
? current
|
||||
: getWorkingCopyRoot(file);
|
||||
}
|
||||
|
||||
private static File getParentWithDb(File file) {
|
||||
File current = file;
|
||||
boolean wcDbFound = false;
|
||||
while (current != null) {
|
||||
File wcDb;
|
||||
if ((wcDb = getWcDb(current)).exists() && ! wcDb.isDirectory()) {
|
||||
wcDbFound = true;
|
||||
break;
|
||||
}
|
||||
current = current.getParentFile();
|
||||
}
|
||||
if (! wcDbFound) return null;
|
||||
return current;
|
||||
}
|
||||
|
||||
public static boolean is17CopyPart(final File file) {
|
||||
try {
|
||||
return SvnWcGeneration.V17.equals(SvnOperationFactory.detectWcGeneration(file, true));
|
||||
@@ -703,44 +734,24 @@ public class SvnUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] getFileContents(final SvnVcs vcs, final String path, final boolean isUrl, final SVNRevision revision,
|
||||
final SVNRevision pegRevision)
|
||||
public static byte[] getFileContents(@NotNull final SvnVcs vcs,
|
||||
@NotNull final SvnTarget target,
|
||||
@Nullable final SVNRevision revision,
|
||||
@Nullable final SVNRevision pegRevision)
|
||||
throws VcsException {
|
||||
final int maxSize = VcsUtil.getMaxVcsLoadedFileSize();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream() {
|
||||
@Override
|
||||
public synchronized void write(int b) {
|
||||
if (size() > maxSize) throw new FileTooBigRuntimeException();
|
||||
super.write(b);
|
||||
}
|
||||
ClientFactory factory = target.isFile() ? vcs.getFactory(target.getFile()) : vcs.getFactory();
|
||||
|
||||
@Override
|
||||
public synchronized void write(byte[] b, int off, int len) {
|
||||
if (size() > maxSize) throw new FileTooBigRuntimeException();
|
||||
super.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void writeTo(OutputStream out) throws IOException {
|
||||
if (size() > maxSize) throw new FileTooBigRuntimeException();
|
||||
super.writeTo(out);
|
||||
}
|
||||
};
|
||||
SVNWCClient wcClient = vcs.createWCClient();
|
||||
try {
|
||||
if (isUrl) {
|
||||
wcClient.doGetFileContents(SVNURL.parseURIEncoded(path), pegRevision, revision, true, buffer);
|
||||
} else {
|
||||
wcClient.doGetFileContents(new File(path), pegRevision, revision, true, buffer);
|
||||
}
|
||||
ContentRevisionCache.checkContentsSize(path, buffer.size());
|
||||
} catch (FileTooBigRuntimeException e) {
|
||||
ContentRevisionCache.checkContentsSize(path, buffer.size());
|
||||
} catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
return buffer.toByteArray();
|
||||
return factory.createContentClient().getContent(target, revision, pegRevision);
|
||||
}
|
||||
|
||||
private static class FileTooBigRuntimeException extends RuntimeException {}
|
||||
public static SVNURL parseUrl(@NotNull String url) {
|
||||
try {
|
||||
return SVNURL.parseURIEncoded(url);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
IllegalArgumentException runtimeException = new IllegalArgumentException();
|
||||
runtimeException.initCause(e);
|
||||
throw runtimeException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +68,12 @@ import org.jetbrains.idea.svn.actions.CleanupWorker;
|
||||
import org.jetbrains.idea.svn.actions.ShowPropertiesDiffWithLocalAction;
|
||||
import org.jetbrains.idea.svn.actions.SvnMergeProvider;
|
||||
import org.jetbrains.idea.svn.annotate.SvnAnnotationProvider;
|
||||
import org.jetbrains.idea.svn.api.ClientFactory;
|
||||
import org.jetbrains.idea.svn.api.CmdClientFactory;
|
||||
import org.jetbrains.idea.svn.api.SvnKitClientFactory;
|
||||
import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment;
|
||||
import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnExecutableChecker;
|
||||
import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator;
|
||||
import org.jetbrains.idea.svn.dialogs.WCInfo;
|
||||
@@ -79,6 +83,7 @@ import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider;
|
||||
import org.jetbrains.idea.svn.history.SvnHistoryProvider;
|
||||
import org.jetbrains.idea.svn.lowLevel.PrimitivePool;
|
||||
import org.jetbrains.idea.svn.networking.SSLProtocolExceptionParser;
|
||||
import org.jetbrains.idea.svn.portable.SvnWcClientI;
|
||||
import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment;
|
||||
import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment;
|
||||
import org.jetbrains.idea.svn.update.SvnUpdateEnvironment;
|
||||
@@ -195,6 +200,10 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
};
|
||||
private SvnCheckoutProvider myCheckoutProvider;
|
||||
|
||||
private ClientFactory cmdClientFactory;
|
||||
private ClientFactory svnKitClientFactory;
|
||||
|
||||
|
||||
public void checkCommandLineVersion() {
|
||||
myChecker.checkExecutableAndNotifyIfNeeded();
|
||||
}
|
||||
@@ -481,6 +490,9 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
myChecker.checkExecutableAndNotifyIfNeeded();
|
||||
}
|
||||
|
||||
cmdClientFactory = new CmdClientFactory(this);
|
||||
svnKitClientFactory = new SvnKitClientFactory(this);
|
||||
|
||||
// do one time after project loaded
|
||||
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() {
|
||||
@Override
|
||||
@@ -911,24 +923,125 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
return new File(file, pathToDirProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides info either with command line or SvnKit based on project settings.
|
||||
* Call this method only if failed to detect working copy format by any other means.
|
||||
*
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
private SVNInfo runInfoCommand(@NotNull final File file) {
|
||||
SVNInfo result = null;
|
||||
|
||||
try {
|
||||
result = SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration.myUseAcceleration)
|
||||
? getInfoCommandLine(file, SVNRevision.UNDEFINED)
|
||||
: getInfoSvnKit(file);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
handleInfoException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public SVNInfo getInfo(@NotNull SVNURL url,
|
||||
SVNRevision pegRevision,
|
||||
SVNRevision revision,
|
||||
ISVNAuthenticationManager manager) throws SVNException {
|
||||
if (SvnConfiguration.UseAcceleration.commandLine.equals(myConfiguration.myUseAcceleration)) {
|
||||
return createInfoClient().doInfo(url, pegRevision, revision);
|
||||
} else {
|
||||
return (manager != null ? createWCClient(manager) : createWCClient()).doInfo(url, pegRevision, revision);
|
||||
}
|
||||
}
|
||||
|
||||
public SVNInfo getInfo(@NotNull SVNURL url, SVNRevision revision) throws SVNException {
|
||||
return getInfo(url, SVNRevision.UNDEFINED, revision, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SVNInfo getInfo(final VirtualFile file) {
|
||||
public SVNInfo getInfo(@NotNull final VirtualFile file) {
|
||||
final File ioFile = new File(file.getPath());
|
||||
return getInfo(ioFile);
|
||||
}
|
||||
|
||||
public SVNInfo getInfo(File ioFile) {
|
||||
@Nullable
|
||||
public SVNInfo getInfo(@NotNull String path) {
|
||||
return getInfo(new File(path));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SVNInfo getInfo(@NotNull File ioFile) {
|
||||
WorkingCopyFormat format = getWorkingCopyFormat(ioFile);
|
||||
SVNInfo result = null;
|
||||
|
||||
try {
|
||||
SVNWCClient wcClient = createWCClient();
|
||||
SVNInfo info = wcClient.doInfo(ioFile, SVNRevision.UNDEFINED);
|
||||
if (info == null || info.getRepositoryRootURL() == null) {
|
||||
info = wcClient.doInfo(ioFile, SVNRevision.HEAD);
|
||||
}
|
||||
return info;
|
||||
result = format == WorkingCopyFormat.ONE_DOT_EIGHT ? getInfoCommandLine(ioFile, SVNRevision.UNDEFINED) : runInfoCommand(ioFile);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return null;
|
||||
handleInfoException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SVNInfo getInfo(@NotNull File ioFile, @NotNull SVNRevision revision) {
|
||||
WorkingCopyFormat format = getWorkingCopyFormat(ioFile);
|
||||
SVNInfo result = null;
|
||||
|
||||
try {
|
||||
result = format == WorkingCopyFormat.ONE_DOT_EIGHT ? getInfoCommandLine(ioFile, revision) : getInfoSvnKit(ioFile, revision);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
handleInfoException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void handleInfoException(SVNException e) {
|
||||
final SVNErrorCode errorCode = e.getErrorMessage().getErrorCode();
|
||||
|
||||
if (SVNErrorCode.WC_PATH_NOT_FOUND.equals(errorCode) ||
|
||||
SVNErrorCode.UNVERSIONED_RESOURCE.equals(errorCode) || SVNErrorCode.WC_NOT_WORKING_COPY.equals(errorCode)) {
|
||||
LOG.debug(e);
|
||||
} else {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private SVNInfo getInfoSvnKit(@NotNull File ioFile) throws SVNException {
|
||||
SVNInfo info = getInfoSvnKit(ioFile, SVNRevision.UNDEFINED);
|
||||
if (info == null || info.getRepositoryRootURL() == null) {
|
||||
info = getInfoSvnKit(ioFile, SVNRevision.HEAD);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
private SVNInfo getInfoSvnKit(@NotNull File ioFile, SVNRevision revision) throws SVNException {
|
||||
return createWCClient().doInfo(ioFile, revision);
|
||||
}
|
||||
|
||||
private SVNInfo getInfoCommandLine(@NotNull File ioFile, SVNRevision revision) throws SVNException {
|
||||
SvnCommandLineInfoClient client = new SvnCommandLineInfoClient(myProject);
|
||||
return client.doInfo(ioFile, revision);
|
||||
}
|
||||
|
||||
private SvnWcClientI createInfoClient() {
|
||||
return new SvnCommandLineInfoClient(myProject);
|
||||
}
|
||||
|
||||
public WorkingCopyFormat getWorkingCopyFormat(@NotNull File ioFile) {
|
||||
RootUrlInfo rootInfo = getSvnFileUrlMapping().getWcRootForFilePath(ioFile);
|
||||
WorkingCopyFormat format = rootInfo != null ? rootInfo.getFormat() : WorkingCopyFormat.UNKNOWN;
|
||||
|
||||
if (WorkingCopyFormat.UNKNOWN.equals(format)) {
|
||||
format = SvnFormatSelector.findRootAndGetFormat(ioFile);
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
public void refreshSSLProperty() {
|
||||
@@ -1245,4 +1358,27 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
}
|
||||
return myCheckoutProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* For instance, when working copies of several formats are presented in project
|
||||
* (though it seems to be rather unlikely case).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ClientFactory getFactory() {
|
||||
// check working copy format of project directory
|
||||
WorkingCopyFormat format = getWorkingCopyFormat(new File(getProject().getBaseDir().getPath()));
|
||||
|
||||
return WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) ||
|
||||
myConfiguration.myUseAcceleration.equals(SvnConfiguration.UseAcceleration.commandLine) ? cmdClientFactory : svnKitClientFactory;
|
||||
}
|
||||
|
||||
public ClientFactory getFactory(@NotNull File file) {
|
||||
WorkingCopyFormat format = getWorkingCopyFormat(file);
|
||||
|
||||
return WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) ? cmdClientFactory : getFactory();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.io.File;
|
||||
* Date: 10/23/12
|
||||
* Time: 2:29 PM
|
||||
*/
|
||||
// TODO: Such locking functionality is not required anymore. Likely to be removed.
|
||||
public class SvnWriteOperationLocks extends SvnAbstractWriteOperationLocks {
|
||||
private final RootsToWorkingCopies myRootsToWorkingCopies;
|
||||
|
||||
|
||||
@@ -15,19 +15,22 @@
|
||||
*/
|
||||
package org.jetbrains.idea.svn;
|
||||
|
||||
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb;
|
||||
|
||||
/**
|
||||
* since not all constants are available from svnkit & constants are fixed
|
||||
*/
|
||||
public enum WorkingCopyFormat {
|
||||
|
||||
ONE_DOT_THREE(4, false, false, false, SvnBundle.message("dialog.show.svn.map.table.version13.text")),
|
||||
ONE_DOT_FOUR(8, false, false, false, SvnBundle.message("dialog.show.svn.map.table.version14.text")),
|
||||
ONE_DOT_FIVE(9, true, true, false, SvnBundle.message("dialog.show.svn.map.table.version15.text")),
|
||||
ONE_DOT_SIX(10, true, true, true, SvnBundle.message("dialog.show.svn.map.table.version16.text")),
|
||||
ONE_DOT_SEVEN(12, true, true, true, SvnBundle.message("dialog.show.svn.map.table.version17.text")),
|
||||
ONE_DOT_EIGHT(12, true, true, true, SvnBundle.message("dialog.show.svn.map.table.version18.text")),
|
||||
UNKNOWN(0, false, false, false, "unknown");
|
||||
|
||||
public static final int INTERNAL_FORMAT_17 = 29;
|
||||
public static final int INTERNAL_FORMAT_18 = 31;
|
||||
|
||||
private final int myFormat;
|
||||
private final boolean myChangelistSupport;
|
||||
private final boolean myMergeInfoSupport;
|
||||
@@ -60,10 +63,11 @@ public enum WorkingCopyFormat {
|
||||
|
||||
public static WorkingCopyFormat getInstance(final int value) {
|
||||
// somewhy 1.7 wc format can also be 29
|
||||
if (ISVNWCDb.WC_FORMAT_17 == value) {
|
||||
if (INTERNAL_FORMAT_17 == value) {
|
||||
return ONE_DOT_SEVEN;
|
||||
}
|
||||
if (ONE_DOT_FIVE.getFormat() == value) {
|
||||
} else if (INTERNAL_FORMAT_18 == value) {
|
||||
return ONE_DOT_EIGHT;
|
||||
} else if (ONE_DOT_FIVE.getFormat() == value) {
|
||||
return ONE_DOT_FIVE;
|
||||
} else if (ONE_DOT_FOUR.getFormat() == value) {
|
||||
return ONE_DOT_FOUR;
|
||||
|
||||
@@ -30,8 +30,6 @@ import org.jetbrains.idea.svn.SvnBundle;
|
||||
import org.jetbrains.idea.svn.SvnStatusUtil;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.SVNWCClient;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -68,8 +66,6 @@ public class AddAction extends BasicAction {
|
||||
ProjectLevelVcsManager manager = ProjectLevelVcsManager.getInstance(project);
|
||||
manager.startBackgroundVcsOperation();
|
||||
try {
|
||||
|
||||
SVNWCClient wcClient = activeVcs.createWCClient();
|
||||
final Set<VirtualFile> additionallyDirty = new HashSet<VirtualFile>();
|
||||
final FileStatusManager fileStatusManager = FileStatusManager.getInstance(project);
|
||||
for (VirtualFile item : items) {
|
||||
@@ -84,13 +80,13 @@ public class AddAction extends BasicAction {
|
||||
}
|
||||
}
|
||||
}
|
||||
Collection<SVNException> exceptions =
|
||||
SvnCheckinEnvironment.scheduleUnversionedFilesForAddition(wcClient, Arrays.asList(items), true);
|
||||
Collection<VcsException> exceptions =
|
||||
SvnCheckinEnvironment.scheduleUnversionedFilesForAddition(activeVcs, Arrays.asList(items), true);
|
||||
additionallyDirty.addAll(Arrays.asList(items));
|
||||
markDirty(project, additionallyDirty);
|
||||
if (!exceptions.isEmpty()) {
|
||||
final Collection<String> messages = new ArrayList<String>(exceptions.size());
|
||||
for (SVNException exception : exceptions) {
|
||||
for (VcsException exception : exceptions) {
|
||||
messages.add(exception.getMessage());
|
||||
}
|
||||
throw new VcsException(messages);
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.idea.svn.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
@@ -32,8 +33,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
import org.jetbrains.idea.svn.SvnStatusUtil;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.conflict.ConflictClient;
|
||||
import org.jetbrains.idea.svn.dialogs.SelectFilesDialog;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.jetbrains.idea.svn.portable.SvnStatusClientI;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
|
||||
@@ -42,6 +44,8 @@ import java.util.Collection;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class MarkResolvedAction extends BasicAction {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.actions.MarkResolvedAction");
|
||||
|
||||
protected String getActionName(AbstractVcs vcs) {
|
||||
return SvnBundle.message("action.name.mark.resolved");
|
||||
}
|
||||
@@ -88,15 +92,13 @@ public class MarkResolvedAction extends BasicAction {
|
||||
}
|
||||
pathsArray = dialog.getSelectedPaths();
|
||||
try {
|
||||
SVNWCClient wcClient = vcs.createWCClient();
|
||||
for (String path : pathsArray) {
|
||||
File ioFile = new File(path);
|
||||
wcClient.doResolve(ioFile, SVNDepth.EMPTY, SVNConflictChoice.MERGED);
|
||||
ConflictClient client = vcs.getFactory(ioFile).createConflictClient();
|
||||
|
||||
client.resolve(ioFile, true);
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
finally {
|
||||
for (VirtualFile file : files) {
|
||||
VcsDirtyScopeManager.getInstance(project).fileDirty(file);
|
||||
@@ -115,10 +117,12 @@ public class MarkResolvedAction extends BasicAction {
|
||||
|
||||
private static Collection<String> collectResolvablePaths(final SvnVcs vcs, VirtualFile[] files) {
|
||||
final Collection<String> target = new TreeSet<String>();
|
||||
SVNStatusClient stClient = vcs.createStatusClient();
|
||||
for (VirtualFile file : files) {
|
||||
try {
|
||||
stClient.doStatus(new File(file.getPath()), true, false, false, false, new ISVNStatusHandler() {
|
||||
File path = new File(file.getPath());
|
||||
SvnStatusClientI client = vcs.getFactory(path).createStatusClient();
|
||||
|
||||
client.doStatus(path, true, false, false, false, new ISVNStatusHandler() {
|
||||
public void handleStatus(SVNStatus status) {
|
||||
if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED ||
|
||||
status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) {
|
||||
@@ -128,7 +132,7 @@ public class MarkResolvedAction extends BasicAction {
|
||||
});
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
|
||||
@@ -27,12 +27,13 @@ import com.intellij.vcsUtil.VcsRunnable;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnRevisionNumber;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.jetbrains.idea.svn.properties.PropertyClient;
|
||||
import org.tmatesoft.svn.core.SVNProperty;
|
||||
import org.tmatesoft.svn.core.SVNPropertyValue;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
@@ -57,38 +58,34 @@ public class SvnMergeProvider implements MergeProvider {
|
||||
final MergeData data = new MergeData();
|
||||
VcsRunnable runnable = new VcsRunnable() {
|
||||
public void run() throws VcsException {
|
||||
SvnVcs vcs = SvnVcs.getInstance(myProject);
|
||||
File oldFile = null;
|
||||
File newFile = null;
|
||||
File workingFile = null;
|
||||
SVNWCClient client;
|
||||
boolean mergeCase = false;
|
||||
try {
|
||||
client = vcs.createWCClient();
|
||||
SVNInfo info = client.doInfo(new File(file.getPath()), SVNRevision.UNDEFINED);
|
||||
if (info != null) {
|
||||
oldFile = info.getConflictOldFile();
|
||||
newFile = info.getConflictNewFile();
|
||||
workingFile = info.getConflictWrkFile();
|
||||
mergeCase = workingFile == null || workingFile.getName().contains("working");
|
||||
// for debug
|
||||
if (workingFile == null) {
|
||||
LOG.info("Null working file when merging text conflict for " + file.getPath() + " old file: " + oldFile + " new file: " + newFile);
|
||||
}
|
||||
if (mergeCase) {
|
||||
// this is merge case
|
||||
oldFile = info.getConflictNewFile();
|
||||
newFile = info.getConflictOldFile();
|
||||
workingFile = info.getConflictWrkFile();
|
||||
}
|
||||
data.LAST_REVISION_NUMBER = new SvnRevisionNumber(info.getRevision());
|
||||
SvnVcs vcs = SvnVcs.getInstance(myProject);
|
||||
SVNInfo info = vcs.getInfo(file);
|
||||
|
||||
if (info != null) {
|
||||
oldFile = info.getConflictOldFile();
|
||||
newFile = info.getConflictNewFile();
|
||||
workingFile = info.getConflictWrkFile();
|
||||
mergeCase = workingFile == null || workingFile.getName().contains("working");
|
||||
// for debug
|
||||
if (workingFile == null) {
|
||||
LOG.info("Null working file when merging text conflict for " + file.getPath() + " old file: " + oldFile + " new file: " + newFile);
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
if (mergeCase) {
|
||||
// this is merge case
|
||||
oldFile = info.getConflictNewFile();
|
||||
newFile = info.getConflictOldFile();
|
||||
workingFile = info.getConflictWrkFile();
|
||||
}
|
||||
data.LAST_REVISION_NUMBER = new SvnRevisionNumber(info.getRevision());
|
||||
} else {
|
||||
throw new VcsException("Could not get info for " + file.getPath());
|
||||
}
|
||||
if (oldFile == null || newFile == null || workingFile == null) {
|
||||
ByteArrayOutputStream bos = getBaseRevisionContents(client, file);
|
||||
ByteArrayOutputStream bos = getBaseRevisionContents(vcs, file);
|
||||
data.ORIGINAL = bos.toByteArray();
|
||||
data.LAST = bos.toByteArray();
|
||||
data.CURRENT = readFile(new File(file.getPath()));
|
||||
@@ -99,7 +96,7 @@ public class SvnMergeProvider implements MergeProvider {
|
||||
data.CURRENT = readFile(workingFile);
|
||||
}
|
||||
if (mergeCase) {
|
||||
final ByteArrayOutputStream contents = getBaseRevisionContents(vcs.createWCClient(), file);
|
||||
final ByteArrayOutputStream contents = getBaseRevisionContents(vcs, file);
|
||||
if (! Arrays.equals(contents.toByteArray(), data.ORIGINAL)) {
|
||||
// swap base and server: another order of merge arguments
|
||||
byte[] original = data.ORIGINAL;
|
||||
@@ -114,13 +111,17 @@ public class SvnMergeProvider implements MergeProvider {
|
||||
return data;
|
||||
}
|
||||
|
||||
private ByteArrayOutputStream getBaseRevisionContents(SVNWCClient client, VirtualFile file) {
|
||||
private ByteArrayOutputStream getBaseRevisionContents(@NotNull SvnVcs vcs, @NotNull VirtualFile file) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try {
|
||||
client.doGetFileContents(new File(file.getPath()), SVNRevision.UNDEFINED, SVNRevision.BASE, true, bos);
|
||||
byte[] contents = SvnUtil.getFileContents(vcs, SvnTarget.fromFile(new File(file.getPath())), SVNRevision.BASE, SVNRevision.UNDEFINED);
|
||||
bos.write(contents);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
catch (VcsException e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
return bos;
|
||||
}
|
||||
@@ -135,13 +136,14 @@ public class SvnMergeProvider implements MergeProvider {
|
||||
}
|
||||
|
||||
public void conflictResolvedForFile(VirtualFile file) {
|
||||
// TODO: Add possibility to resolve content conflicts separately from property conflicts.
|
||||
SvnVcs vcs = SvnVcs.getInstance(myProject);
|
||||
File path = new File(file.getPath());
|
||||
try {
|
||||
SVNWCClient client = vcs.createWCClient();
|
||||
client.doResolve(new File(file.getPath()), SVNDepth.EMPTY, true, false, SVNConflictChoice.MERGED);
|
||||
vcs.getFactory(path).createConflictClient().resolve(path, false);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
catch (VcsException e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
// the .mine/.r## files have been deleted
|
||||
final VirtualFile parent = file.getParent();
|
||||
@@ -152,17 +154,20 @@ public class SvnMergeProvider implements MergeProvider {
|
||||
|
||||
public boolean isBinary(@NotNull final VirtualFile file) {
|
||||
SvnVcs vcs = SvnVcs.getInstance(myProject);
|
||||
|
||||
try {
|
||||
SVNWCClient client = vcs.createWCClient();
|
||||
File ioFile = new File(file.getPath());
|
||||
SVNPropertyData svnPropertyData = client.doGetProperty(ioFile, SVNProperty.MIME_TYPE, SVNRevision.UNDEFINED, SVNRevision.WORKING);
|
||||
PropertyClient client = vcs.getFactory(ioFile).createPropertyClient();
|
||||
|
||||
SVNPropertyData svnPropertyData = client.getProperty(ioFile, SVNProperty.MIME_TYPE, false, SVNRevision.UNDEFINED, SVNRevision.WORKING);
|
||||
if (svnPropertyData != null && SVNProperty.isBinaryMimeType(SVNPropertyValue.getPropertyAsString(svnPropertyData.getValue()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
catch (VcsException e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.jetbrains.idea.svn.add;
|
||||
|
||||
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.SVNDepth;
|
||||
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface AddClient extends SvnClient {
|
||||
|
||||
void add(@NotNull File file,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean makeParents,
|
||||
boolean includeIgnored,
|
||||
boolean force,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.jetbrains.idea.svn.add;
|
||||
|
||||
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.api.BaseSvnClient;
|
||||
import org.jetbrains.idea.svn.api.FileStatusResultParser;
|
||||
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.SVNEvent;
|
||||
import org.tmatesoft.svn.core.wc.SVNStatusType;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdAddClient extends BaseSvnClient implements AddClient {
|
||||
|
||||
private static final String STATUS = "\\s*(\\w)\\s*";
|
||||
private static final String OPTIONAL_FILE_TYPE = "(\\(.*\\))?";
|
||||
private static final String PATH = "\\s*(.*?)\\s*";
|
||||
private static final Pattern CHANGED_PATH = Pattern.compile(STATUS + OPTIONAL_FILE_TYPE + PATH);
|
||||
|
||||
@Override
|
||||
public void add(@NotNull File file,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean makeParents,
|
||||
boolean includeIgnored,
|
||||
boolean force,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException {
|
||||
List<String> parameters = prepareParameters(file, depth, makeParents, includeIgnored, force);
|
||||
|
||||
// TODO: handler should be called in parallel with command execution, but this will be in other thread
|
||||
// TODO: check if that is ok for current handler implementation
|
||||
// TODO: add possibility to invoke "handler.checkCancelled" - process should be killed
|
||||
CommandUtil.execute(myVcs, SvnCommandName.add, parameters, new FileStatusResultParser(CHANGED_PATH, handler, new AddStatusConvertor()));
|
||||
}
|
||||
|
||||
private static List<String> prepareParameters(File file, SVNDepth depth, boolean makeParents, boolean includeIgnored, boolean force) {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
CommandUtil.put(parameters, file);
|
||||
CommandUtil.put(parameters, depth);
|
||||
CommandUtil.put(parameters, makeParents, "--parents");
|
||||
CommandUtil.put(parameters, includeIgnored, "--no-ignore");
|
||||
CommandUtil.put(parameters, force, "--force");
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static class AddStatusConvertor implements Convertor<Matcher, SVNEvent> {
|
||||
@Override
|
||||
public SVNEvent convert(Matcher o) {
|
||||
SVNStatusType contentStatus = CommandUtil.getStatusType(o.group(1));
|
||||
String path = o.group(3);
|
||||
|
||||
return new SVNEvent(new File(path), null, null, 0, contentStatus, null, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.jetbrains.idea.svn.add;
|
||||
|
||||
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.tmatesoft.svn.core.SVNDepth;
|
||||
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 SvnKitAddClient extends BaseSvnClient implements AddClient {
|
||||
|
||||
@Override
|
||||
public void add(@NotNull File file,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean makeParents,
|
||||
boolean includeIgnored,
|
||||
boolean force,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException {
|
||||
try {
|
||||
SVNWCClient client = myVcs.createWCClient();
|
||||
|
||||
client.setEventHandler(handler);
|
||||
client.doAdd(file, force,
|
||||
false, // directory should already be created
|
||||
makeParents, // not used but will be passed as makeParents value
|
||||
SVNDepth.recurseFromDepth(depth));
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.jetbrains.idea.svn.annotate;
|
||||
|
||||
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.ISVNAnnotateHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNDiffOptions;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface AnnotateClient extends SvnClient {
|
||||
|
||||
void annotate(@NotNull SvnTarget target,
|
||||
@NotNull SVNRevision startRevision,
|
||||
@NotNull SVNRevision endRevision,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
boolean includeMergedRevisions,
|
||||
@Nullable SVNDiffOptions diffOptions,
|
||||
@Nullable ISVNAnnotateHandler handler) throws VcsException;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package org.jetbrains.idea.svn.annotate;
|
||||
|
||||
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.SvnCommand;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.ISVNAnnotateHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNDiffOptions;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdAnnotateClient extends BaseSvnClient implements AnnotateClient {
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull SvnTarget target,
|
||||
@NotNull SVNRevision startRevision,
|
||||
@NotNull SVNRevision endRevision,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
boolean includeMergedRevisions,
|
||||
@Nullable SVNDiffOptions diffOptions,
|
||||
@Nullable final ISVNAnnotateHandler handler) throws VcsException {
|
||||
// TODO: after merge remove setting includeMergedRevisions to false and update parsing
|
||||
includeMergedRevisions = false;
|
||||
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
CommandUtil.put(parameters, target.getPathOrUrlString(), pegRevision);
|
||||
parameters.add("--revision");
|
||||
parameters.add(startRevision + ":" + endRevision);
|
||||
CommandUtil.put(parameters, includeMergedRevisions, "--use-merge-history");
|
||||
CommandUtil.put(parameters, diffOptions);
|
||||
parameters.add("--xml");
|
||||
|
||||
SvnCommand command = CommandUtil.execute(myVcs, SvnCommandName.blame, parameters, null);
|
||||
|
||||
parseOutput(command.getOutput(), handler);
|
||||
}
|
||||
|
||||
public void parseOutput(@NotNull String output, @Nullable ISVNAnnotateHandler handler) throws VcsException {
|
||||
try {
|
||||
JAXBContext context = JAXBContext.newInstance(BlameInfo.class);
|
||||
Unmarshaller unmarshaller = context.createUnmarshaller();
|
||||
BlameInfo info = (BlameInfo)unmarshaller.unmarshal(new StringReader(output));
|
||||
|
||||
if (handler != null && info != null && info.target != null && info.target.lineEntries != null) {
|
||||
for (LineEntry entry : info.target.lineEntries) {
|
||||
invokeHandler(handler, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JAXBException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void invokeHandler(ISVNAnnotateHandler handler, LineEntry entry) throws SVNException {
|
||||
// line numbers in our api start from 0 - not from 1 like in svn output
|
||||
handler.handleLine(entry.date(), entry.revision(), entry.author(), null, null, 0, null, null, entry.lineNumber - 1);
|
||||
}
|
||||
|
||||
@XmlRootElement(name = "blame")
|
||||
public static class BlameInfo {
|
||||
|
||||
@XmlElement(name = "target")
|
||||
public TargetEntry target;
|
||||
}
|
||||
|
||||
public static class TargetEntry {
|
||||
|
||||
@XmlElement(name = "entry")
|
||||
List<LineEntry> lineEntries;
|
||||
}
|
||||
|
||||
public static class LineEntry {
|
||||
|
||||
@XmlAttribute(name = "line-number")
|
||||
public int lineNumber;
|
||||
|
||||
@XmlElement(name = "commit")
|
||||
public CommitEntry commit;
|
||||
|
||||
public long revision() {
|
||||
return commit != null ? commit.revision : 0;
|
||||
}
|
||||
|
||||
public String author() {
|
||||
return commit != null ? commit.author : null;
|
||||
}
|
||||
|
||||
public Date date() {
|
||||
return commit != null ? commit.date : null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CommitEntry {
|
||||
|
||||
@XmlAttribute(name = "revision")
|
||||
public long revision;
|
||||
|
||||
@XmlElement(name = "author")
|
||||
public String author;
|
||||
|
||||
@XmlElement(name = "date")
|
||||
public Date date;
|
||||
}
|
||||
}
|
||||
@@ -32,14 +32,16 @@ import com.intellij.openapi.vcs.history.*;
|
||||
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.*;
|
||||
import org.jetbrains.idea.svn.history.HistoryClient;
|
||||
import org.jetbrains.idea.svn.history.SvnChangeList;
|
||||
import org.jetbrains.idea.svn.history.SvnFileRevision;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -89,9 +91,8 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
|
||||
final String contents;
|
||||
if (loadExternally) {
|
||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
myVcs.createWCClient().doGetFileContents(ioFile, SVNRevision.UNDEFINED, SVNRevision.BASE, true, buffer);
|
||||
contents = LoadTextUtil.getTextByBinaryPresentation(buffer.toByteArray(), file, false, false).toString();
|
||||
byte[] data = SvnUtil.getFileContents(myVcs, SvnTarget.fromFile(ioFile), SVNRevision.BASE, SVNRevision.UNDEFINED);
|
||||
contents = LoadTextUtil.getTextByBinaryPresentation(data, file, false, false).toString();
|
||||
} else {
|
||||
final byte[] bytes = VcsHistoryUtil.loadRevisionContent(revision);
|
||||
contents = LoadTextUtil.getTextByBinaryPresentation(bytes, file, false, false).toString();
|
||||
@@ -99,16 +100,13 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
|
||||
final SvnFileAnnotation result = new SvnFileAnnotation(myVcs, file, contents, lastChangedRevision);
|
||||
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
info = wcClient.doInfo(ioFile, SVNRevision.UNDEFINED);
|
||||
info = myVcs.getInfo(ioFile);
|
||||
if (info == null) {
|
||||
exception[0] = new VcsException(new SVNException(SVNErrorMessage.create(SVNErrorCode.UNKNOWN, "File ''{0}'' is not under version control", ioFile)));
|
||||
return;
|
||||
}
|
||||
final String url = info.getURL() == null ? null : info.getURL().toString();
|
||||
|
||||
SVNLogClient client = myVcs.createLogClient();
|
||||
setLogClientOptions(client);
|
||||
SVNRevision endRevision = ((SvnFileRevision) revision).getRevision();
|
||||
if (SVNRevision.WORKING.equals(endRevision)) {
|
||||
endRevision = info.getRevision();
|
||||
@@ -124,12 +122,19 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
SvnUtil.checkRepositoryVersion15(myVcs, url);
|
||||
final SVNRevision svnRevision = ((SvnRevisionNumber)revision.getRevisionNumber()).getRevision();
|
||||
|
||||
final MySteppedLogGetter logGetter = new MySteppedLogGetter(myVcs, ioFile, progress, client, endRevision, result, url, calculateMergeinfo, file.getCharset());
|
||||
final MySteppedLogGetter logGetter = new MySteppedLogGetter(
|
||||
myVcs, ioFile, progress,
|
||||
myVcs.getFactory(ioFile).createHistoryClient(), endRevision, result,
|
||||
url, calculateMergeinfo, file.getCharset());
|
||||
|
||||
logGetter.go();
|
||||
final LinkedList<SVNRevision> rp = logGetter.getRevisionPoints();
|
||||
|
||||
// TODO: only 2 elements will be in rp and for loop will be executed only once - probably rewrite with Pair
|
||||
AnnotateClient annotateClient = myVcs.getFactory(ioFile).createAnnotateClient();
|
||||
for (int i = 0; i < rp.size() - 1; i++) {
|
||||
client.doAnnotate(ioFile, svnRevision, rp.get(i + 1), rp.get(i), true, calculateMergeinfo, annotateHandler, null);
|
||||
annotateClient.annotate(SvnTarget.fromFile(ioFile), rp.get(i + 1), rp.get(i), svnRevision, calculateMergeinfo,
|
||||
getLogClientOptions(myVcs), annotateHandler);
|
||||
}
|
||||
|
||||
if (rp.get(1).getNumber() > 0) {
|
||||
@@ -137,31 +142,15 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
}
|
||||
annotation[0] = result;
|
||||
}
|
||||
catch (SVNException e) {
|
||||
if (SVNErrorCode.FS_NOT_FOUND.equals(e.getErrorMessage().getErrorCode())) {
|
||||
final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> provider = myVcs.getCommittedChangesProvider();
|
||||
try {
|
||||
final Pair<SvnChangeList, FilePath> pair = provider.getOneList(file, revision.getRevisionNumber());
|
||||
if (pair != null && info != null && pair.getSecond() != null && ! Comparing.equal(pair.getSecond().getIOFile(), ioFile)) {
|
||||
annotation[0] = annotateNonExisting(pair, revision, info, file.getCharset(), file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (VcsException e1) {
|
||||
exception[0] = e1;
|
||||
}
|
||||
catch (SVNException e1) {
|
||||
exception[0] = new VcsException(e);
|
||||
}
|
||||
catch (IOException e1) {
|
||||
exception[0] = new VcsException(e);
|
||||
}
|
||||
}
|
||||
exception[0] = new VcsException(e);
|
||||
} catch (IOException e) {
|
||||
catch (IOException e) {
|
||||
exception[0] = new VcsException(e);
|
||||
} catch (VcsException e) {
|
||||
exception[0] = e;
|
||||
if (e.getCause() instanceof SVNException) {
|
||||
handleSvnException(ioFile, info, (SVNException)e.getCause(), file, revision, annotation, exception);
|
||||
}
|
||||
else {
|
||||
exception[0] = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -177,6 +166,35 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
return annotation[0];
|
||||
}
|
||||
|
||||
private void handleSvnException(File ioFile,
|
||||
SVNInfo info,
|
||||
SVNException e,
|
||||
VirtualFile file,
|
||||
VcsFileRevision revision,
|
||||
FileAnnotation[] annotation, VcsException[] exception) {
|
||||
// TODO: Check how this scenario could be reproduced by user and what changes needs to be done for command line client
|
||||
if (SVNErrorCode.FS_NOT_FOUND.equals(e.getErrorMessage().getErrorCode())) {
|
||||
final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> provider = myVcs.getCommittedChangesProvider();
|
||||
try {
|
||||
final Pair<SvnChangeList, FilePath> pair = provider.getOneList(file, revision.getRevisionNumber());
|
||||
if (pair != null && info != null && pair.getSecond() != null && ! Comparing.equal(pair.getSecond().getIOFile(), ioFile)) {
|
||||
annotation[0] = annotateNonExisting(pair, revision, info, file.getCharset(), file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (VcsException e1) {
|
||||
exception[0] = e1;
|
||||
}
|
||||
catch (SVNException e1) {
|
||||
exception[0] = new VcsException(e);
|
||||
}
|
||||
catch (IOException e1) {
|
||||
exception[0] = new VcsException(e);
|
||||
}
|
||||
}
|
||||
exception[0] = new VcsException(e);
|
||||
}
|
||||
|
||||
public static File getCommonAncestor(final File file1, final File file2) throws IOException {
|
||||
if (FileUtil.filesEqual(file1, file2)) return file1;
|
||||
final File can1 = file1.getCanonicalFile();
|
||||
@@ -214,8 +232,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
final String relativePath = FileUtil.getRelativePath(root.getPath(), wasFile.getPath(), File.separatorChar);
|
||||
if (relativePath == null) throw new VcsException("Can not find relative path for " + wasFile.getPath() + "@" + revision.getRevisionNumber().asString());
|
||||
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
SVNInfo wcRootInfo = wcClient.doInfo(root, SVNRevision.UNDEFINED);
|
||||
SVNInfo wcRootInfo = myVcs.getInfo(root);
|
||||
if (wcRootInfo == null || wcRootInfo.getURL() == null) {
|
||||
throw new VcsException("Can not find relative path for " + wasFile.getPath() + "@" + revision.getRevisionNumber().asString());
|
||||
}
|
||||
@@ -225,21 +242,18 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
wasUrl = wasUrl.appendPath(string, true);
|
||||
}
|
||||
|
||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
final SVNRevision svnRevision = ((SvnRevisionNumber)revision.getRevisionNumber()).getRevision();
|
||||
myVcs.createWCClient().doGetFileContents(wasUrl, svnRevision, svnRevision, true, buffer);
|
||||
final String contents = LoadTextUtil.getTextByBinaryPresentation(buffer.toByteArray(),
|
||||
charset == null ? CharsetToolkit.UTF8_CHARSET : charset).toString();
|
||||
SVNLogClient client = myVcs.createLogClient();
|
||||
setLogClientOptions(client);
|
||||
byte[] data = SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(wasUrl), svnRevision, svnRevision);
|
||||
final String contents = LoadTextUtil.getTextByBinaryPresentation(data, charset == null ? CharsetToolkit.UTF8_CHARSET : charset).toString();
|
||||
final SvnRemoteFileAnnotation result = new SvnRemoteFileAnnotation(myVcs, contents, revision.getRevisionNumber(), pair.getFirst(),
|
||||
pair.getSecond().getPath(), current);
|
||||
final ISVNAnnotateHandler annotateHandler = createAnnotationHandler(ProgressManager.getInstance().getProgressIndicator(), result);
|
||||
|
||||
final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE &&
|
||||
SvnUtil.checkRepositoryVersion15(myVcs, wasUrl.toString());
|
||||
client.doAnnotate(wasUrl, svnRevision, SVNRevision.create(1), svnRevision, true, calculateMergeinfo, annotateHandler, null);
|
||||
|
||||
AnnotateClient client = myVcs.getFactory().createAnnotateClient();
|
||||
client.annotate(SvnTarget.fromURL(wasUrl), SVNRevision.create(1), svnRevision, svnRevision, calculateMergeinfo,
|
||||
getLogClientOptions(myVcs), annotateHandler);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -370,14 +384,14 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
private final SvnVcs myVcs;
|
||||
private final File myIoFile;
|
||||
private final ProgressIndicator myProgress;
|
||||
private final SVNLogClient myClient;
|
||||
private final HistoryClient myClient;
|
||||
private final SVNRevision myEndRevision;
|
||||
private final boolean myCalculateMergeinfo;
|
||||
private final SvnFileAnnotation myResult;
|
||||
private final String myUrl;
|
||||
private final Charset myCharset;
|
||||
|
||||
private MySteppedLogGetter(final SvnVcs vcs, final File ioFile, final ProgressIndicator progress, final SVNLogClient client,
|
||||
private MySteppedLogGetter(final SvnVcs vcs, final File ioFile, final ProgressIndicator progress, final HistoryClient client,
|
||||
final SVNRevision endRevision,
|
||||
final SvnFileAnnotation result,
|
||||
final String url,
|
||||
@@ -395,7 +409,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
myRevisionPoints = new LinkedList<SVNRevision>();
|
||||
}
|
||||
|
||||
public void go() throws SVNException {
|
||||
public void go() throws VcsException {
|
||||
final int maxAnnotateRevisions = SvnConfiguration.getInstance(myVcs.getProject()).getMaxAnnotateRevisions();
|
||||
boolean longHistory = true;
|
||||
if (maxAnnotateRevisions == -1) {
|
||||
@@ -437,8 +451,8 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
myRevisionPoints.add(SVNRevision.create(0));
|
||||
}
|
||||
|
||||
private void doLog(final boolean includeMerged, final SVNRevision truncateTo, final int max) throws SVNException {
|
||||
myClient.doLog(new File[]{myIoFile}, myEndRevision, truncateTo == null ? SVNRevision.create(1L) : truncateTo,
|
||||
private void doLog(final boolean includeMerged, final SVNRevision truncateTo, final int max) throws VcsException {
|
||||
myClient.doLog(myIoFile, myEndRevision, truncateTo == null ? SVNRevision.create(1L) : truncateTo,
|
||||
SVNRevision.UNDEFINED, false, false, includeMerged, max, null,
|
||||
new ISVNLogEntryHandler() {
|
||||
public void handleLogEntry(SVNLogEntry logEntry) {
|
||||
@@ -464,9 +478,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setLogClientOptions(final SVNLogClient client) {
|
||||
if (SvnConfiguration.getInstance(myVcs.getProject()).IGNORE_SPACES_IN_ANNOTATE) {
|
||||
client.setDiffOptions(new SVNDiffOptions(true, true, true));
|
||||
}
|
||||
private static SVNDiffOptions getLogClientOptions(@NotNull SvnVcs vcs) {
|
||||
return SvnConfiguration.getInstance(vcs.getProject()).IGNORE_SPACES_IN_ANNOTATE ? new SVNDiffOptions(true, true, true) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.jetbrains.idea.svn.annotate;
|
||||
|
||||
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.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.ISVNAnnotateHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNDiffOptions;
|
||||
import org.tmatesoft.svn.core.wc.SVNLogClient;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitAnnotateClient extends BaseSvnClient implements AnnotateClient {
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull SvnTarget target,
|
||||
@NotNull SVNRevision startRevision,
|
||||
@NotNull SVNRevision endRevision,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
boolean includeMergedRevisions,
|
||||
@Nullable SVNDiffOptions diffOptions,
|
||||
@Nullable ISVNAnnotateHandler handler) throws VcsException {
|
||||
try {
|
||||
SVNLogClient client = myVcs.createLogClient();
|
||||
|
||||
client.setDiffOptions(diffOptions);
|
||||
if (target.isFile()) {
|
||||
client.doAnnotate(target.getFile(), pegRevision, startRevision, endRevision, true, includeMergedRevisions, handler, null);
|
||||
}
|
||||
else {
|
||||
client.doAnnotate(target.getURL(), pegRevision, startRevision, endRevision, true, includeMergedRevisions, handler, null);
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.jetbrains.idea.svn.api;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public abstract class BaseSvnClient implements SvnClient {
|
||||
protected SvnVcs myVcs;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SvnVcs getVcs() {
|
||||
return myVcs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVcs(@NotNull SvnVcs vcs) {
|
||||
myVcs = vcs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package org.jetbrains.idea.svn.api;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.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.portable.SvnStatusClientI;
|
||||
import org.jetbrains.idea.svn.properties.PropertyClient;
|
||||
import org.jetbrains.idea.svn.revert.RevertClient;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public abstract class ClientFactory {
|
||||
|
||||
@NotNull
|
||||
protected SvnVcs myVcs;
|
||||
|
||||
protected AddClient addClient;
|
||||
protected AnnotateClient annotateClient;
|
||||
protected ContentClient contentClient;
|
||||
protected HistoryClient historyClient;
|
||||
protected RevertClient revertClient;
|
||||
protected DeleteClient deleteClient;
|
||||
protected SvnStatusClientI statusClient;
|
||||
protected CopyMoveClient copyMoveClient;
|
||||
protected ConflictClient conflictClient;
|
||||
protected PropertyClient propertyClient;
|
||||
|
||||
protected ClientFactory(@NotNull SvnVcs vcs) {
|
||||
myVcs = vcs;
|
||||
setup();
|
||||
}
|
||||
|
||||
protected abstract void setup();
|
||||
|
||||
@NotNull
|
||||
public AddClient createAddClient() {
|
||||
return prepare(addClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AnnotateClient createAnnotateClient() {
|
||||
return prepare(annotateClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ContentClient createContentClient() {
|
||||
return prepare(contentClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public HistoryClient createHistoryClient() {
|
||||
return prepare(historyClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public RevertClient createRevertClient() {
|
||||
return prepare(revertClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SvnStatusClientI createStatusClient() {
|
||||
// TODO: Update this in same like other clients - move to corresponding package, rename clients
|
||||
return statusClient;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DeleteClient createDeleteClient() {
|
||||
return prepare(deleteClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CopyMoveClient createCopyMoveClient() {
|
||||
return prepare(copyMoveClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ConflictClient createConflictClient() {
|
||||
return prepare(conflictClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PropertyClient createPropertyClient() {
|
||||
return prepare(propertyClient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected <T extends SvnClient> T prepare(@NotNull T client) {
|
||||
client.setVcs(myVcs);
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.jetbrains.idea.svn.api;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.commandLine.SvnCommandLineStatusClient;
|
||||
import org.jetbrains.idea.svn.conflict.CmdConflictClient;
|
||||
import org.jetbrains.idea.svn.content.CmdContentClient;
|
||||
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.properties.CmdPropertyClient;
|
||||
import org.jetbrains.idea.svn.revert.CmdRevertClient;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdClientFactory extends ClientFactory {
|
||||
|
||||
public CmdClientFactory(@NotNull SvnVcs vcs) {
|
||||
super(vcs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
addClient = new CmdAddClient();
|
||||
annotateClient = new CmdAnnotateClient();
|
||||
contentClient = new CmdContentClient();
|
||||
historyClient = new CmdHistoryClient();
|
||||
revertClient = new CmdRevertClient();
|
||||
deleteClient = new CmdDeleteClient();
|
||||
copyMoveClient = new CmdCopyMoveClient();
|
||||
conflictClient = new CmdConflictClient();
|
||||
propertyClient = new CmdPropertyClient();
|
||||
statusClient = new SvnCommandLineStatusClient(myVcs.getProject());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.jetbrains.idea.svn.api;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
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.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class FileStatusResultParser {
|
||||
|
||||
private static final double DEFAULT_PROGRESS = 0.0;
|
||||
|
||||
@NotNull
|
||||
private Pattern myLinePattern;
|
||||
|
||||
@Nullable
|
||||
private ISVNEventHandler handler;
|
||||
|
||||
@NotNull
|
||||
private Convertor<Matcher, SVNEvent> myConvertor;
|
||||
|
||||
public FileStatusResultParser(@NotNull Pattern linePattern,
|
||||
@Nullable ISVNEventHandler handler,
|
||||
@NotNull Convertor<Matcher, SVNEvent> convertor) {
|
||||
myLinePattern = linePattern;
|
||||
this.handler = handler;
|
||||
myConvertor = convertor;
|
||||
}
|
||||
|
||||
public void parse(@NotNull String output) throws VcsException {
|
||||
if (StringUtil.isEmpty(output)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String line : StringUtil.splitByLines(output)) {
|
||||
onLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
public void onLine(@NotNull String line) throws VcsException {
|
||||
Matcher matcher = myLinePattern.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
process(matcher);
|
||||
}
|
||||
else {
|
||||
throw new VcsException("unknown state on line " + line);
|
||||
}
|
||||
}
|
||||
|
||||
public void process(@NotNull Matcher matcher) throws VcsException {
|
||||
if (handler != null) {
|
||||
try {
|
||||
handler.handleEvent(myConvertor.convert(matcher), DEFAULT_PROGRESS);
|
||||
} catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.jetbrains.idea.svn.api;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface SvnClient {
|
||||
|
||||
@NotNull
|
||||
SvnVcs getVcs();
|
||||
|
||||
void setVcs(@NotNull SvnVcs vcs);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.jetbrains.idea.svn.api;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.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.portable.SvnkitSvnStatusClient;
|
||||
import org.jetbrains.idea.svn.properties.SvnKitPropertyClient;
|
||||
import org.jetbrains.idea.svn.revert.SvnKitRevertClient;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitClientFactory extends ClientFactory {
|
||||
|
||||
public SvnKitClientFactory(@NotNull SvnVcs vcs) {
|
||||
super(vcs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
addClient = new SvnKitAddClient();
|
||||
annotateClient = new SvnKitAnnotateClient();
|
||||
contentClient = new SvnKitContentClient();
|
||||
historyClient = new SvnKitHistoryClient();
|
||||
revertClient = new SvnKitRevertClient();
|
||||
deleteClient = new SvnKitDeleteClient();
|
||||
copyMoveClient = new SvnKitCopyMoveClient();
|
||||
conflictClient = new SvnKitConflictClient();
|
||||
propertyClient = new SvnKitPropertyClient();
|
||||
statusClient = new SvnkitSvnStatusClient(myVcs.createStatusClient());
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class DefaultConfigLoader {
|
||||
final SvnVcs vcs = SvnVcs.getInstance(project);
|
||||
|
||||
File rootFile = new File(vcsRoot.getPath());
|
||||
final SVNInfo info = vcs.createWCClient().doInfo(rootFile, SVNRevision.UNDEFINED);
|
||||
final SVNInfo info = vcs.getInfo(rootFile);
|
||||
if (info == null || info.getURL() == null) {
|
||||
LOG.info("Directory is not a working copy: " + vcsRoot.getPresentableUrl());
|
||||
return null;
|
||||
|
||||
+2
-3
@@ -223,9 +223,8 @@ public class SvnBranchConfigurationNew {
|
||||
private BranchRootSearcher(final SvnVcs vcs, final VirtualFile root) throws SVNException {
|
||||
myRoot = root;
|
||||
myBranchesUnder = new HashMap<String, String>();
|
||||
final SVNWCClient client = vcs.createWCClient();
|
||||
final SVNInfo info = client.doInfo(new File(myRoot.getPath()), SVNRevision.UNDEFINED);
|
||||
myRootUrl = info.getURL();
|
||||
final SVNInfo info = vcs.getInfo(myRoot.getPath());
|
||||
myRootUrl = info != null ? info.getURL() : null;
|
||||
}
|
||||
|
||||
public boolean accept(final String url) throws SVNException {
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package org.jetbrains.idea.svn.checkin;
|
||||
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import org.jetbrains.idea.svn.CommitEventHandler;
|
||||
import org.jetbrains.idea.svn.CommitEventType;
|
||||
import org.jetbrains.idea.svn.commandLine.CommitEventHandler;
|
||||
import org.jetbrains.idea.svn.commandLine.CommitEventType;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
+17
@@ -28,6 +28,7 @@ import com.intellij.util.net.HttpConfigurable;
|
||||
import com.intellij.util.proxy.CommonProxy;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.*;
|
||||
import org.jetbrains.idea.svn.commandLine.AuthenticationCallback;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.auth.*;
|
||||
import org.tmatesoft.svn.core.internal.util.SVNBase64;
|
||||
@@ -77,6 +78,20 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall
|
||||
return new CredentialsAuthenticator(myVcs).tryAuthenticate(realm, url, file, previousFailed, passwordRequest);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SVNAuthentication requestCredentials(@Nullable SVNURL url, String type) {
|
||||
SVNAuthentication authentication =
|
||||
url != null ? myVcs.getSvnConfiguration().getInteractiveManager(myVcs).getProvider().requestClientAuthentication(
|
||||
type, url, url.toDecodedString(), null, null, true) : null;
|
||||
|
||||
if (authentication == null) {
|
||||
LOG.warn("Could not get authentication. Type - " + type + ", Url - " + url);
|
||||
}
|
||||
|
||||
return authentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptSSLServerCertificate(final File file, final String realm) {
|
||||
final File base = getExistingParent(file);
|
||||
@@ -354,7 +369,9 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall
|
||||
}, new ThrowableRunnable<SVNException>() {
|
||||
@Override
|
||||
public void run() throws SVNException {
|
||||
// NOTE: DO NOT replace this call - SSL authentication highly tied to SVNKit
|
||||
myVcs.createWCClient(active).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
|
||||
//myVcs.getInfo(myUrl, SVNRevision.HEAD, active);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -48,8 +48,8 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.*;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnBindClient;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
|
||||
import org.tigris.subversion.javahl.ClientException;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
|
||||
@@ -177,7 +177,7 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
|
||||
if (committables.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format) &&
|
||||
if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) || WorkingCopyFormat.ONE_DOT_SEVEN.equals(format) &&
|
||||
SvnConfiguration.UseAcceleration.commandLine.equals(SvnConfiguration.getInstance(mySvnVcs.getProject()).myUseAcceleration) &&
|
||||
(SvnAuthenticationManager.HTTP.equals(url.getProtocol()) || SvnAuthenticationManager.HTTPS.equals(url.getProtocol()))) {
|
||||
doWithCommandLine(committables, comment, exception, feedback);
|
||||
@@ -256,14 +256,25 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
|
||||
});
|
||||
final IdeaSvnkitBasedAuthenticationCallback authenticationCallback = new IdeaSvnkitBasedAuthenticationCallback(mySvnVcs);
|
||||
try {
|
||||
final SvnBindClient client = new SvnBindClient(SvnApplicationSettings.getInstance().getCommandLinePath());
|
||||
final SvnBindClient client = new SvnBindClient(SvnApplicationSettings.getInstance().getCommandLinePath(), new Convertor<String[], SVNURL>() {
|
||||
@Override
|
||||
public SVNURL convert(String[] o) {
|
||||
SVNInfo info = o.length > 0 ? mySvnVcs.getInfo(o[0]) : null;
|
||||
|
||||
if (info == null || info.getURL() == null) {
|
||||
LOG.warn("Could not resolve repository url for commit. Paths - " + Arrays.toString(o));
|
||||
}
|
||||
|
||||
return info != null ? info.getURL() : null;
|
||||
}
|
||||
});
|
||||
client.setAuthenticationCallback(authenticationCallback);
|
||||
client.setHandler(new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()));
|
||||
final long revision = client.commit(ArrayUtil.toStringArray(paths), comment, false, false);
|
||||
reportCommittedRevisions(feedback, String.valueOf(revision));
|
||||
}
|
||||
catch (ClientException e) {
|
||||
exception.add(new VcsException(e));
|
||||
catch (VcsException e) {
|
||||
exception.add(e);
|
||||
} finally {
|
||||
authenticationCallback.reset();
|
||||
}
|
||||
@@ -348,25 +359,19 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
|
||||
private List<File> getCommitables(List<File> paths) {
|
||||
final Adder adder = new Adder();
|
||||
|
||||
SVNStatusClient statusClient = mySvnVcs.createStatusClient();
|
||||
for (File path : paths) {
|
||||
File file = path.getAbsoluteFile();
|
||||
adder.add(file);
|
||||
if (file.getParentFile() != null) {
|
||||
addParents(statusClient, file.getParentFile(), adder);
|
||||
addParents(file.getParentFile(), adder);
|
||||
}
|
||||
}
|
||||
return adder.getResult();
|
||||
}
|
||||
|
||||
private static void addParents(SVNStatusClient statusClient, File file, final Adder adder) {
|
||||
SVNStatus status;
|
||||
try {
|
||||
status = statusClient.doStatus(file, false);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return;
|
||||
}
|
||||
private void addParents(File file, final Adder adder) {
|
||||
SVNStatus status = getStatus(file);
|
||||
|
||||
if (status != null &&
|
||||
(SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_ADDED) ||
|
||||
SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_REPLACED))) {
|
||||
@@ -374,11 +379,33 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
|
||||
adder.add(file);
|
||||
file = file.getParentFile();
|
||||
if (file != null) {
|
||||
addParents(statusClient, file, adder);
|
||||
addParents(file, adder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SVNStatus getStatus(File file) {
|
||||
SVNStatus result = null;
|
||||
WorkingCopyFormat format = mySvnVcs.getWorkingCopyFormat(file);
|
||||
|
||||
try {
|
||||
result = WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) ? getStatusCommandLine(file) : getStatusSvnKit(file);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private SVNStatus getStatusSvnKit(File file) throws SVNException {
|
||||
return mySvnVcs.createStatusClient().doStatus(file, false);
|
||||
}
|
||||
|
||||
private SVNStatus getStatusCommandLine(File file) throws SVNException {
|
||||
return new SvnCommandLineStatusClient(mySvnVcs.getProject()).doStatus(file, false);
|
||||
}
|
||||
|
||||
private static List<File> collectPaths(final List<Change> changes) {
|
||||
// case sensitive..
|
||||
ArrayList<File> result = new ArrayList<File>();
|
||||
@@ -418,15 +445,14 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
|
||||
|
||||
public List<VcsException> scheduleMissingFileForDeletion(List<FilePath> filePaths) {
|
||||
List<VcsException> exceptions = new ArrayList<VcsException>();
|
||||
final SVNWCClient wcClient = mySvnVcs.createWCClient();
|
||||
|
||||
List<File> files = ChangesUtil.filePathsToFiles(filePaths);
|
||||
|
||||
for (File file : files) {
|
||||
try {
|
||||
wcClient.doDelete(file, true, false);
|
||||
mySvnVcs.getFactory(file).createDeleteClient().delete(file, true);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
exceptions.add(new VcsException(e));
|
||||
catch (VcsException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,30 +460,22 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
|
||||
}
|
||||
|
||||
public List<VcsException> scheduleUnversionedFilesForAddition(List<VirtualFile> files) {
|
||||
final List<VcsException> result = new ArrayList<VcsException>();
|
||||
final SVNWCClient wcClient = mySvnVcs.createWCClient();
|
||||
|
||||
final List<SVNException> exceptionList = scheduleUnversionedFilesForAddition(wcClient, files);
|
||||
for (SVNException svnException : exceptionList) {
|
||||
result.add(new VcsException(svnException));
|
||||
}
|
||||
return result;
|
||||
return scheduleUnversionedFilesForAddition(mySvnVcs, files);
|
||||
}
|
||||
|
||||
public static List<SVNException> scheduleUnversionedFilesForAddition(SVNWCClient wcClient, List<VirtualFile> files) {
|
||||
return scheduleUnversionedFilesForAddition(wcClient, files, false);
|
||||
public static List<VcsException> scheduleUnversionedFilesForAddition(@NotNull SvnVcs vcs, List<VirtualFile> files) {
|
||||
return scheduleUnversionedFilesForAddition(vcs, files, false);
|
||||
}
|
||||
|
||||
public static List<SVNException> scheduleUnversionedFilesForAddition(SVNWCClient wcClient, List<VirtualFile> files, final boolean recursive) {
|
||||
List<SVNException> exceptions = new ArrayList<SVNException>();
|
||||
|
||||
public static List<VcsException> scheduleUnversionedFilesForAddition(@NotNull SvnVcs vcs, List<VirtualFile> files, final boolean recursive) {
|
||||
Collections.sort(files, FilePathComparator.getInstance());
|
||||
|
||||
wcClient.setEventHandler(new ISVNEventHandler() {
|
||||
ISVNEventHandler eventHandler = new ISVNEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(SVNEvent event, double progress) throws SVNException {
|
||||
final ProgressManager pm = ProgressManager.getInstance();
|
||||
final ProgressIndicator pi = pm.getProgressIndicator();
|
||||
// TODO: pi is null here when invoking "Add" action
|
||||
if (pi != null && event.getFile() != null) {
|
||||
File file = event.getFile();
|
||||
pi.setText(SvnBundle.message("progress.text2.adding", file.getName() + " (" + file.getParent() + ")"));
|
||||
@@ -472,12 +490,18 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
|
||||
if (pi.isCanceled()) throw new SVNCancelException();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
List<VcsException> exceptions = new ArrayList<VcsException>();
|
||||
|
||||
for (VirtualFile file : files) {
|
||||
try {
|
||||
wcClient.doAdd(new File(FileUtil.toSystemDependentName(file.getPath())), true, false, true, recursive);
|
||||
File convertedFile = new File(FileUtil.toSystemDependentName(file.getPath()));
|
||||
SVNDepth depth = recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY;
|
||||
|
||||
vcs.getFactory(convertedFile).createAddClient().add(convertedFile, depth, true, false, true, eventHandler);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
catch (VcsException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-1
@@ -13,9 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn;
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.auth.SVNAuthentication;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -50,6 +52,17 @@ public interface AuthenticationCallback {
|
||||
*/
|
||||
boolean authenticateFor(@Nullable String realm, File base, boolean previousFailed, boolean passwordRequest);
|
||||
|
||||
/**
|
||||
* Provides authentication information to access given url by authentication protocol identified by type.
|
||||
* For instance, username/password for http/svn protocols. SSL client certificate for two way SSL protocol.
|
||||
*
|
||||
* @param url url to item in repository
|
||||
* @param type authentication protocol type with svn specific values, like "svn.simple" for http.
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
SVNAuthentication requestCredentials(@Nullable SVNURL url, String type);
|
||||
|
||||
/**
|
||||
* @return config directory if TMP was created
|
||||
*/
|
||||
@@ -0,0 +1,218 @@
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.SvnApplicationSettings;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.api.FileStatusResultParser;
|
||||
import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.wc.SVNDiffOptions;
|
||||
import org.tmatesoft.svn.core.wc.SVNInfo;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNStatusType;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CommandUtil {
|
||||
public static SvnLineCommand runSimple(@NotNull SvnCommandName name,
|
||||
@NotNull SvnVcs vcs,
|
||||
@Nullable File base,
|
||||
@Nullable SVNURL url,
|
||||
List<String> parameters)
|
||||
throws SVNException {
|
||||
String exe = resolveExePath();
|
||||
base = resolveBaseDirectory(base, exe);
|
||||
url = resolveRepositoryUrl(vcs, url);
|
||||
|
||||
try {
|
||||
return SvnLineCommand
|
||||
.runWithAuthenticationAttempt(exe, base, url, name, new SvnCommitRunner.CommandListener(null),
|
||||
new IdeaSvnkitBasedAuthenticationCallback(vcs), ArrayUtil.toStringArray(parameters));
|
||||
}
|
||||
catch (SvnBindException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SVNURL resolveRepositoryUrl(@NotNull SvnVcs vcs, @Nullable SVNURL url) {
|
||||
if (url == null) {
|
||||
// TODO: or take it from RootUrlInfo
|
||||
SVNInfo info = vcs.getInfo(vcs.getProject().getBaseDir());
|
||||
|
||||
url = info != null ? info.getURL() : null;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static File resolveBaseDirectory(@Nullable File base, @NotNull String defaultBase) {
|
||||
return base == null ? new File(defaultBase) : base;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String resolveExePath() {
|
||||
return SvnApplicationSettings.getInstance().getCommandLinePath();
|
||||
}
|
||||
|
||||
public static SvnLineCommand runSimple(@NotNull SvnSimpleCommand command, @NotNull SvnVcs vcs, @Nullable File base, @Nullable SVNURL url)
|
||||
throws SVNException {
|
||||
// empty command name passed, as command name is already in command.getParameters()
|
||||
return runSimple(SvnCommandName.empty, vcs, base, url, new ArrayList<String>(Arrays.asList(command.getParameters())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts given value to parameters if condition is satisfied
|
||||
*
|
||||
* @param parameters
|
||||
* @param condition
|
||||
* @param value
|
||||
*/
|
||||
public static void put(@NotNull List<String> parameters, boolean condition, @NotNull String value) {
|
||||
if (condition) {
|
||||
parameters.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void put(@NotNull List<String> parameters, @NotNull File path) {
|
||||
parameters.add(path.getAbsolutePath());
|
||||
}
|
||||
|
||||
public static void put(@NotNull List<String> parameters, @NotNull File path, @Nullable SVNRevision pegRevision) {
|
||||
put(parameters, path.getAbsolutePath(), pegRevision);
|
||||
}
|
||||
|
||||
public static void put(@NotNull List<String> parameters, @NotNull String path, @Nullable SVNRevision pegRevision) {
|
||||
StringBuilder builder = new StringBuilder(path);
|
||||
|
||||
if (pegRevision != null && !SVNRevision.UNDEFINED.equals(pegRevision) && !SVNRevision.WORKING.equals(pegRevision) &&
|
||||
pegRevision.getNumber() > 0) {
|
||||
builder.append("@");
|
||||
builder.append(pegRevision);
|
||||
}
|
||||
|
||||
parameters.add(builder.toString());
|
||||
}
|
||||
|
||||
public static void put(@NotNull List<String> parameters, @NotNull File... paths) {
|
||||
for (File path : paths) {
|
||||
put(parameters, path);
|
||||
}
|
||||
}
|
||||
|
||||
public static void put(@NotNull List<String> parameters, @Nullable SVNDepth depth) {
|
||||
if (depth != null && !SVNDepth.UNKNOWN.equals(depth)) {
|
||||
parameters.add("--depth");
|
||||
parameters.add(depth.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public static void put(@NotNull List<String> parameters, @Nullable SVNRevision revision) {
|
||||
if (revision != null && !SVNRevision.UNDEFINED.equals(revision) && !SVNRevision.WORKING.equals(revision) && revision.getNumber() >= 0) {
|
||||
parameters.add("--revision");
|
||||
parameters.add(revision.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void put(@NotNull List<String> parameters, @Nullable SVNDiffOptions diffOptions) {
|
||||
if (diffOptions != null) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
if (diffOptions.isIgnoreAllWhitespace()) {
|
||||
builder.append(" --ignore-space-change");
|
||||
}
|
||||
if (diffOptions.isIgnoreAmountOfWhitespace()) {
|
||||
builder.append(" --ignore-all-space");
|
||||
}
|
||||
if (diffOptions.isIgnoreEOLStyle()) {
|
||||
builder.append(" --ignore-eol-style");
|
||||
}
|
||||
|
||||
String value = builder.toString().trim();
|
||||
|
||||
if (!StringUtil.isEmpty(value)) {
|
||||
parameters.add("--extensions");
|
||||
parameters.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for running commands changing certain file status information.
|
||||
* // TODO: Should be replaced with non-static analogue.
|
||||
*
|
||||
* @param vcs
|
||||
* @param name
|
||||
* @param parameters
|
||||
* @param parser
|
||||
* @throws VcsException
|
||||
*/
|
||||
public static SvnCommand execute(@NotNull SvnVcs vcs,
|
||||
@NotNull SvnCommandName name,
|
||||
@NotNull List<String> parameters,
|
||||
@Nullable FileStatusResultParser parser)
|
||||
throws VcsException {
|
||||
String exe = resolveExePath();
|
||||
File base = resolveBaseDirectory(null, exe);
|
||||
SVNURL url = resolveRepositoryUrl(vcs, null);
|
||||
|
||||
SvnLineCommand command = SvnLineCommand.runWithAuthenticationAttempt(
|
||||
exe, base, url, name, new SvnCommitRunner.CommandListener(null),
|
||||
new IdeaSvnkitBasedAuthenticationCallback(vcs),
|
||||
ArrayUtil.toStringArray(parameters));
|
||||
|
||||
if (parser != null) {
|
||||
parser.parse(command.getOutput());
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets svn status represented by single character.
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
public static char getStatusChar(@Nullable String type) {
|
||||
return !StringUtil.isEmpty(type) ? type.charAt(0) : ' ';
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static SVNStatusType getStatusType(@Nullable String type) {
|
||||
return getStatusType(getStatusChar(type));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static SVNStatusType getStatusType(char first) {
|
||||
final SVNStatusType contentsStatus;
|
||||
if ('A' == first) {
|
||||
contentsStatus = SVNStatusType.STATUS_ADDED;
|
||||
} else if ('D' == first) {
|
||||
contentsStatus = SVNStatusType.STATUS_DELETED;
|
||||
} else if ('U' == first) {
|
||||
contentsStatus = SVNStatusType.CHANGED;
|
||||
} else if ('C' == first) {
|
||||
contentsStatus = SVNStatusType.CONFLICTED;
|
||||
} else if ('G' == first) {
|
||||
contentsStatus = SVNStatusType.MERGED;
|
||||
} else if ('R' == first) {
|
||||
contentsStatus = SVNStatusType.STATUS_REPLACED;
|
||||
} else if ('E' == first) {
|
||||
contentsStatus = SVNStatusType.STATUS_OBSTRUCTED;
|
||||
} else {
|
||||
contentsStatus = SVNStatusType.STATUS_NORMAL;
|
||||
}
|
||||
return contentsStatus;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn;
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn;
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Irina.Chernushina
|
||||
* Date: 2/5/13
|
||||
* Time: 3:08 PM
|
||||
*/
|
||||
public class SvnBindClient {
|
||||
private final String myExecutablePath;
|
||||
private CommitEventHandler myHandler;
|
||||
private AuthenticationCallback myAuthenticationCallback;
|
||||
private Convertor<String[], SVNURL> myUrlProvider;
|
||||
|
||||
public SvnBindClient(String path, Convertor<String[], SVNURL> urlProvider) {
|
||||
myExecutablePath = path;
|
||||
myUrlProvider = urlProvider;
|
||||
}
|
||||
|
||||
public long commit(String[] path, String message, boolean recurse, boolean noUnlock) throws VcsException {
|
||||
return commit(path, message, recurse? 3 : 0, noUnlock, false, null, null);
|
||||
}
|
||||
|
||||
public long commit(String[] path,
|
||||
String message,
|
||||
int depth,
|
||||
boolean noUnlock,
|
||||
boolean keepChangelist,
|
||||
String[] changelists,
|
||||
Map revpropTable) throws VcsException {
|
||||
final long commit = new SvnCommitRunner(myExecutablePath, myHandler, myAuthenticationCallback).
|
||||
commit(path, message, depth, noUnlock, keepChangelist, changelists, revpropTable, myUrlProvider);
|
||||
if (commit < 0) {
|
||||
throw new VcsException("Wrong committed revision number: " + commit);
|
||||
}
|
||||
return commit;
|
||||
}
|
||||
|
||||
public void setHandler(CommitEventHandler handler) {
|
||||
myHandler = handler;
|
||||
}
|
||||
|
||||
public void setAuthenticationCallback(AuthenticationCallback authenticationCallback) {
|
||||
myAuthenticationCallback = authenticationCallback;
|
||||
}
|
||||
}
|
||||
+1
-19
@@ -13,12 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn.config;
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Irina.Chernushina
|
||||
@@ -32,23 +30,7 @@ public class SvnBindException extends VcsException {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SvnBindException(Throwable throwable, boolean isWarning) {
|
||||
super(throwable, isWarning);
|
||||
}
|
||||
|
||||
public SvnBindException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
public SvnBindException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public SvnBindException(String message, boolean isWarning) {
|
||||
super(message, isWarning);
|
||||
}
|
||||
|
||||
public SvnBindException(Collection<String> messages) {
|
||||
super(messages);
|
||||
}
|
||||
}
|
||||
+2
-24
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn;
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
@@ -31,16 +31,7 @@ import java.util.Locale;
|
||||
* Time: 4:56 PM
|
||||
*/
|
||||
public class SvnBindUtil {
|
||||
/**
|
||||
* SVN_ASP_DOT_NET_HACK allows use of an alternate name for Subversion working copy
|
||||
* administrative directories on Windows (which were formerly always
|
||||
* named ".svn"), by setting the SVN_ASP_DOT_NET_HACK environment variable.
|
||||
* When the variable is set (to any value), the administrative directory
|
||||
* will be "_svn" instead of ".svn".
|
||||
*
|
||||
* http://svn.apache.org/repos/asf/subversion/trunk/notes/asp-dot-net-hack.txt
|
||||
*/
|
||||
public static final String ADM_NAME = System.getenv("SVN_ASP_DOT_NET_HACK") != null ? "_svn" : ".svn";
|
||||
|
||||
private final static List<DateFormat> ourFormats = new ArrayList<DateFormat>();
|
||||
|
||||
static {
|
||||
@@ -88,17 +79,4 @@ public class SvnBindUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static File getWcRoot(File base) {
|
||||
File current = base;
|
||||
while (current != null) {
|
||||
if (getWcDbUnder(current).exists()) return current;
|
||||
current = current.getParentFile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static File getWcDbUnder(final File file) {
|
||||
return new File(file, ADM_NAME + File.separator + "wc.db");
|
||||
}
|
||||
}
|
||||
+48
-5
@@ -16,6 +16,7 @@
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.CapturingProcessAdapter;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessListener;
|
||||
@@ -38,6 +39,7 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class SvnCommand {
|
||||
static final Logger LOG = Logger.getInstance(SvnCommand.class.getName());
|
||||
private final File myConfigDir;
|
||||
|
||||
private boolean myIsDestroyed;
|
||||
private int myExitCode;
|
||||
@@ -45,13 +47,13 @@ public abstract class SvnCommand {
|
||||
private final File myWorkingDirectory;
|
||||
private Process myProcess;
|
||||
private OSProcessHandler myHandler;
|
||||
// TODO: Try to implement commands in a way that they manually indicate if they need full output - to prevent situations
|
||||
// TODO: when large amount of data needs to be stored instead of just sequential processing.
|
||||
private CapturingProcessAdapter outputAdapter;
|
||||
private final Object myLock;
|
||||
|
||||
private final EventDispatcher<ProcessEventListener> myListeners = EventDispatcher.create(ProcessEventListener.class);
|
||||
|
||||
// todo check version
|
||||
/*c:\Program Files (x86)\CollabNet\Subversion Client17>svn --version --quiet
|
||||
1.7.2*/
|
||||
private final SvnCommandName myCommandName;
|
||||
|
||||
public SvnCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath) {
|
||||
this(workingDirectory, commandName, exePath, null);
|
||||
@@ -59,15 +61,34 @@ public abstract class SvnCommand {
|
||||
|
||||
public SvnCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath,
|
||||
@Nullable File configDir) {
|
||||
myCommandName = commandName;
|
||||
myLock = new Object();
|
||||
myCommandLine = new GeneralCommandLine();
|
||||
myWorkingDirectory = workingDirectory;
|
||||
myCommandLine.setExePath(exePath);
|
||||
myCommandLine.setWorkDirectory(workingDirectory);
|
||||
myConfigDir = configDir;
|
||||
if (configDir != null) {
|
||||
myCommandLine.addParameters("--config-dir", configDir.getPath());
|
||||
}
|
||||
myCommandLine.addParameter(commandName.getName());
|
||||
if (!SvnCommandName.empty.equals(commandName)) {
|
||||
myCommandLine.addParameter(commandName.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getParameters() {
|
||||
synchronized (myLock) {
|
||||
return myCommandLine.getParametersList().getArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if process was destroyed "manually" by command execution logic.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isManuallyDestroyed() {
|
||||
return myIsDestroyed;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
@@ -112,10 +133,16 @@ public abstract class SvnCommand {
|
||||
}
|
||||
};
|
||||
|
||||
outputAdapter = new CapturingProcessAdapter();
|
||||
myHandler.addProcessListener(outputAdapter);
|
||||
myHandler.addProcessListener(processListener);
|
||||
myHandler.startNotify();
|
||||
}
|
||||
|
||||
public String getOutput() {
|
||||
return outputAdapter.getOutput().getStdout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for process termination
|
||||
* @param timeout
|
||||
@@ -186,6 +213,18 @@ public abstract class SvnCommand {
|
||||
}
|
||||
}
|
||||
|
||||
public String getCommandText() {
|
||||
synchronized (myLock) {
|
||||
return myCommandLine.getCommandLineString();
|
||||
}
|
||||
}
|
||||
|
||||
public String getExePath() {
|
||||
synchronized (myLock) {
|
||||
return myCommandLine.getExePath();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check that process is not started yet
|
||||
*
|
||||
@@ -226,4 +265,8 @@ public abstract class SvnCommand {
|
||||
protected File getWorkingDirectory() {
|
||||
return myWorkingDirectory;
|
||||
}
|
||||
|
||||
public SvnCommandName getCommandName() {
|
||||
return myCommandName;
|
||||
}
|
||||
}
|
||||
+77
-34
@@ -15,12 +15,13 @@
|
||||
*/
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.idea.svn.SvnBindUtil;
|
||||
import org.jetbrains.idea.svn.SvnApplicationSettings;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.portable.SvnExceptionWrapper;
|
||||
import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient;
|
||||
@@ -36,7 +37,9 @@ import javax.xml.parsers.SAXParserFactory;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
@@ -45,9 +48,12 @@ import java.util.Collection;
|
||||
* Time: 12:59 PM
|
||||
*/
|
||||
public class SvnCommandLineInfoClient extends SvnkitSvnWcClient {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient");
|
||||
private final Project myProject;
|
||||
|
||||
public SvnCommandLineInfoClient(final Project project) {
|
||||
// TODO: Remove svn kit client instantiation
|
||||
super(SvnVcs.getInstance(project).createWCClient());
|
||||
myProject = project;
|
||||
}
|
||||
@@ -74,22 +80,56 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient {
|
||||
base = SvnBindUtil.correctUpToExistingParent(base);
|
||||
if (base == null) {
|
||||
// very unrealistic
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), new RuntimeException("Can not find existing parent file"));
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not find existing parent file"));
|
||||
}
|
||||
final SvnSimpleCommand command = SvnCommandFactory.createSimpleCommand(myProject, base, SvnCommandName.info);
|
||||
issueCommand(path.getAbsolutePath(), pegRevision, revision, depth, changeLists, handler, base);
|
||||
}
|
||||
|
||||
if (depth != null) {
|
||||
command.addParameters("--depth", depth.getName());
|
||||
}
|
||||
if (revision != null && ! SVNRevision.UNDEFINED.equals(revision) && ! SVNRevision.WORKING.equals(revision)) {
|
||||
command.addParameters("-r", revision.toString());
|
||||
}
|
||||
command.addParameters("--xml");
|
||||
private void issueCommand(String path, SVNRevision pegRevision,
|
||||
SVNRevision revision,
|
||||
SVNDepth depth,
|
||||
Collection changeLists,
|
||||
final ISVNInfoHandler handler, File base) throws SVNException {
|
||||
final SvnSimpleCommand command = SvnCommandFactory.createSimpleCommand(myProject, base, SvnCommandName.info);
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
fillParameters(path, pegRevision, revision, depth, parameters);
|
||||
command.addParameters(parameters);
|
||||
SvnCommandLineStatusClient.changelistsToCommand(changeLists, command);
|
||||
if (pegRevision != null && ! SVNRevision.UNDEFINED.equals(pegRevision) && ! SVNRevision.WORKING.equals(pegRevision)) {
|
||||
command.addParameters(path.getPath() + "@" + pegRevision.toString());
|
||||
} else {
|
||||
command.addParameters(path.getPath());
|
||||
|
||||
parseResult(handler, base, execute(command));
|
||||
}
|
||||
|
||||
private String execute(SvnSimpleCommand command) throws SVNException {
|
||||
try {
|
||||
return command.run();
|
||||
}
|
||||
catch (VcsException e) {
|
||||
final String text = e.getMessage();
|
||||
final boolean notEmpty = !StringUtil.isEmptyOrSpaces(text);
|
||||
if (notEmpty && text.contains("W155010")) {
|
||||
// just null
|
||||
return null;
|
||||
}
|
||||
// not a working copy exception
|
||||
// "E155007: '' is not a working copy"
|
||||
if (notEmpty && text.contains("is not a working copy")) {
|
||||
if (StringUtil.isNotEmpty(command.getOutput())) {
|
||||
// workaround: as in subversion 1.8 "svn info" on a working copy root outputs such error for parent folder,
|
||||
// if there are files with conflicts.
|
||||
// but the requested info is still in the output except root closing tag
|
||||
return command.getOutput() + "</info>";
|
||||
} else {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_WORKING_COPY, e), e);
|
||||
}
|
||||
}
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseResult(final ISVNInfoHandler handler, File base, String result) throws SVNException {
|
||||
if (StringUtil.isEmpty(result)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SvnInfoHandler[] infoHandler = new SvnInfoHandler[1];
|
||||
@@ -106,38 +146,34 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient {
|
||||
});
|
||||
|
||||
try {
|
||||
final String result = command.run();
|
||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||
parser.parse(new ByteArrayInputStream(result.getBytes(CharsetToolkit.UTF8_CHARSET)), infoHandler[0]);
|
||||
|
||||
parser.parse(new ByteArrayInputStream(result.getBytes(CharsetToolkit.UTF8_CHARSET)), infoHandler[0]);
|
||||
}
|
||||
catch (SvnExceptionWrapper e) {
|
||||
LOG.info("info output " + result);
|
||||
throw (SVNException) e.getCause();
|
||||
} catch (IOException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
LOG.info("info output " + result);
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
catch (ParserConfigurationException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
LOG.info("info output " + result);
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
catch (SAXException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
final String text = e.getMessage();
|
||||
final boolean notEmpty = !StringUtil.isEmptyOrSpaces(text);
|
||||
if (notEmpty && text.contains("W155010")) {
|
||||
// just null
|
||||
return;
|
||||
}
|
||||
// not a working copy exception
|
||||
// "E155007: '' is not a working copy"
|
||||
if (notEmpty && text.contains("is not a working copy")) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_WORKING_COPY), e);
|
||||
}
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
LOG.info("info output " + result);
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillParameters(String path, SVNRevision pegRevision, SVNRevision revision, SVNDepth depth, List<String> parameters) {
|
||||
CommandUtil.put(parameters, depth);
|
||||
CommandUtil.put(parameters, revision);
|
||||
CommandUtil.put(parameters, path, pegRevision);
|
||||
parameters.add("--xml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision, boolean recursive, ISVNInfoHandler handler)
|
||||
throws SVNException {
|
||||
@@ -147,7 +183,14 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient {
|
||||
@Override
|
||||
public void doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision, SVNDepth depth, ISVNInfoHandler handler)
|
||||
throws SVNException {
|
||||
throw new UnsupportedOperationException();
|
||||
String path = url.toDecodedString();
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
fillParameters(path, pegRevision, revision, depth, parameters);
|
||||
File base = new File(SvnApplicationSettings.getInstance().getCommandLinePath());
|
||||
String result = CommandUtil.runSimple(SvnCommandName.info, SvnVcs.getInstance(myProject), base, url, parameters).getOutput();
|
||||
|
||||
parseResult(handler, base, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+67
-22
@@ -15,14 +15,16 @@
|
||||
*/
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import org.jetbrains.idea.svn.SvnBindUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.portable.PortableStatus;
|
||||
import org.jetbrains.idea.svn.portable.SvnExceptionWrapper;
|
||||
import org.jetbrains.idea.svn.portable.SvnStatusClientI;
|
||||
@@ -48,6 +50,8 @@ import java.util.Map;
|
||||
* Time: 5:21 PM
|
||||
*/
|
||||
public class SvnCommandLineStatusClient implements SvnStatusClientI {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient");
|
||||
|
||||
private final Project myProject;
|
||||
private final SvnCommandLineInfoClient myInfoClient;
|
||||
|
||||
@@ -102,47 +106,84 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI {
|
||||
final SVNInfo infoBase = myInfoClient.doInfo(base, revision);
|
||||
|
||||
final SvnSimpleCommand command = SvnCommandFactory.createSimpleCommand(myProject, base, SvnCommandName.st);
|
||||
putParameters(depth, remote, reportAll, includeIgnored, changeLists, command);
|
||||
putParameters(path, depth, remote, reportAll, includeIgnored, changeLists, command);
|
||||
|
||||
final SvnStatusHandler[] svnHandl = new SvnStatusHandler[1];
|
||||
svnHandl[0] = createStatusHandler(revision, handler, base, infoBase, svnHandl);
|
||||
parseResult(path, revision, handler, base, infoBase, command, execute(command, base));
|
||||
return 0;
|
||||
}
|
||||
|
||||
private String execute(SvnSimpleCommand command, File base) throws SVNException {
|
||||
String result = CommandUtil.runSimple(command, SvnVcs.getInstance(myProject), base, null).getOutput();
|
||||
|
||||
if (StringUtil.isEmptyOrSpaces(result)) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_GENERAL, "Status request returned nothing for command: " +
|
||||
command.myCommandLine.getCommandLineString()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void parseResult(final File path,
|
||||
SVNRevision revision,
|
||||
ISVNStatusHandler handler,
|
||||
File base,
|
||||
SVNInfo infoBase,
|
||||
SvnSimpleCommand command, String result) throws SVNException {
|
||||
|
||||
if (StringUtil.isEmpty(result)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final String result = command.run();
|
||||
if (StringUtil.isEmptyOrSpaces(result)) {
|
||||
throw new VcsException("Status request returned nothing for command: " + command.myCommandLine.getCommandLineString());
|
||||
}
|
||||
final SvnStatusHandler[] svnHandl = new SvnStatusHandler[1];
|
||||
svnHandl[0] = createStatusHandler(revision, handler, base, infoBase, svnHandl);
|
||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||
parser.parse(new ByteArrayInputStream(result.getBytes(CharsetToolkit.UTF8_CHARSET)), svnHandl[0]);
|
||||
if (! svnHandl[0].isAnythingReported()) {
|
||||
if (! SvnUtil.isSvnVersioned(myProject, path)) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY));
|
||||
if (!svnHandl[0].isAnythingReported()) {
|
||||
if (!SvnUtil.isSvnVersioned(myProject, path)) {
|
||||
throw new SVNException(
|
||||
SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY, "Command - " + command.getCommandText() + ". Result - " + result));
|
||||
} else {
|
||||
// return status indicating "NORMAL" state
|
||||
// typical output would be like
|
||||
// <status>
|
||||
// <target path="1.txt"></target>
|
||||
// </status>
|
||||
// so it does not contain any <entry> element and current parsing logic returns null
|
||||
|
||||
PortableStatus status = new PortableStatus();
|
||||
status.setPath(path.getAbsolutePath());
|
||||
status.setContentsStatus(SVNStatusType.STATUS_NORMAL);
|
||||
status.setInfoGetter(new Getter<SVNInfo>() {
|
||||
@Override
|
||||
public SVNInfo get() {
|
||||
return createInfoGetter(null).convert(path);
|
||||
}
|
||||
});
|
||||
handler.handleStatus(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SvnExceptionWrapper e) {
|
||||
throw (SVNException) e.getCause();
|
||||
} catch (IOException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
catch (ParserConfigurationException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
catch (SAXException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void putParameters(SVNDepth depth,
|
||||
private void putParameters(@NotNull File path, SVNDepth depth,
|
||||
boolean remote,
|
||||
boolean reportAll,
|
||||
boolean includeIgnored,
|
||||
Collection changeLists,
|
||||
SvnSimpleCommand command) {
|
||||
command.addParameters(path.getAbsolutePath());
|
||||
if (depth != null) {
|
||||
command.addParameters("--depth", depth.getName());
|
||||
}
|
||||
@@ -171,7 +212,11 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI {
|
||||
final SVNInfo infoBase, final SvnStatusHandler[] svnHandl) {
|
||||
final SvnStatusHandler.ExternalDataCallback callback = createStatusCallback(handler, base, infoBase, svnHandl);
|
||||
|
||||
return new SvnStatusHandler(callback, base, new Convertor<File, SVNInfo>() {
|
||||
return new SvnStatusHandler(callback, base, createInfoGetter(revision));
|
||||
}
|
||||
|
||||
private Convertor<File, SVNInfo> createInfoGetter(final SVNRevision revision) {
|
||||
return new Convertor<File, SVNInfo>() {
|
||||
@Override
|
||||
public SVNInfo convert(File o) {
|
||||
try {
|
||||
@@ -181,7 +226,7 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI {
|
||||
throw new SvnExceptionWrapper(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public static SvnStatusHandler.ExternalDataCallback createStatusCallback(final ISVNStatusHandler handler,
|
||||
|
||||
+28
-34
@@ -24,7 +24,6 @@ import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.idea.svn.SvnApplicationSettings;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback;
|
||||
import org.jetbrains.idea.svn.config.SvnBindException;
|
||||
import org.jetbrains.idea.svn.portable.SvnSvnkitUpdateClient;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
@@ -49,9 +48,9 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
|
||||
private final VirtualFile myCommonAncestor;
|
||||
private boolean myIgnoreExternals;
|
||||
|
||||
public SvnCommandLineUpdateClient(final Project project, VirtualFile commonAncestor) {
|
||||
super(SvnVcs.getInstance(project).createUpdateClient());
|
||||
myProject = project;
|
||||
public SvnCommandLineUpdateClient(final SvnVcs vcs, VirtualFile commonAncestor) {
|
||||
super(vcs.createUpdateClient());
|
||||
myProject = vcs.getProject();
|
||||
myCommonAncestor = commonAncestor;
|
||||
}
|
||||
|
||||
@@ -88,35 +87,7 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
|
||||
File base = myCommonAncestor == null ? paths[0] : new File(myCommonAncestor.getPath());
|
||||
base = base.isDirectory() ? base : base.getParentFile();
|
||||
|
||||
final List<String> parameters = new ArrayList<String>();
|
||||
if (revision != null && ! SVNRevision.UNDEFINED.equals(revision) && ! SVNRevision.WORKING.equals(revision)) {
|
||||
parameters.add("-r");
|
||||
parameters.add(revision.toString());
|
||||
}
|
||||
// unknown depth is not used any more for 1.7 -> why?
|
||||
if (depth != null && ! SVNDepth.UNKNOWN.equals(depth)) {
|
||||
parameters.add("--depth");
|
||||
parameters.add(depth.toString());
|
||||
}
|
||||
if (allowUnversionedObstructions) {
|
||||
parameters.add("--force");
|
||||
}
|
||||
if (depthIsSticky && depth != null) {// !!! not sure, but not used
|
||||
parameters.add("--set-depth");
|
||||
parameters.add(depth.toString());
|
||||
}
|
||||
if (makeParents) {
|
||||
parameters.add("--parents");
|
||||
}
|
||||
if (myIgnoreExternals) {
|
||||
parameters.add("--ignore-externals");
|
||||
}
|
||||
parameters.add("--accept");
|
||||
parameters.add("postpone");
|
||||
|
||||
for (File path : paths) {
|
||||
parameters.add(path.getPath());
|
||||
}
|
||||
final List<String> parameters = prepareParameters(paths, revision, depth, allowUnversionedObstructions, depthIsSticky, makeParents);
|
||||
|
||||
final AtomicReference<SVNException> excRef = new AtomicReference<SVNException>();
|
||||
final ISVNEventHandler handler = getEventHandler();
|
||||
@@ -166,7 +137,7 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
|
||||
}
|
||||
};
|
||||
SvnLineCommand.runWithAuthenticationAttempt(SvnApplicationSettings.getInstance().getCommandLinePath(),
|
||||
base, SvnCommandName.up, listener,
|
||||
base, info.getURL(), SvnCommandName.up, listener,
|
||||
new IdeaSvnkitBasedAuthenticationCallback(SvnVcs.getInstance(myProject)),
|
||||
ArrayUtil.toStringArray(parameters));
|
||||
}
|
||||
@@ -180,6 +151,29 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
|
||||
return updatedToRevision.get();
|
||||
}
|
||||
|
||||
private List<String> prepareParameters(File[] paths,
|
||||
SVNRevision revision,
|
||||
SVNDepth depth,
|
||||
boolean allowUnversionedObstructions,
|
||||
boolean depthIsSticky, boolean makeParents) {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
CommandUtil.put(parameters, revision);
|
||||
CommandUtil.put(parameters, depth);
|
||||
CommandUtil.put(parameters, allowUnversionedObstructions, "--force");
|
||||
if (depthIsSticky && depth != null) {// !!! not sure, but not used
|
||||
parameters.add("--set-depth");
|
||||
parameters.add(depth.toString());
|
||||
}
|
||||
CommandUtil.put(parameters, makeParents, "--parents");
|
||||
CommandUtil.put(parameters, myIgnoreExternals, "--ignore-externals");
|
||||
parameters.add("--accept");
|
||||
parameters.add("postpone");
|
||||
CommandUtil.put(parameters, paths);
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
||||
private void checkForException(final StringBuffer sbError) throws SVNException {
|
||||
if (sbError.length() == 0) return;
|
||||
|
||||
+14
-2
@@ -22,13 +22,25 @@ package org.jetbrains.idea.svn.commandLine;
|
||||
* Time: 1:49 PM
|
||||
*/
|
||||
public enum SvnCommandName {
|
||||
// TODO: temporary command for "more smooth" converting between simple commands and line commands
|
||||
empty("", false),
|
||||
version("--version", false),
|
||||
info("info", false),
|
||||
st("st", false),
|
||||
up("up", true),
|
||||
ci("commit", true),
|
||||
cleanup("cleanup", true);
|
||||
|
||||
cleanup("cleanup", true),
|
||||
cat("cat", false),
|
||||
add("add", true),
|
||||
log("log", false),
|
||||
revert("revert", true),
|
||||
delete("delete", true),
|
||||
copy("copy", true),
|
||||
move("move", true),
|
||||
resolve("resolve", true),
|
||||
propget("propget", false),
|
||||
blame("blame", false);
|
||||
|
||||
private final String myName;
|
||||
private final boolean myWriteable;
|
||||
|
||||
+11
-19
@@ -13,22 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn;
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import org.apache.subversion.javahl.types.Revision;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.commandLine.LineCommandListener;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnLineCommand;
|
||||
import org.jetbrains.idea.svn.config.SvnBindException;
|
||||
import org.tigris.subversion.javahl.BindClientException;
|
||||
import org.tigris.subversion.javahl.ClientException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
@@ -42,7 +39,7 @@ import java.util.*;
|
||||
public class SvnCommitRunner {
|
||||
private final String myExePath;
|
||||
@Nullable private final AuthenticationCallback myAuthenticationCallback;
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.SvnCommitRunner");
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.commandLine.SvnCommitRunner");
|
||||
private SvnCommitRunner.CommandListener myCommandListener;
|
||||
|
||||
public SvnCommitRunner(@NotNull String path, @Nullable CommitEventHandler handler, @Nullable AuthenticationCallback authenticationCallback) {
|
||||
@@ -57,7 +54,7 @@ public class SvnCommitRunner {
|
||||
boolean noUnlock,
|
||||
boolean keepChangelist,
|
||||
String[] changelists,
|
||||
Map revpropTable) throws ClientException {
|
||||
Map revpropTable, Convertor<String[], SVNURL> urlProvider) throws VcsException {
|
||||
if (paths.length == 0) return Revision.SVN_INVALID_REVNUM;
|
||||
|
||||
final List<String> parameters = new ArrayList<String>();
|
||||
@@ -84,19 +81,14 @@ public class SvnCommitRunner {
|
||||
Arrays.sort(paths);
|
||||
parameters.addAll(Arrays.asList(paths));
|
||||
|
||||
try {
|
||||
SvnLineCommand.runWithAuthenticationAttempt(myExePath, new File(paths[0]), SvnCommandName.ci,
|
||||
myCommandListener, myAuthenticationCallback, ArrayUtil.toStringArray(parameters));
|
||||
}
|
||||
catch (SvnBindException e) {
|
||||
throw BindClientException.create(e, Revision.SVN_INVALID_REVNUM);
|
||||
}
|
||||
SvnLineCommand.runWithAuthenticationAttempt(myExePath, new File(paths[0]), urlProvider.convert(paths), SvnCommandName.ci,
|
||||
myCommandListener, myAuthenticationCallback, ArrayUtil.toStringArray(parameters));
|
||||
myCommandListener.throwExceptionIfOccurred();
|
||||
|
||||
return myCommandListener.getCommittedRevision();
|
||||
}
|
||||
|
||||
private static class CommandListener extends LineCommandListener {
|
||||
public static class CommandListener extends LineCommandListener {
|
||||
@Nullable private final CommitEventHandler myHandler;
|
||||
private SvnBindException myException;
|
||||
private long myCommittedRevision = Revision.SVN_INVALID_REVNUM;
|
||||
@@ -106,9 +98,9 @@ public class SvnCommitRunner {
|
||||
myHandler = handler;
|
||||
}
|
||||
|
||||
public void throwExceptionIfOccurred() throws BindClientException {
|
||||
public void throwExceptionIfOccurred() throws VcsException {
|
||||
if (myException != null) {
|
||||
throw BindClientException.create(myException, Revision.SVN_INVALID_REVNUM);
|
||||
throw myException;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.idea.svn.commandLine;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNNodeKind;
|
||||
@@ -49,7 +50,7 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
public SvnInfoHandler(File base, final Consumer<SVNInfo> infoConsumer) {
|
||||
myBase = base;
|
||||
myInfoConsumer = infoConsumer;
|
||||
myPending = new SvnInfoStructure();
|
||||
myPending = createPending();
|
||||
myElementsMap = new HashMap<String, Getter<ElementHandlerBase>>();
|
||||
fillElements();
|
||||
myParseStack = new ArrayList<ElementHandlerBase>();
|
||||
@@ -70,7 +71,14 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
myInfoConsumer.consume(info);
|
||||
}
|
||||
myResultsMap.put(info.getFile(), info);
|
||||
myPending = new SvnInfoStructure();
|
||||
myPending = createPending();
|
||||
}
|
||||
|
||||
private SvnInfoStructure createPending() {
|
||||
SvnInfoStructure pending = new SvnInfoStructure();
|
||||
pending.myDepth = SVNDepth.INFINITY;
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,16 +98,13 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
assertSAX(! myParseStack.isEmpty());
|
||||
ElementHandlerBase current = myParseStack.get(myParseStack.size() - 1);
|
||||
if (mySb.length() > 0) {
|
||||
current.characters(mySb.toString().trim(), myPending);
|
||||
mySb.setLength(0);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
final boolean createNewChild = current.startElement(uri, localName, qName, attributes);
|
||||
if (createNewChild) {
|
||||
assertSAX(myElementsMap.containsKey(qName));
|
||||
final ElementHandlerBase newChild = myElementsMap.get(qName).get();
|
||||
newChild.setParent(current);
|
||||
newChild.updateInfo(attributes, myPending);
|
||||
myParseStack.add(newChild);
|
||||
return;
|
||||
@@ -115,6 +120,18 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
ElementHandlerBase current = myParseStack.get(myParseStack.size() - 1);
|
||||
String value = mySb.toString().trim();
|
||||
|
||||
if (!StringUtil.isEmpty(value)) {
|
||||
current.characters(value, myPending);
|
||||
}
|
||||
|
||||
mySb.setLength(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
assertSAX(! myParseStack.isEmpty());
|
||||
@@ -252,6 +269,24 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
return new Url();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("relative-url", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
return new RelativeUrl();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("lock", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
return new Lock();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("created", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
return new Date();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("uuid", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
@@ -270,6 +305,18 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
return new WcInfo();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("moved-to", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
return new MovedPath();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("moved-from", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
return new MovedPath();
|
||||
}
|
||||
});
|
||||
myElementsMap.put("wcroot-abspath", new Getter<ElementHandlerBase>() {
|
||||
@Override
|
||||
public ElementHandlerBase get() {
|
||||
@@ -295,6 +342,12 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
|
||||
@Override
|
||||
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
|
||||
// TODO: Currently information for conflict (not tree-conflict) available in svn 1.8 is not used
|
||||
// TODO: And it also not suite well for SVNKit api
|
||||
if (getParent() instanceof Conflict) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String side = attributes.getValue("side");
|
||||
if ("source-left".equals(side)) {
|
||||
final SvnInfoStructure.ConflictVersion conflictVersion = new SvnInfoStructure.ConflictVersion();
|
||||
@@ -382,7 +435,7 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
structure.myConflictWorking = s;
|
||||
structure.myConflictNew = new File(s).getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +450,7 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
structure.myConflictNew = s;
|
||||
structure.myConflictWorking = new File(s).getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,14 +465,13 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
// todo path? or plus base
|
||||
structure.myConflictOld = s;
|
||||
structure.myConflictOld = new File(s).getName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class Conflict extends ElementHandlerBase {
|
||||
private Conflict() {
|
||||
super(new String[]{"prev-base-file","prev-wc-file","cur-base-file","prop-file"}, new String[]{});
|
||||
super(new String[]{"prev-base-file","prev-wc-file","cur-base-file","prop-file"}, new String[]{"version"});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -498,6 +550,25 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "moved-from" and "moved-to" elements are represented by this class.
|
||||
*/
|
||||
private static class MovedPath extends ElementHandlerBase {
|
||||
|
||||
private MovedPath() {
|
||||
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 {
|
||||
// TODO: is there some field to initialize from this value?
|
||||
}
|
||||
}
|
||||
|
||||
private static class TextUpdated extends ElementHandlerBase {
|
||||
private TextUpdated() {
|
||||
super(new String[]{}, new String[]{});
|
||||
@@ -617,7 +688,7 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
private static class WcInfo extends ElementHandlerBase {
|
||||
private WcInfo() {
|
||||
super(new String[]{"wcroot-abspath", "schedule", "depth", "text-updated", "checksum", "changelist", "copy-from-url",
|
||||
"copy-from-rev"}, new String[]{});
|
||||
"copy-from-rev", "moved-to", "moved-from"}, new String[]{});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -698,11 +769,34 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static class RelativeUrl extends Url{
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
structure.relativeUrl = s;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Lock extends ElementHandlerBase {
|
||||
private Lock() {
|
||||
super(new String[]{"created"}, new String[]{});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(String s, SvnInfoStructure structure) throws SAXException {
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
private static class Entry extends ElementHandlerBase {
|
||||
private final File myBase;
|
||||
|
||||
private Entry(final File base) {
|
||||
super(new String[]{"url","repository","wc-info","commit","conflict","tree-conflict"}, new String[]{});
|
||||
super(new String[]{"url", "relative-url", "lock", "repository","wc-info","commit","conflict","tree-conflict"}, new String[]{});
|
||||
myBase = base;
|
||||
}
|
||||
|
||||
@@ -763,12 +857,22 @@ public class SvnInfoHandler extends DefaultHandler {
|
||||
private abstract static class ElementHandlerBase {
|
||||
private final Set<String> myAwaitedChildren;
|
||||
private final Set<String> myAwaitedChildrenMultiple;
|
||||
private ElementHandlerBase parent;
|
||||
|
||||
ElementHandlerBase(String[] awaitedChildren, String[] awaitedChildrenMultiple) {
|
||||
myAwaitedChildren = new HashSet<String>(Arrays.asList(awaitedChildren));
|
||||
myAwaitedChildrenMultiple = new HashSet<String>(Arrays.asList(awaitedChildrenMultiple));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ElementHandlerBase getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(@NotNull ElementHandlerBase parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
protected abstract void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException;
|
||||
|
||||
public boolean startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.Date;
|
||||
*/
|
||||
public class SvnInfoStructure {
|
||||
public File myFile;
|
||||
public String relativeUrl;
|
||||
public SVNURL myUrl;
|
||||
public SVNURL myRootURL;
|
||||
public long myRevision;
|
||||
|
||||
+181
-23
@@ -23,20 +23,30 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.LineHandlerHelper;
|
||||
import com.intellij.openapi.vcs.LineProcessEventListener;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.AuthenticationCallback;
|
||||
import org.jetbrains.idea.svn.SvnBindUtil;
|
||||
import org.jetbrains.idea.svn.config.SvnBindException;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
|
||||
import org.tmatesoft.svn.core.auth.SVNAuthentication;
|
||||
import org.tmatesoft.svn.core.auth.SVNPasswordAuthentication;
|
||||
import org.tmatesoft.svn.core.auth.SVNSSLAuthentication;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
@@ -47,11 +57,21 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
* honestly stolen from GitLineHandler
|
||||
*/
|
||||
public class SvnLineCommand extends SvnCommand {
|
||||
|
||||
public static final String AUTHENTICATION_REALM = "Authentication realm:";
|
||||
public static final String CERTIFICATE_ERROR = "Error validating server certificate for";
|
||||
public static final String PASSPHRASE_FOR = "Passphrase for";
|
||||
public static final String UNABLE_TO_CONNECT = "svn: E170001:";
|
||||
public static final String CANNOT_AUTHENTICATE_TO_PROXY = "Could not authenticate to proxy server";
|
||||
public static final String AUTHENTICATION_FAILED_MESSAGE = "Authentication failed";
|
||||
|
||||
private static final String INVALID_CREDENTIALS_FOR_SVN_PROTOCOL = "svn: E170001: Can't get";
|
||||
private static final String UNTRUSTED_SERVER_CERTIFICATE = "Server SSL certificate untrusted";
|
||||
private static final String ACCESS_TO_PREFIX = "Access to ";
|
||||
private static final String FORBIDDEN_STATUS = "forbidden";
|
||||
private static final String PASSWORD_STRING = "password";
|
||||
|
||||
private static final Pattern UNABLE_TO_CONNECT_TO_URL_PATTERN = Pattern.compile("Unable to connect to a repository at URL '(.*)'");
|
||||
|
||||
// kept for exact text
|
||||
//public static final String CLIENT_CERTIFICATE_FILENAME = "Client certificate filename:";
|
||||
@@ -66,6 +86,7 @@ public class SvnLineCommand extends SvnCommand {
|
||||
private final EventDispatcher<LineProcessEventListener> myLineListeners;
|
||||
private final AtomicReference<Integer> myExitCode;
|
||||
private final StringBuffer myErr;
|
||||
private final StringBuffer myStdOut;
|
||||
|
||||
public SvnLineCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath) {
|
||||
this(workingDirectory, commandName, exePath, null);
|
||||
@@ -76,6 +97,7 @@ public class SvnLineCommand extends SvnCommand {
|
||||
myLineListeners = EventDispatcher.create(LineProcessEventListener.class);
|
||||
myExitCode = new AtomicReference<Integer>();
|
||||
myErr = new StringBuffer();
|
||||
myStdOut = new StringBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,13 +111,14 @@ public class SvnLineCommand extends SvnCommand {
|
||||
}
|
||||
}
|
||||
|
||||
public static void runWithAuthenticationAttempt(final String exePath,
|
||||
final File firstFile,
|
||||
SvnCommandName commandName,
|
||||
final LineCommandListener listener,
|
||||
@Nullable AuthenticationCallback authenticationCallback,
|
||||
final String... parameters) throws SvnBindException {
|
||||
File base = firstFile.isDirectory() ? firstFile : firstFile.getParentFile();
|
||||
public static SvnLineCommand runWithAuthenticationAttempt(final String exePath,
|
||||
final File firstFile,
|
||||
final SVNURL url,
|
||||
SvnCommandName commandName,
|
||||
final LineCommandListener listener,
|
||||
@Nullable AuthenticationCallback authenticationCallback,
|
||||
String... parameters) throws SvnBindException {
|
||||
File base = firstFile != null ? (firstFile.isDirectory() ? firstFile : firstFile.getParentFile()) : null;
|
||||
base = SvnBindUtil.correctUpToExistingParent(base);
|
||||
|
||||
listener.baseDirectory(base);
|
||||
@@ -114,13 +137,14 @@ public class SvnLineCommand extends SvnCommand {
|
||||
if (command.myErr.length() > 0) {
|
||||
final String errText = command.myErr.toString().trim();
|
||||
if (authenticationCallback != null) {
|
||||
final AuthCallbackCase callback = createCallback(errText, authenticationCallback, base);
|
||||
final AuthCallbackCase callback = createCallback(errText, authenticationCallback, base, url);
|
||||
if (callback != null) {
|
||||
cleanup(exePath, commandName, base);
|
||||
cleanup(exePath, command, base);
|
||||
if (callback.getCredentials(errText)) {
|
||||
if (authenticationCallback.getSpecialConfigDir() != null) {
|
||||
configDir = authenticationCallback.getSpecialConfigDir();
|
||||
}
|
||||
parameters = updateParameters(callback, parameters);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -131,7 +155,7 @@ public class SvnLineCommand extends SvnCommand {
|
||||
if (exitCode != 0) {
|
||||
throw new SvnBindException("Svn process exited with error code: " + exitCode);
|
||||
}
|
||||
return;
|
||||
return command;
|
||||
}
|
||||
} finally {
|
||||
if (authenticationCallback != null) {
|
||||
@@ -140,6 +164,13 @@ public class SvnLineCommand extends SvnCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] updateParameters(AuthCallbackCase callback, String[] parameters) {
|
||||
List<String> p = new ArrayList<String>(Arrays.asList(parameters));
|
||||
|
||||
callback.updateParameters(p);
|
||||
return ArrayUtil.toStringArray(p);
|
||||
}
|
||||
|
||||
private static void writeIdeaConfig2SubversionConfig(@NotNull AuthenticationCallback authenticationCallback, @NotNull File base) throws SvnBindException {
|
||||
if (authenticationCallback.haveDataForTmpConfig()) {
|
||||
try {
|
||||
@@ -158,7 +189,7 @@ public class SvnLineCommand extends SvnCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private static AuthCallbackCase createCallback(final String errText, final AuthenticationCallback callback, final File base) {
|
||||
private static AuthCallbackCase createCallback(final String errText, final AuthenticationCallback callback, final File base, final SVNURL url) {
|
||||
if (errText.startsWith(CERTIFICATE_ERROR)) {
|
||||
return new CertificateCallbackCase(callback, base);
|
||||
}
|
||||
@@ -171,9 +202,85 @@ public class SvnLineCommand extends SvnCommand {
|
||||
if (errText.startsWith(UNABLE_TO_CONNECT) && errText.contains(CANNOT_AUTHENTICATE_TO_PROXY)) {
|
||||
return new ProxyCallback(callback, base);
|
||||
}
|
||||
// http/https protocol invalid credentials
|
||||
if (errText.contains(AUTHENTICATION_FAILED_MESSAGE)) {
|
||||
return new UsernamePasswordCallback(callback, base, url);
|
||||
}
|
||||
// messages could be "Can't get password", "Can't get username or password"
|
||||
if (errText.contains(INVALID_CREDENTIALS_FOR_SVN_PROTOCOL) && errText.contains(PASSWORD_STRING)) {
|
||||
// svn protocol invalid credentials
|
||||
return new UsernamePasswordCallback(callback, base, url);
|
||||
}
|
||||
// https one-way protocol untrusted server certificate
|
||||
if (errText.contains(UNTRUSTED_SERVER_CERTIFICATE)) {
|
||||
return new CertificateCallbackCase(callback, base);
|
||||
}
|
||||
// https two-way protocol invalid client certificate
|
||||
if (errText.contains(ACCESS_TO_PREFIX) && errText.contains(FORBIDDEN_STATUS)) {
|
||||
return new TwoWaySslCallback(callback, base, url);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Special callback for svn 1.8 credentials request as --non-interactive does not return
|
||||
// authentication realm (just url) - so we could not create temp cache
|
||||
private static class UsernamePasswordCallback extends AuthCallbackCase {
|
||||
protected SVNAuthentication myAuthentication;
|
||||
protected SVNURL myUrl;
|
||||
|
||||
protected UsernamePasswordCallback(AuthenticationCallback callback, File base, SVNURL url) {
|
||||
super(callback, base);
|
||||
myUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean getCredentials(String errText) throws SvnBindException {
|
||||
myAuthentication = myAuthenticationCallback.requestCredentials(myUrl != null ? myUrl : parseUrlFromError(errText),
|
||||
getType());
|
||||
|
||||
return myAuthentication != null;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return ISVNAuthenticationManager.PASSWORD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateParameters(List<String> parameters) {
|
||||
if (myAuthentication instanceof SVNPasswordAuthentication) {
|
||||
SVNPasswordAuthentication auth = (SVNPasswordAuthentication)myAuthentication;
|
||||
|
||||
parameters.add("--username");
|
||||
parameters.add(auth.getUserName());
|
||||
parameters.add("--password");
|
||||
parameters.add(auth.getPassword());
|
||||
if (!auth.isStorageAllowed()) {
|
||||
parameters.add("--no-auth-cache");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SVNURL parseUrlFromError(String errorText) {
|
||||
Matcher matcher = UNABLE_TO_CONNECT_TO_URL_PATTERN.matcher(errorText);
|
||||
String urlValue = null;
|
||||
|
||||
if (matcher.find()) {
|
||||
urlValue = matcher.group(1);
|
||||
}
|
||||
|
||||
return urlValue != null ? parseUrl(urlValue) : null;
|
||||
}
|
||||
|
||||
private SVNURL parseUrl(String urlValue) {
|
||||
try {
|
||||
return SVNURL.parseURIEncoded(urlValue);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProxyCallback extends AuthCallbackCase {
|
||||
protected ProxyCallback(AuthenticationCallback callback, File base) {
|
||||
super(callback, base);
|
||||
@@ -192,7 +299,8 @@ public class SvnLineCommand extends SvnCommand {
|
||||
|
||||
@Override
|
||||
boolean getCredentials(String errText) throws SvnBindException {
|
||||
final String realm = cutFirstLine(errText).substring(AUTHENTICATION_REALM.length()).trim();
|
||||
final String realm =
|
||||
errText.startsWith(AUTHENTICATION_REALM) ? cutFirstLine(errText).substring(AUTHENTICATION_REALM.length()).trim() : null;
|
||||
final boolean isPassword = StringUtil.containsIgnoreCase(errText, "password");
|
||||
if (myTried) {
|
||||
myAuthenticationCallback.clearPassiveCredentials(realm, myBase, isPassword);
|
||||
@@ -212,13 +320,16 @@ public class SvnLineCommand extends SvnCommand {
|
||||
}
|
||||
|
||||
private static class CertificateCallbackCase extends AuthCallbackCase {
|
||||
private boolean accepted;
|
||||
|
||||
private CertificateCallbackCase(AuthenticationCallback callback, File base) {
|
||||
super(callback, base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCredentials(final String errText) throws SvnBindException {
|
||||
String realm = cutFirstLine(errText).substring(CERTIFICATE_ERROR.length());
|
||||
// parse realm from error text
|
||||
String realm = errText;
|
||||
final int idx1 = realm.indexOf('\'');
|
||||
if (idx1 == -1) {
|
||||
throw new SvnBindException("Can not detect authentication realm name: " + errText);
|
||||
@@ -229,11 +340,48 @@ public class SvnLineCommand extends SvnCommand {
|
||||
}
|
||||
realm = realm.substring(idx1 + 1, idx2);
|
||||
if (! myTried && myAuthenticationCallback.acceptSSLServerCertificate(myBase, realm)) {
|
||||
accepted = true;
|
||||
myTried = true;
|
||||
return true;
|
||||
}
|
||||
throw new SvnBindException("Server SSL certificate rejected");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateParameters(List<String> parameters) {
|
||||
if (accepted) {
|
||||
parameters.add("--trust-server-cert");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class TwoWaySslCallback extends UsernamePasswordCallback {
|
||||
|
||||
protected TwoWaySslCallback(AuthenticationCallback callback, File base, SVNURL url) {
|
||||
super(callback, base, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return ISVNAuthenticationManager.SSL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateParameters(List<String> parameters) {
|
||||
if (myAuthentication instanceof SVNSSLAuthentication) {
|
||||
SVNSSLAuthentication auth = (SVNSSLAuthentication)myAuthentication;
|
||||
|
||||
// TODO: Seems that config option should be specified for concrete server and not for global group.
|
||||
// as in that case it could be overriden by settings in config file
|
||||
parameters.add("--config-option");
|
||||
parameters.add("servers:global:ssl-client-cert-file=" + auth.getCertificatePath());
|
||||
parameters.add("--config-option");
|
||||
parameters.add("servers:global:ssl-client-cert-password=" + auth.getPassword());
|
||||
if (!auth.isStorageAllowed()) {
|
||||
parameters.add("--no-auth-cache");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class AuthCallbackCase {
|
||||
@@ -247,17 +395,23 @@ public class SvnLineCommand extends SvnCommand {
|
||||
}
|
||||
|
||||
abstract boolean getCredentials(final String errText) throws SvnBindException;
|
||||
|
||||
public void updateParameters(List<String> parameters) {
|
||||
}
|
||||
}
|
||||
|
||||
private static void cleanup(String exePath, SvnCommandName commandName, File base) throws SvnBindException {
|
||||
File wcRoot = SvnBindUtil.getWcRoot(base);
|
||||
if (wcRoot == null) throw new SvnBindException("Can not find working copy root for: " + base.getPath());
|
||||
private static void cleanup(String exePath, SvnCommand command, File base) throws SvnBindException {
|
||||
// TODO: could be issues with fake "empty" command as it is not writable - but only read commands currently use "empty" command
|
||||
// TODO: and "empty" command will be removed shortly
|
||||
if (command.isManuallyDestroyed() && command.getCommandName().isWriteable()) {
|
||||
File wcRoot = SvnUtil.getWorkingCopyRootNew(base);
|
||||
if (wcRoot == null) {
|
||||
throw new SvnBindException("Can not find working copy root for: " + base.getPath());
|
||||
}
|
||||
|
||||
//cleanup -> check command type
|
||||
if (commandName.isWriteable()) {
|
||||
final SvnSimpleCommand command = new SvnSimpleCommand(wcRoot, SvnCommandName.cleanup, exePath);
|
||||
final SvnSimpleCommand cleanupCommand = new SvnSimpleCommand(wcRoot, SvnCommandName.cleanup, exePath);
|
||||
try {
|
||||
command.run();
|
||||
cleanupCommand.run();
|
||||
}
|
||||
catch (VcsException e) {
|
||||
throw new SvnBindException(e);
|
||||
@@ -320,6 +474,10 @@ public class SvnLineCommand extends SvnCommand {
|
||||
command.addLineListener(new LineProcessEventListener() {
|
||||
@Override
|
||||
public void onLineAvailable(String line, Key outputType) {
|
||||
if (ProcessOutputTypes.STDOUT.equals(outputType)) {
|
||||
command.myStdOut.append(line);
|
||||
}
|
||||
|
||||
if (SvnCommand.LOG.isDebugEnabled()) {
|
||||
SvnCommand.LOG.debug("==> " + line);
|
||||
}
|
||||
+5
-1
@@ -94,7 +94,11 @@ public class SvnSimpleCommand extends SvnCommand {
|
||||
if (myException != null) throw myException;
|
||||
final int code = getExitCode();
|
||||
if (code == 0) {
|
||||
return myStdout.toString();
|
||||
String result = myStdout.toString();
|
||||
|
||||
LOG.debug(result);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
final String msg = new StringBuilder("Svn process exited with error code: ").append(code).append("\n")
|
||||
.append("stderr: ").append(myStderr.toString()).append("\nstdout: ").append(getStdout().toString())
|
||||
+4
-24
@@ -62,6 +62,8 @@ public class UpdateOutputLineConverter {
|
||||
}
|
||||
|
||||
public SVNEvent convert(final String line) {
|
||||
// TODO: Add direct processing of "Summary of conflicts" lines at the end of "svn update" output (if there are conflicts).
|
||||
// TODO: Now it works ok because parseNormalLine could not determine necessary statuses from that and further lines
|
||||
if (StringUtil.isEmptyOrSpaces(line)) return null;
|
||||
|
||||
if (line.startsWith(UPDATING)) {
|
||||
@@ -103,9 +105,9 @@ public class UpdateOutputLineConverter {
|
||||
if (line.length() < 5) return null;
|
||||
final char first = line.charAt(0);
|
||||
if (' ' != first && ! ourActions.contains(first)) return null;
|
||||
final SVNStatusType contentsStatus = getStatusType(first);
|
||||
final SVNStatusType contentsStatus = CommandUtil.getStatusType(first);
|
||||
final char second = line.charAt(1);
|
||||
final SVNStatusType propertiesStatus = getStatusType(second);
|
||||
final SVNStatusType propertiesStatus = CommandUtil.getStatusType(second);
|
||||
final char lock = line.charAt(2); // dont know what to do with stolen lock info
|
||||
if (' ' != lock && 'B' != lock) return null;
|
||||
final char treeConflict = line.charAt(3);
|
||||
@@ -140,28 +142,6 @@ public class UpdateOutputLineConverter {
|
||||
null, action, expectedAction, null, null, null, null, null);
|
||||
}
|
||||
|
||||
private SVNStatusType getStatusType(char first) {
|
||||
final SVNStatusType contentsStatus;
|
||||
if ('A' == first) {
|
||||
contentsStatus = SVNStatusType.STATUS_ADDED;
|
||||
} else if ('D' == first) {
|
||||
contentsStatus = SVNStatusType.STATUS_DELETED;
|
||||
} else if ('U' == first) {
|
||||
contentsStatus = SVNStatusType.CHANGED;
|
||||
} else if ('C' == first) {
|
||||
contentsStatus = SVNStatusType.CONFLICTED;
|
||||
} else if ('G' == first) {
|
||||
contentsStatus = SVNStatusType.MERGED;
|
||||
} else if ('R' == first) {
|
||||
contentsStatus = SVNStatusType.STATUS_REPLACED;
|
||||
} else if ('E' == first) {
|
||||
contentsStatus = SVNStatusType.STATUS_OBSTRUCTED;
|
||||
} else {
|
||||
contentsStatus = SVNStatusType.STATUS_NORMAL;
|
||||
}
|
||||
return contentsStatus;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private long matchAndGetRevision(final Pattern pattern, final String line) {
|
||||
final Matcher matcher = pattern.matcher(line);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.jetbrains.idea.svn.conflict;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.jetbrains.idea.svn.commandLine.CommandUtil;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdConflictClient extends BaseSvnClient implements ConflictClient {
|
||||
|
||||
// TODO: Add possibility to resolve content conflicts separately from property conflicts.
|
||||
@Override
|
||||
public void resolve(@NotNull File path, boolean resolvePropertyConflicts) throws VcsException {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
CommandUtil.put(parameters, path);
|
||||
CommandUtil.put(parameters, SVNDepth.EMPTY);
|
||||
parameters.add("--accept");
|
||||
parameters.add("working");
|
||||
|
||||
// for now parsing of the output is not required as command is executed only for one file
|
||||
// and will be either successful or exception will be thrown
|
||||
CommandUtil.execute(myVcs, SvnCommandName.resolve, parameters, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.jetbrains.idea.svn.conflict;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.api.SvnClient;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface ConflictClient extends SvnClient {
|
||||
|
||||
void resolve(@NotNull File path, boolean resolvePropertyConflicts) throws VcsException;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.jetbrains.idea.svn.conflict;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.SVNConflictChoice;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitConflictClient extends BaseSvnClient implements ConflictClient {
|
||||
@Override
|
||||
public void resolve(@NotNull File path, boolean resolvePropertyConflicts) throws VcsException {
|
||||
try {
|
||||
myVcs.createWCClient().doResolve(path, SVNDepth.EMPTY, true, resolvePropertyConflicts, SVNConflictChoice.MERGED);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.jetbrains.idea.svn.content;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.impl.ContentRevisionCache;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.jetbrains.idea.svn.commandLine.*;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdContentClient extends BaseSvnClient implements ContentClient {
|
||||
|
||||
@Override
|
||||
public byte[] getContent(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable SVNRevision pegRevision)
|
||||
throws VcsException, FileTooBigRuntimeException {
|
||||
// TODO: rewrite this to provide output as Stream
|
||||
// TODO: rewrite without conversion from String to byte[]
|
||||
// TODO: Also implement max size constraint like in SvnKitContentClient
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
CommandUtil.put(parameters, target.getPathOrUrlString(), pegRevision);
|
||||
CommandUtil.put(parameters, revision);
|
||||
|
||||
SvnCommand command = CommandUtil.execute(myVcs, SvnCommandName.cat, parameters, null);
|
||||
|
||||
byte[] bytes = CharsetToolkit.getUtf8Bytes(command.getOutput());
|
||||
|
||||
ContentRevisionCache.checkContentsSize(target.getPathOrUrlString(), bytes.length);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.jetbrains.idea.svn.content;
|
||||
|
||||
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.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface ContentClient extends SvnClient {
|
||||
|
||||
byte[] getContent(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable SVNRevision pegRevision)
|
||||
throws VcsException, FileTooBigRuntimeException;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.idea.svn.content;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class FileTooBigRuntimeException extends RuntimeException {
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.jetbrains.idea.svn.content;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.impl.ContentRevisionCache;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNWCClient;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitContentClient extends BaseSvnClient implements ContentClient {
|
||||
|
||||
@Override
|
||||
public byte[] getContent(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable SVNRevision pegRevision)
|
||||
throws VcsException, FileTooBigRuntimeException {
|
||||
final int maxSize = VcsUtil.getMaxVcsLoadedFileSize();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream() {
|
||||
@Override
|
||||
public synchronized void write(int b) {
|
||||
if (size() > maxSize) throw new FileTooBigRuntimeException();
|
||||
super.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(byte[] b, int off, int len) {
|
||||
if (size() > maxSize) throw new FileTooBigRuntimeException();
|
||||
super.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void writeTo(OutputStream out) throws IOException {
|
||||
if (size() > maxSize) throw new FileTooBigRuntimeException();
|
||||
super.writeTo(out);
|
||||
}
|
||||
};
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
try {
|
||||
if (target.isURL()) {
|
||||
wcClient.doGetFileContents(target.getURL(), pegRevision, revision, true, buffer);
|
||||
} else {
|
||||
wcClient.doGetFileContents(target.getFile(), pegRevision, revision, true, buffer);
|
||||
}
|
||||
ContentRevisionCache.checkContentsSize(target.getPathOrUrlString(), buffer.size());
|
||||
} catch (FileTooBigRuntimeException e) {
|
||||
ContentRevisionCache.checkContentsSize(target.getPathOrUrlString(), buffer.size());
|
||||
} catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.jetbrains.idea.svn.copy;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.jetbrains.idea.svn.commandLine.CommandUtil;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdCopyMoveClient extends BaseSvnClient implements CopyMoveClient {
|
||||
|
||||
@Override
|
||||
public void copy(@NotNull File src, @NotNull File dst, boolean makeParents, boolean isMove) throws VcsException {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
CommandUtil.put(parameters, src);
|
||||
CommandUtil.put(parameters, dst);
|
||||
CommandUtil.put(parameters, makeParents, "--parents");
|
||||
|
||||
// for now parsing of the output is not required as command is executed only for one file
|
||||
// and will be either successful or exception will be thrown
|
||||
CommandUtil.execute(myVcs, isMove ? SvnCommandName.move : SvnCommandName.copy, parameters, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.jetbrains.idea.svn.copy;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.api.SvnClient;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface CopyMoveClient extends SvnClient {
|
||||
|
||||
void copy(@NotNull File src, @NotNull File dst, boolean makeParents, boolean isMove) throws VcsException;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.jetbrains.idea.svn.copy;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.SVNCopySource;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitCopyMoveClient extends BaseSvnClient implements CopyMoveClient {
|
||||
|
||||
@Override
|
||||
public void copy(@NotNull File src, @NotNull File dst, boolean makeParents, boolean isMove) throws VcsException {
|
||||
final SVNCopySource copySource = new SVNCopySource(isMove ? SVNRevision.UNDEFINED : SVNRevision.WORKING, SVNRevision.WORKING, src);
|
||||
|
||||
try {
|
||||
myVcs.createCopyClient().doCopy(new SVNCopySource[]{copySource}, dst, isMove, makeParents, true);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.jetbrains.idea.svn.delete;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.jetbrains.idea.svn.commandLine.CommandUtil;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdDeleteClient extends BaseSvnClient implements DeleteClient {
|
||||
|
||||
@Override
|
||||
public void delete(@NotNull File path, boolean force) throws VcsException {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
CommandUtil.put(parameters, path);
|
||||
CommandUtil.put(parameters, force, "--force");
|
||||
|
||||
// for now parsing of the output is not required as command is executed only for one file
|
||||
// and will be either successful or exception will be thrown
|
||||
CommandUtil.execute(myVcs, SvnCommandName.delete, parameters, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.jetbrains.idea.svn.delete;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.api.SvnClient;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface DeleteClient extends SvnClient {
|
||||
|
||||
void delete(@NotNull File path, boolean force) throws VcsException;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.jetbrains.idea.svn.delete;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.api.BaseSvnClient;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitDeleteClient extends BaseSvnClient implements DeleteClient {
|
||||
|
||||
@Override
|
||||
public void delete(@NotNull File path, boolean force) throws VcsException {
|
||||
try {
|
||||
myVcs.createWCClient().doDelete(path, force, false);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,17 +263,11 @@ public class CreateBranchOrTagDialog extends DialogWrapper {
|
||||
super.init();
|
||||
SvnVcs vcs = SvnVcs.getInstance(myProject);
|
||||
String revStr = "";
|
||||
try {
|
||||
SVNWCClient client = vcs.createWCClient();
|
||||
SVNInfo info = client.doInfo(mySrcFile, SVNRevision.UNDEFINED);
|
||||
if (info != null) {
|
||||
mySrcURL = info.getURL() == null ? null : info.getURL().toString();
|
||||
revStr = String.valueOf(info.getRevision());
|
||||
myURL = mySrcURL;
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
//
|
||||
SVNInfo info = vcs.getInfo(mySrcFile);
|
||||
if (info != null) {
|
||||
mySrcURL = info.getURL() == null ? null : info.getURL().toString();
|
||||
revStr = String.valueOf(info.getRevision());
|
||||
myURL = mySrcURL;
|
||||
}
|
||||
if (myURL == null) {
|
||||
return;
|
||||
@@ -354,15 +348,8 @@ public class CreateBranchOrTagDialog extends DialogWrapper {
|
||||
return true;
|
||||
}
|
||||
else if (myWorkingCopyRadioButton.isSelected()) {
|
||||
String srcUrl;
|
||||
try {
|
||||
SVNWCClient client = SvnVcs.getInstance(myProject).createWCClient();
|
||||
SVNInfo info = client.doInfo(mySrcFile, SVNRevision.UNDEFINED);
|
||||
srcUrl = info != null && info.getURL() != null ? info.getURL().toString() : null;
|
||||
}
|
||||
catch (SVNException e) {
|
||||
srcUrl = null;
|
||||
}
|
||||
SVNInfo info = SvnVcs.getInstance(myProject).getInfo(mySrcFile);
|
||||
String srcUrl = info != null && info.getURL() != null ? info.getURL().toString() : null;
|
||||
if (srcUrl == null) {
|
||||
myErrorLabel.setText(SvnBundle.message("create.branch.no.working.copy.error", myWorkingCopyField.getText()));
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
package org.jetbrains.idea.svn.history;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
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.api.BaseSvnClient;
|
||||
import org.jetbrains.idea.svn.commandLine.CommandUtil;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnLineCommand;
|
||||
import org.tmatesoft.svn.core.ISVNLogEntryHandler;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNLogEntry;
|
||||
import org.tmatesoft.svn.core.SVNLogEntryPath;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdHistoryClient extends BaseSvnClient implements HistoryClient {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.history.CmdHistoryClient");
|
||||
|
||||
@Override
|
||||
public void doLog(@NotNull File path,
|
||||
@NotNull SVNRevision startRevision,
|
||||
@NotNull SVNRevision endRevision,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
boolean stopOnCopy,
|
||||
boolean discoverChangedPaths,
|
||||
boolean includeMergedRevisions,
|
||||
long limit,
|
||||
@Nullable String[] revisionProperties,
|
||||
@Nullable ISVNLogEntryHandler handler) throws VcsException {
|
||||
// TODO: add revision properties parameter if necessary
|
||||
// TODO: svn log command supports --xml option - could update parsing to use xml format
|
||||
|
||||
// TODO: after merge remove setting includeMergedRevisions to false and update parsing
|
||||
includeMergedRevisions = false;
|
||||
|
||||
List<String> parameters =
|
||||
prepareCommand(path, startRevision, endRevision, pegRevision, stopOnCopy, discoverChangedPaths, includeMergedRevisions, limit);
|
||||
|
||||
try {
|
||||
SvnLineCommand command = CommandUtil.runSimple(SvnCommandName.log, myVcs, path, null, parameters);
|
||||
// TODO: handler should be called in parallel with command execution, but this will be in other thread
|
||||
// TODO: check if that is ok for current handler implementation
|
||||
parseOutput(handler, command);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseOutput(@Nullable ISVNLogEntryHandler handler, @NotNull SvnLineCommand command)
|
||||
throws VcsException, SVNException {
|
||||
Parser parser = new Parser(handler);
|
||||
for (String line : StringUtil.splitByLines(command.getOutput(), false)) {
|
||||
parser.onLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> prepareCommand(@NotNull File path,
|
||||
@NotNull SVNRevision startRevision,
|
||||
@NotNull SVNRevision endRevision,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
boolean stopOnCopy, boolean discoverChangedPaths, boolean includeMergedRevisions, long limit) {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
CommandUtil.put(parameters, path, pegRevision);
|
||||
parameters.add("--revision");
|
||||
parameters.add(startRevision + ":" + endRevision);
|
||||
|
||||
CommandUtil.put(parameters, stopOnCopy, "--stop-on-copy");
|
||||
CommandUtil.put(parameters, discoverChangedPaths, "--verbose");
|
||||
CommandUtil.put(parameters, includeMergedRevisions, "--use-merge-history");
|
||||
if (limit > 0) {
|
||||
parameters.add("--limit");
|
||||
parameters.add(String.valueOf(limit));
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static class Parser {
|
||||
private static final String REVISION = "\\s*r(\\d+)\\s*";
|
||||
private static final String AUTHOR = "\\s*([^|]*)\\s*";
|
||||
private static final String DATE = "\\s*([^|]*)\\s*";
|
||||
private static final String MESSAGE_LINES = "\\s*(\\d+).*";
|
||||
|
||||
private static final Pattern ENTRY_START = Pattern.compile("-+");
|
||||
private static final Pattern DETAILS = Pattern.compile(REVISION + "\\|" + AUTHOR + "\\|" + DATE + "\\|" + MESSAGE_LINES);
|
||||
|
||||
private static final String STATUS = "\\s*(\\w)";
|
||||
private static final String PATH = "\\s*(.*?)\\s*";
|
||||
private static final String COPY_FROM_PATH = "(/[^:]*)";
|
||||
private static final String COPY_FROM_REVISION = "(\\d+)\\))\\s*";
|
||||
private static final String COPY_FROM_INFO = "((\\(from " + COPY_FROM_PATH + ":" + COPY_FROM_REVISION + ")?";
|
||||
private static final Pattern CHANGED_PATH = Pattern.compile(STATUS + PATH + COPY_FROM_INFO);
|
||||
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
|
||||
|
||||
ISVNLogEntryHandler handler;
|
||||
|
||||
Entry entry;
|
||||
boolean waitDetails;
|
||||
boolean waitChangedPath;
|
||||
boolean waitMessage;
|
||||
|
||||
public Parser(@Nullable ISVNLogEntryHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public void onLine(@NotNull String line) throws VcsException, SVNException {
|
||||
if (ENTRY_START.matcher(line).matches()) {
|
||||
processEntryStart();
|
||||
}
|
||||
else if (waitDetails) {
|
||||
processDetails(line);
|
||||
}
|
||||
else if (waitMessage) {
|
||||
processMessage(line);
|
||||
}
|
||||
else if (StringUtil.isEmpty(line.trim())) {
|
||||
processChangedPathsFinished();
|
||||
}
|
||||
else if (line.startsWith("Changed paths:")) {
|
||||
processChangedPathsStarted();
|
||||
}
|
||||
else if (waitChangedPath) {
|
||||
processChangedPath(line);
|
||||
}
|
||||
else {
|
||||
throw new VcsException("unknown state on line " + line);
|
||||
}
|
||||
}
|
||||
|
||||
private void processChangedPath(@NotNull String line) throws VcsException {
|
||||
Matcher matcher = CHANGED_PATH.matcher(line);
|
||||
if (!matcher.matches()) {
|
||||
throw new VcsException("changed path not found in " + line);
|
||||
}
|
||||
|
||||
String path = matcher.group(2);
|
||||
char type = CommandUtil.getStatusChar(matcher.group(1));
|
||||
String copyPath = matcher.group(5);
|
||||
long copyRevision = !StringUtil.isEmpty(matcher.group(6)) ? Long.valueOf(matcher.group(6)) : 0;
|
||||
|
||||
entry.changedPaths.put(path, new SVNLogEntryPath(path, type, copyPath, copyRevision));
|
||||
}
|
||||
|
||||
private void processChangedPathsStarted() {
|
||||
waitChangedPath = true;
|
||||
}
|
||||
|
||||
private void processChangedPathsFinished() {
|
||||
waitChangedPath = false;
|
||||
waitMessage = true;
|
||||
}
|
||||
|
||||
private void processMessage(@NotNull String line) {
|
||||
entry.message.append(line);
|
||||
entry.message.append(LineSeparator.LF.getSeparatorString());
|
||||
}
|
||||
|
||||
private void processDetails(@NotNull String line) throws VcsException {
|
||||
Matcher matcher = DETAILS.matcher(line);
|
||||
if (!matcher.matches()) {
|
||||
throw new VcsException("details not found in " + line);
|
||||
}
|
||||
entry.revision = Long.valueOf(matcher.group(1));
|
||||
entry.author = matcher.group(2).trim();
|
||||
entry.date = tryGetDate(matcher.group(3));
|
||||
|
||||
waitDetails = false;
|
||||
}
|
||||
|
||||
private void processEntryStart() throws SVNException {
|
||||
if (entry != null) {
|
||||
handler.handleLogEntry(entry.toLogEntry());
|
||||
}
|
||||
entry = new Entry();
|
||||
waitDetails = true;
|
||||
waitMessage = false;
|
||||
}
|
||||
|
||||
private static Date tryGetDate(@NotNull String value) {
|
||||
Date result = null;
|
||||
try {
|
||||
result = DATE_FORMAT.parse(value);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class Entry {
|
||||
Map<String, SVNLogEntryPath> changedPaths = new HashMap<String, SVNLogEntryPath>();
|
||||
long revision;
|
||||
String author;
|
||||
Date date;
|
||||
StringBuilder message = new StringBuilder();
|
||||
|
||||
private SVNLogEntry toLogEntry() {
|
||||
return new SVNLogEntry(changedPaths, revision, author, date, message.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.jetbrains.idea.svn.history;
|
||||
|
||||
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.ISVNLogEntryHandler;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface HistoryClient extends SvnClient {
|
||||
|
||||
// TODO: Url is also supported as parameter in cmd - use Target class
|
||||
void doLog(@NotNull File path,
|
||||
@NotNull SVNRevision startRevision,
|
||||
@NotNull SVNRevision endRevision,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
boolean stopOnCopy,
|
||||
boolean discoverChangedPaths,
|
||||
boolean includeMergedRevisions,
|
||||
long limit,
|
||||
@Nullable String[] revisionProperties,
|
||||
@Nullable ISVNLogEntryHandler handler) throws VcsException;
|
||||
}
|
||||
+2
-3
@@ -518,9 +518,8 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi
|
||||
revisionBefore = SVNRevision.create(revision);
|
||||
|
||||
svnurl = SVNURL.parseURIEncoded(url);
|
||||
final SVNWCClient client = myVcs.createWCClient();
|
||||
final SVNInfo info = client.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
|
||||
targetInfo = client.doInfo(new File(file.getPath()), SVNRevision.UNDEFINED);
|
||||
final SVNInfo info = myVcs.getInfo(svnurl, SVNRevision.HEAD);
|
||||
targetInfo = myVcs.getInfo(new File(file.getPath()));
|
||||
if (info == null) {
|
||||
throw new VcsException("Can not get repository URL");
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public class SvnEditCommitMessageAction extends AnAction {
|
||||
final String url = myLocation.getURL();
|
||||
final SVNURL root;
|
||||
try {
|
||||
root = SvnUtil.getRepositoryRoot(myVcs, SVNURL.parseURIEncoded(url), true);
|
||||
root = SvnUtil.getRepositoryRoot(myVcs, SVNURL.parseURIEncoded(url));
|
||||
if (root == null) {
|
||||
myException = new VcsException("Can not determine repository root for URL: " + url);
|
||||
return;
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.tmatesoft.svn.core.SVNLogEntry;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -211,7 +212,7 @@ public class SvnFileRevision implements VcsFileRevision {
|
||||
}
|
||||
|
||||
try {
|
||||
myContents = SvnUtil.getFileContents(myVCS, myURL, true, myRevision, myPegRevision);
|
||||
myContents = SvnUtil.getFileContents(myVCS, SvnTarget.fromURL(SvnUtil.parseUrl(myURL)), myRevision, myPegRevision);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
myException = e;
|
||||
|
||||
@@ -42,7 +42,6 @@ import org.jetbrains.idea.svn.*;
|
||||
import org.tmatesoft.svn.core.*;
|
||||
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
|
||||
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
|
||||
import org.tmatesoft.svn.core.io.SVNRepository;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
import org.tmatesoft.svn.util.SVNLogType;
|
||||
|
||||
@@ -50,7 +49,6 @@ import javax.swing.*;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@@ -285,18 +283,9 @@ public class SvnHistoryProvider
|
||||
|
||||
@Override
|
||||
protected void preliminary() throws SVNException {
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
myInfo = wcClient.doInfo(new File(myFile.getIOFile().getAbsolutePath()), SVNRevision.UNDEFINED);
|
||||
wcClient.setEventHandler(new ISVNEventHandler() {
|
||||
public void handleEvent(SVNEvent event, double progress) throws SVNException {
|
||||
}
|
||||
|
||||
public void checkCancelled() throws SVNCancelException {
|
||||
myPI.checkCanceled();
|
||||
}
|
||||
});
|
||||
myInfo = myVcs.getInfo(myFile.getIOFile());
|
||||
if (myInfo == null || myInfo.getRepositoryRootURL() == null) {
|
||||
myException = new VcsException("File ''{0}'' is not under version control" + myFile.getIOFile());
|
||||
myException = new VcsException("File " + myFile.getPath() + " is not under version control");
|
||||
return;
|
||||
}
|
||||
if (myInfo.getURL() == null) {
|
||||
@@ -319,14 +308,15 @@ public class SvnHistoryProvider
|
||||
myPI.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", myUrl));
|
||||
}
|
||||
final SVNRevision pegRevision = myInfo.getRevision();
|
||||
SVNLogClient client = myVcs.createLogClient();
|
||||
try {
|
||||
// a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
|
||||
client
|
||||
.doLog(new File[]{new File(myFile.getIOFile().getAbsolutePath())},
|
||||
myFrom == null ? SVNRevision.HEAD : myFrom, myTo == null ? SVNRevision.create(1) : myTo, myPeg,
|
||||
false, true, myShowMergeSources && mySupport15, myLimit + 1, null,
|
||||
new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl, createConsumerAdapter(myConsumer), repoRootURL, myFile.getCharset()));
|
||||
myVcs.getFactory(myFile.getIOFile()).createHistoryClient().doLog(
|
||||
myFile.getIOFile(),
|
||||
myFrom == null ? SVNRevision.HEAD : myFrom,
|
||||
myTo == null ? SVNRevision.create(1) : myTo, myPeg,
|
||||
false, true, myShowMergeSources && mySupport15, myLimit + 1, null,
|
||||
new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl,
|
||||
createConsumerAdapter(myConsumer),
|
||||
repoRootURL, myFile.getCharset()));
|
||||
}
|
||||
catch (SVNCancelException e) {
|
||||
//
|
||||
@@ -383,7 +373,6 @@ public class SvnHistoryProvider
|
||||
}
|
||||
}
|
||||
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
final SVNURL svnurl = SVNURL.parseURIEncoded(myUrl);
|
||||
SVNRevision operationalFrom = myFrom == null ? SVNRevision.HEAD : myFrom;
|
||||
final SVNURL rootURL = getRepositoryRoot(svnurl, myFrom);
|
||||
@@ -395,6 +384,7 @@ public class SvnHistoryProvider
|
||||
if (myUrl.startsWith(root)) {
|
||||
relativeUrl = myUrl.substring(root.length());
|
||||
}
|
||||
// TODO: Update this call to myVcs.getFactory.createHistoryClient
|
||||
SVNLogClient client = myVcs.createLogClient();
|
||||
// a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
|
||||
client.doLog(svnurl, new String[]{}, myPeg == null ? myFrom : myPeg,
|
||||
@@ -420,6 +410,7 @@ public class SvnHistoryProvider
|
||||
relativeUrl = myUrl.substring(root.length());
|
||||
}
|
||||
|
||||
// TODO: Update this call to myVcs.getFactory.createHistoryClient
|
||||
SVNLogClient client = myVcs.createLogClient();
|
||||
|
||||
final RepositoryLogEntryHandler repositoryLogEntryHandler =
|
||||
@@ -437,36 +428,15 @@ public class SvnHistoryProvider
|
||||
}
|
||||
|
||||
private SVNURL getRepositoryRoot(SVNURL svnurl, SVNRevision operationalFrom) throws SVNException {
|
||||
final SVNRepository repository = myVcs.createRepository(svnurl);
|
||||
final SVNURL root = repository.getRepositoryRoot(false);
|
||||
if (root == null) {
|
||||
return repository.getRepositoryRoot(true);
|
||||
}
|
||||
return root;
|
||||
/*final SVNWCClient wcClient = myVcs.createWCClient();
|
||||
try {
|
||||
final SVNInfo info;
|
||||
info = wcClient.doInfo(svnurl, myPeg, operationalFrom);
|
||||
return info.getRepositoryRootURL();
|
||||
}
|
||||
catch (SVNException e) {
|
||||
try {
|
||||
final SVNInfo info;
|
||||
info = wcClient.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.UNDEFINED);
|
||||
return info.getRepositoryRootURL();
|
||||
} catch (SVNException e1) {
|
||||
final SVNInfo info;
|
||||
info = wcClient.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
|
||||
return info.getRepositoryRootURL();
|
||||
}
|
||||
}*/
|
||||
SVNInfo info = myVcs.getInfo(svnurl, SVNRevision.HEAD);
|
||||
|
||||
return info != null ? info.getRepositoryRootURL() : null;
|
||||
}
|
||||
|
||||
private boolean existsNow(SVNURL svnurl) {
|
||||
final SVNWCClient wcClient = myVcs.createWCClient();
|
||||
final SVNInfo info;
|
||||
try {
|
||||
info = wcClient.doInfo(svnurl, SVNRevision.HEAD, SVNRevision.HEAD);
|
||||
info = myVcs.getInfo(svnurl, SVNRevision.HEAD, SVNRevision.HEAD, null);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return false;
|
||||
|
||||
@@ -20,21 +20,19 @@ import com.intellij.openapi.vcs.history.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.SvnRevisionNumber;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.SVNInfo;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNWCClient;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Irina.Chernushina
|
||||
* Date: 4/27/12
|
||||
* Time: 12:24 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Irina.Chernushina
|
||||
* Date: 4/27/12
|
||||
* Time: 12:24 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class SvnHistorySession extends VcsAbstractHistorySession {
|
||||
private final SvnVcs myVcs;
|
||||
private final FilePath myCommittedPath;
|
||||
@@ -71,19 +69,8 @@ public class SvnHistorySession extends VcsAbstractHistorySession {
|
||||
}
|
||||
|
||||
public static VcsRevisionNumber getCurrentCommittedRevision(final SvnVcs vcs, final File file) {
|
||||
try {
|
||||
SVNWCClient wcClient = vcs.createWCClient();
|
||||
SVNInfo info = wcClient.doInfo(file, SVNRevision.UNDEFINED);
|
||||
if (info != null) {
|
||||
return new SvnRevisionNumber(info.getCommittedRevision());
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return null;
|
||||
}
|
||||
SVNInfo info = vcs.getInfo(file);
|
||||
return info != null ? new SvnRevisionNumber(info.getCommittedRevision()) : null;
|
||||
}
|
||||
|
||||
public FilePath getCommittedPath() {
|
||||
@@ -101,7 +88,8 @@ public class SvnHistorySession extends VcsAbstractHistorySession {
|
||||
|
||||
@Override
|
||||
public VcsHistorySession copy() {
|
||||
return new SvnHistorySession(myVcs, getRevisionList(), myCommittedPath, myHaveMergeSources, getCurrentRevisionNumber(), true, myHasLocalSource);
|
||||
return new SvnHistorySession(myVcs, getRevisionList(), myCommittedPath, myHaveMergeSources, getCurrentRevisionNumber(), true,
|
||||
myHasLocalSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.jetbrains.idea.svn.history;
|
||||
|
||||
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.tmatesoft.svn.core.ISVNLogEntryHandler;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.wc.SVNLogClient;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitHistoryClient extends BaseSvnClient implements HistoryClient {
|
||||
@Override
|
||||
public void doLog(@NotNull File path,
|
||||
@NotNull SVNRevision startRevision,
|
||||
@NotNull SVNRevision endRevision,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
boolean stopOnCopy,
|
||||
boolean discoverChangedPaths,
|
||||
boolean includeMergedRevisions,
|
||||
long limit,
|
||||
@Nullable String[] revisionProperties,
|
||||
@Nullable ISVNLogEntryHandler handler) throws VcsException {
|
||||
try {
|
||||
// TODO: a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
|
||||
SVNLogClient client = myVcs.createLogClient();
|
||||
|
||||
client.doLog(new File[]{path}, startRevision, endRevision, pegRevision, stopOnCopy, discoverChangedPaths, includeMergedRevisions,
|
||||
limit, revisionProperties, handler);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-16
@@ -38,13 +38,10 @@ import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vcs.impl.ContentRevisionCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
import org.jetbrains.idea.svn.SvnRevisionNumber;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.*;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.io.SVNRepository;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -108,7 +105,7 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC
|
||||
else {
|
||||
loader.run();
|
||||
}
|
||||
final SVNException exception = loader.getException();
|
||||
final Exception exception = loader.getException();
|
||||
if (exception != null) {
|
||||
throw new VcsException(exception);
|
||||
}
|
||||
@@ -148,7 +145,7 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC
|
||||
private final String myPath;
|
||||
private final long myRevision;
|
||||
private final OutputStream myDst;
|
||||
private SVNException myException;
|
||||
private Exception myException;
|
||||
|
||||
public ContentLoader(String path, OutputStream dst, long revision) {
|
||||
myPath = path;
|
||||
@@ -156,7 +153,7 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC
|
||||
myRevision = revision;
|
||||
}
|
||||
|
||||
public SVNException getException() {
|
||||
public Exception getException() {
|
||||
return myException;
|
||||
}
|
||||
|
||||
@@ -166,16 +163,16 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC
|
||||
progress.setText(SvnBundle.message("progress.text.loading.contents", myPath));
|
||||
progress.setText2(SvnBundle.message("progress.text2.revision.information", myRevision));
|
||||
}
|
||||
|
||||
try {
|
||||
SVNRepository repository = myVcs.createRepository(getFullPath());
|
||||
try {
|
||||
repository.getFile("", myRevision, null, myDst);
|
||||
}
|
||||
finally {
|
||||
repository.closeSession();
|
||||
}
|
||||
byte[] contents = SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(SvnUtil.parseUrl(getFullPath())), SVNRevision.create(myRevision),
|
||||
SVNRevision.UNDEFINED);
|
||||
myDst.write(contents);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
catch (VcsException e) {
|
||||
myException = e;
|
||||
}
|
||||
catch (IOException e) {
|
||||
myException = e;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-12
@@ -251,19 +251,10 @@ public class IntegratedSelectedOptionsDialog extends DialogWrapper {
|
||||
|
||||
@Nullable
|
||||
private static SVNURL realTargetUrl(final SvnVcs vcs, final WorkingCopyInfo info, final String targetBranchUrl) {
|
||||
final SVNWCClient client = vcs.createWCClient();
|
||||
try {
|
||||
final SVNInfo svnInfo = client.doInfo(new File(info.getLocalPath()), SVNRevision.UNDEFINED);
|
||||
final SVNURL svnurl = svnInfo.getURL();
|
||||
final SVNInfo svnInfo = vcs.getInfo(info.getLocalPath());
|
||||
final SVNURL svnurl = svnInfo != null ? svnInfo.getURL() : null;
|
||||
|
||||
if ((svnurl != null) && (svnurl.toString().startsWith(targetBranchUrl))) {
|
||||
return svnurl;
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
// tracked by return value
|
||||
}
|
||||
return null;
|
||||
return (svnurl != null) && (svnurl.toString().startsWith(targetBranchUrl)) ? svnurl : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -238,12 +238,7 @@ public class BranchInfo {
|
||||
}
|
||||
|
||||
private SVNInfo getInfo(final File pathFile) {
|
||||
try {
|
||||
return myClient.doInfo(pathFile, SVNRevision.UNDEFINED);
|
||||
} catch (SVNException e) {
|
||||
//
|
||||
}
|
||||
return null;
|
||||
return myVcs.getInfo(pathFile);
|
||||
}
|
||||
|
||||
private SvnMergeInfoCache.MergeCheckResult checkPathGoingUp(final long revisionAsked, final long targetRevision, final String branchRootPath,
|
||||
|
||||
@@ -117,6 +117,7 @@ public class PortableStatus extends SVNStatus {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
// TODO: Update working copy format detection
|
||||
setWorkingCopyFormat(WorkingCopyFormat.ONE_DOT_SEVEN.getFormat());
|
||||
}
|
||||
|
||||
@@ -241,6 +242,30 @@ public class PortableStatus extends SVNStatus {
|
||||
return url == null ? null : url.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SVNURL getURL() {
|
||||
SVNURL url = super.getURL();
|
||||
|
||||
if (url == null) {
|
||||
SVNInfo info = initInfo();
|
||||
url = info != null ? info.getURL() : url;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = super.getFile();
|
||||
|
||||
if (file == null) {
|
||||
SVNInfo info = initInfo();
|
||||
file = info != null ? info.getFile() : file;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SVNRevision getRevision() {
|
||||
final SVNRevision revision = super.getRevision();
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.jetbrains.idea.svn.properties;
|
||||
|
||||
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.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.SVNPropertyValue;
|
||||
import org.tmatesoft.svn.core.wc.SVNInfo;
|
||||
import org.tmatesoft.svn.core.wc.SVNPropertyData;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SVNPropertyData getProperty(@NotNull File path,
|
||||
@NotNull String property,
|
||||
boolean revisionProperty,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
@Nullable SVNRevision revision)
|
||||
throws VcsException {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
parameters.add(property);
|
||||
CommandUtil.put(parameters, path, pegRevision);
|
||||
if (!revisionProperty) {
|
||||
CommandUtil.put(parameters, revision);
|
||||
} else {
|
||||
parameters.add("--revprop");
|
||||
CommandUtil.put(parameters, resolveRevisionNumber(path, revision));
|
||||
}
|
||||
|
||||
SvnCommand command = CommandUtil.execute(myVcs, SvnCommandName.propget, parameters, null);
|
||||
|
||||
return new SVNPropertyData(property, SVNPropertyValue.create(StringUtil.nullize(command.getOutput())), null);
|
||||
}
|
||||
|
||||
private SVNRevision resolveRevisionNumber(@NotNull File path, @Nullable SVNRevision revision) throws VcsException {
|
||||
long result = revision != null ? revision.getNumber() : -1;
|
||||
|
||||
// base should be resolved manually - could not set revision to BASE to get revision property
|
||||
if (SVNRevision.BASE.equals(revision)) {
|
||||
SVNInfo info = myVcs.getInfo(path, SVNRevision.BASE);
|
||||
|
||||
result = info != null ? info.getRevision().getNumber() : -1;
|
||||
}
|
||||
|
||||
if (result == -1) {
|
||||
throw new VcsException("Could not determine revision number for file " + path + " and revision " + revision);
|
||||
}
|
||||
|
||||
return SVNRevision.create(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.jetbrains.idea.svn.properties;
|
||||
|
||||
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.SVNPropertyData;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface PropertyClient extends SvnClient {
|
||||
|
||||
@Nullable
|
||||
SVNPropertyData getProperty(@NotNull final File path,
|
||||
@NotNull final String property,
|
||||
boolean revisionProperty,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
@Nullable SVNRevision revision) throws VcsException;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.jetbrains.idea.svn.properties;
|
||||
|
||||
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.tmatesoft.svn.core.SVNException;
|
||||
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 java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClient {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SVNPropertyData getProperty(@NotNull File path,
|
||||
@NotNull String property,
|
||||
boolean revisionProperty,
|
||||
@Nullable SVNRevision pegRevision,
|
||||
@Nullable SVNRevision revision) throws VcsException {
|
||||
try {
|
||||
if (!revisionProperty) {
|
||||
return myVcs.createWCClient().doGetProperty(path, property, pegRevision, revision);
|
||||
} else {
|
||||
return getRevisionProperty(path, property, revision);
|
||||
}
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private SVNPropertyData getRevisionProperty(@NotNull File path, @NotNull final String property, @Nullable SVNRevision revision) throws SVNException{
|
||||
final SVNWCClient client = myVcs.createWCClient();
|
||||
final SVNPropertyData[] result = new SVNPropertyData[1];
|
||||
|
||||
client.doGetRevisionProperty(path, null, revision, new ISVNPropertyHandler() {
|
||||
@Override
|
||||
public void handleProperty(File path, SVNPropertyData property) throws SVNException {
|
||||
handle(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
|
||||
handle(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
|
||||
handle(property);
|
||||
}
|
||||
|
||||
private void handle(@NotNull SVNPropertyData data) {
|
||||
if (property.equals(data.getName())) {
|
||||
result[0] = data;
|
||||
}
|
||||
}
|
||||
});
|
||||
return result[0];
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn.properties;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Irina.Chernushina
|
||||
* Date: 2/12/12
|
||||
* Time: 8:40 PM
|
||||
*/
|
||||
public class SvnPropDetailsProvider {
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user