diff options
Diffstat (limited to 'plugins/svn4idea/src/org/jetbrains/idea/svn/history')
22 files changed, 535 insertions, 254 deletions
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java index 3494b9ac9d28..ca934d4a40e4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java @@ -9,19 +9,15 @@ import org.jetbrains.idea.svn.commandLine.CommandExecutor; import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.commandLine.SvnCommandName; -import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import javax.xml.bind.JAXBException; -import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlValue; import java.util.ArrayList; -import java.util.Date; import java.util.List; -import java.util.Map; /** * @author Konstantin Kolosovsky. @@ -37,7 +33,7 @@ public class CmdHistoryClient extends BaseSvnClient implements HistoryClient { boolean includeMergedRevisions, long limit, @Nullable String[] revisionProperties, - @Nullable ISVNLogEntryHandler handler) throws VcsException { + @Nullable LogEntryConsumer handler) throws VcsException { // TODO: add revision properties parameter if necessary List<String> parameters = @@ -54,13 +50,13 @@ public class CmdHistoryClient extends BaseSvnClient implements HistoryClient { } } - private static void parseOutput(@NotNull CommandExecutor command, @Nullable ISVNLogEntryHandler handler) + private static void parseOutput(@NotNull CommandExecutor command, @Nullable LogEntryConsumer handler) throws VcsException, SVNException { try { LogInfo log = CommandUtil.parse(command.getOutput(), LogInfo.class); if (handler != null && log != null) { - for (LogEntry entry : log.entries) { + for (LogEntry.Builder entry : log.entries) { iterateRecursively(entry, handler); } } @@ -70,16 +66,16 @@ public class CmdHistoryClient extends BaseSvnClient implements HistoryClient { } } - private static void iterateRecursively(@NotNull LogEntry entry, @NotNull ISVNLogEntryHandler handler) throws SVNException { - handler.handleLogEntry(entry.toLogEntry()); + private static void iterateRecursively(@NotNull LogEntry.Builder entry, @NotNull LogEntryConsumer handler) throws SVNException { + handler.consume(entry.build()); - for (LogEntry childEntry : entry.childEntries) { + for (LogEntry.Builder childEntry : entry.getChildEntries()) { iterateRecursively(childEntry, handler); } if (entry.hasChildren()) { // empty log entry passed to handler to fully correspond to SVNKit behavior. - handler.handleLogEntry(SVNLogEntry.EMPTY_ENTRY); + handler.consume(LogEntry.EMPTY); } } @@ -109,81 +105,6 @@ public class CmdHistoryClient extends BaseSvnClient implements HistoryClient { public static class LogInfo { @XmlElement(name = "logentry") - public List<LogEntry> entries = new ArrayList<LogEntry>(); - } - - public static class LogEntry { - - @XmlAttribute(name = "revision") - public long revision; - - @XmlElement(name = "author") - public String author; - - @XmlElement(name = "date") - public Date date; - - @XmlElement(name = "msg") - public String message; - - @XmlElement(name = "paths") - public ChangedPaths changedPaths; - - @XmlElement(name = "logentry") - public List<LogEntry> childEntries = new ArrayList<LogEntry>(); - - public boolean hasChildren() { - return !childEntries.isEmpty(); - } - - public SVNLogEntry toLogEntry() { - SVNLogEntry entry = new SVNLogEntry(toChangedPathsMap(), revision, author, date, message); - - entry.setHasChildren(hasChildren()); - - return entry; - } - - public Map<String, SVNLogEntryPath> toChangedPathsMap() { - return changedPaths != null ? changedPaths.toMap() : ContainerUtil.<String, SVNLogEntryPath>newHashMap(); - } - } - - public static class ChangedPaths { - - @XmlElement(name = "path") - public List<ChangedPath> changedPaths = new ArrayList<ChangedPath>(); - - public Map<String, SVNLogEntryPath> toMap() { - Map<String, SVNLogEntryPath> changes = ContainerUtil.newHashMap(); - - for (ChangedPath path : changedPaths) { - changes.put(path.path, path.toLogEntryPath()); - } - - return changes; - } - } - - public static class ChangedPath { - - @XmlAttribute(name = "kind") - public String kind; - - @XmlAttribute(name = "action") - public String action; - - @XmlAttribute(name = "copyfrom-path") - public String copyFromPath; - - @XmlAttribute(name = "copyfrom-rev") - public long copyFromRevision; - - @XmlValue - public String path; - - public SVNLogEntryPath toLogEntryPath() { - return new SVNLogEntryPath(path, CommandUtil.getStatusChar(action), copyFromPath, copyFromRevision); - } + public List<LogEntry.Builder> entries = ContainerUtil.newArrayList(); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java index f871ee09855a..a075251e7675 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java @@ -125,7 +125,7 @@ public class FirstInBranch implements Runnable { } } - private static class MyLogEntryHandler implements ISVNLogEntryHandler { + private static class MyLogEntryHandler implements LogEntryConsumer { @NotNull private final SvnPathThroughHistoryCorrection myTrunkCorrector; @NotNull private final SvnPathThroughHistoryCorrection myBranchCorrector; @@ -137,17 +137,18 @@ public class FirstInBranch implements Runnable { myBranchCorrector = new SvnPathThroughHistoryCorrection(branchUrl); } - public void handleLogEntry(SVNLogEntry logEntry) throws SVNException { + @Override + public void consume(LogEntry logEntry) throws SVNException { final Map map = logEntry.getChangedPaths(); checkEntries(logEntry, map); - myTrunkCorrector.handleLogEntry(logEntry); - myBranchCorrector.handleLogEntry(logEntry); + myTrunkCorrector.consume(logEntry); + myBranchCorrector.consume(logEntry); checkEntries(logEntry, map); } - private void checkEntries(SVNLogEntry logEntry, Map map) throws SVNCancelException { + private void checkEntries(LogEntry logEntry, Map map) throws SVNCancelException { for (Object o : map.values()) { - final SVNLogEntryPath path = (SVNLogEntryPath) o; + final LogEntryPath path = (LogEntryPath) o; final String localPath = path.getPath(); final String copyPath = path.getCopyPath(); @@ -159,7 +160,7 @@ public class FirstInBranch implements Runnable { } } - private boolean checkForCopyCase(SVNLogEntry logEntry, SVNLogEntryPath path, String localPath, String copyPath, + private boolean checkForCopyCase(LogEntry logEntry, LogEntryPath path, String localPath, String copyPath, final String trunkUrl, final String branchUrl) { if (equalOrParent(localPath, branchUrl) && equalOrParent(copyPath, trunkUrl)) { myCopyDataConsumer.consume(new CopyData(path.getCopyRevision(), logEntry.getRevision(), true)); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java index d719e755e661..c85eb9e65968 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java @@ -4,7 +4,6 @@ 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 org.tmatesoft.svn.core.wc2.SvnTarget; @@ -21,5 +20,5 @@ public interface HistoryClient extends SvnClient { boolean includeMergedRevisions, long limit, @Nullable String[] revisionProperties, - @Nullable ISVNLogEntryHandler handler) throws VcsException; + @Nullable LogEntryConsumer handler) throws VcsException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LatestExistentSearcher.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LatestExistentSearcher.java index dc1def418e99..030db0db6ef3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LatestExistentSearcher.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LatestExistentSearcher.java @@ -25,9 +25,10 @@ import org.jetbrains.idea.svn.RootUrlInfo; import org.jetbrains.idea.svn.SvnFileUrlMapping; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.jetbrains.idea.svn.info.Info; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNURLUtil; -import org.tmatesoft.svn.core.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -84,9 +85,6 @@ public class LatestExistentSearcher { myVcs.getFactory(target).createHistoryClient().doLog(target, startRevision, SVNRevision.HEAD, false, true, false, 0, null, createHandler(latest)); } - catch (SVNException e) { - LOG.info(e); - } catch (VcsException e) { LOG.info(e); } @@ -95,12 +93,13 @@ public class LatestExistentSearcher { } @NotNull - private ISVNLogEntryHandler createHandler(@NotNull final Ref<Long> latest) { - return new ISVNLogEntryHandler() { - public void handleLogEntry(final SVNLogEntry logEntry) throws SVNException { + private LogEntryConsumer createHandler(@NotNull final Ref<Long> latest) { + return new LogEntryConsumer() { + @Override + public void consume(final LogEntry logEntry) throws SVNException { final Map changedPaths = logEntry.getChangedPaths(); for (Object o : changedPaths.values()) { - final SVNLogEntryPath path = (SVNLogEntryPath)o; + final LogEntryPath path = (LogEntryPath)o; if ((path.getType() == 'D') && (myRelativeUrl.equals(path.getPath()))) { latest.set(logEntry.getRevision()); throw new SVNException(SVNErrorMessage.UNKNOWN_ERROR_MESSAGE); @@ -125,7 +124,7 @@ public class LatestExistentSearcher { } } } - catch (SVNException e) { + catch (SvnBindException e) { LOG.info(e); } @@ -138,7 +137,7 @@ public class LatestExistentSearcher { final RootUrlInfo rootUrlInfo = mapping.getWcRootForUrl(myUrl.toString()); if (rootUrlInfo == null) return true; final VirtualFile vf = rootUrlInfo.getVirtualFile(); - final SVNInfo info = myVcs.getInfo(vf); + final Info info = myVcs.getInfo(vf); if ((info == null) || (info.getRevision() == null)) { return false; } @@ -149,24 +148,24 @@ public class LatestExistentSearcher { } @Nullable - private SVNURL getExistingParent(SVNURL url) throws SVNException { + private SVNURL getExistingParent(SVNURL url) throws SvnBindException { while (url != null && !url.equals(myRepositoryUrl) && !existsInRevision(url, myEndNumber)) { - url = url.removePathTail(); + url = SvnUtil.removePathTail(url); } return url; } - private boolean existsInRevision(@NotNull SVNURL url, long revisionNumber) throws SVNException { + private boolean existsInRevision(@NotNull SVNURL url, long revisionNumber) throws SvnBindException { SVNRevision revision = SVNRevision.create(revisionNumber); - SVNInfo info = null; + Info info = null; try { info = myVcs.getInfo(url, revision, revision); } - catch (SVNException e) { + catch (SvnBindException e) { // throw error if not "does not exist" error code - if (!SVNErrorCode.RA_ILLEGAL_URL.equals(e.getErrorMessage().getErrorCode())) { + if (!e.contains(SVNErrorCode.RA_ILLEGAL_URL)) { throw e; } } @@ -174,7 +173,7 @@ public class LatestExistentSearcher { return info != null; } - private long getLatestRevision() throws SVNException { + private long getLatestRevision() throws SvnBindException { return SvnUtil.getHeadRevision(myVcs, myRepositoryUrl).getNumber(); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogEntry.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogEntry.java new file mode 100644 index 000000000000..1b3d12656d2b --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogEntry.java @@ -0,0 +1,187 @@ +/* + * Copyright 2000-2014 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.history; + +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.tmatesoft.svn.core.SVNLogEntry; +import org.tmatesoft.svn.core.SVNLogEntryPath; + +import javax.xml.bind.annotation.*; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author Konstantin Kolosovsky. + */ +public class LogEntry { + + public static final LogEntry EMPTY = new LogEntry.Builder().setRevision(-1).setHasChildren(false).build(); + + private final long myRevision; + private final Date myDate; + private final String myMessage; + private final String myAuthor; + @NotNull private final Map<String, LogEntryPath> myChangedPaths; + private boolean myHasChildren; + + @Nullable + public static LogEntry create(@Nullable SVNLogEntry entry) { + LogEntry result = null; + + if (entry != null) { + LogEntry.Builder builder = new LogEntry.Builder(); + + if (entry.getChangedPaths() != null) { + for (SVNLogEntryPath path : entry.getChangedPaths().values()) { + builder.addPath(LogEntryPath.create(path)); + } + } + + result = builder.setRevision(entry.getRevision()).setAuthor(entry.getAuthor()).setDate(entry.getDate()).setMessage(entry.getMessage()) + .setHasChildren(entry.hasChildren()).build(); + } + + return result; + } + + public LogEntry(@NotNull LogEntry.Builder builder) { + myRevision = builder.revision; + myChangedPaths = toImmutable(builder.changedPaths); + myAuthor = builder.author; + myDate = builder.date; + myMessage = builder.message; + myHasChildren = builder.hasChildren(); + } + + @NotNull + private static Map<String, LogEntryPath> toImmutable(@NotNull List<LogEntryPath.Builder> paths) { + ContainerUtil.ImmutableMapBuilder<String, LogEntryPath> builder = ContainerUtil.immutableMapBuilder(); + + for (LogEntryPath.Builder path : paths) { + builder.put(path.getPath(), path.build()); + } + + return builder.build(); + } + + @NotNull + public Map<String, LogEntryPath> getChangedPaths() { + return myChangedPaths; + } + + public String getAuthor() { + return myAuthor; + } + + public Date getDate() { + return myDate; + } + + public String getMessage() { + return myMessage; + } + + public long getRevision() { + return myRevision; + } + + public boolean hasChildren() { + return myHasChildren; + } + + @XmlAccessorType(XmlAccessType.NONE) + // type explicitly specified not to conflict with LogEntryPath.Builder + @XmlType(name = "logentry") + public static class Builder { + + @XmlAttribute(name = "revision") + private long revision; + + @XmlElement(name = "author") + private String author; + + @XmlElement(name = "date") + private Date date; + + @XmlElement(name = "msg") + private String message; + + @XmlElementWrapper(name = "paths") + @XmlElement(name = "path") + private List<LogEntryPath.Builder> changedPaths = ContainerUtil.newArrayList(); + + @XmlElement(name = "logentry") + private List<LogEntry.Builder> childEntries = ContainerUtil.newArrayList(); + + @NotNull + public List<LogEntry.Builder> getChildEntries() { + return childEntries; + } + + public boolean hasChildren() { + return !childEntries.isEmpty(); + } + + @NotNull + public Builder setRevision(long revision) { + this.revision = revision; + return this; + } + + @NotNull + public Builder setAuthor(String author) { + this.author = author; + return this; + } + + @NotNull + public Builder setDate(Date date) { + this.date = date; + return this; + } + + @NotNull + public Builder setMessage(String message) { + this.message = message; + return this; + } + + @NotNull + public Builder setHasChildren(boolean hasChildren) { + // probably LogEntry interface will be changed and child entries will be specified explicitly later, but for now just use such "fake" + // implementation for setting "hasChildren" value + childEntries.clear(); + if (hasChildren) { + childEntries.add(this); + } + return this; + } + + @NotNull + public Builder addPath(@NotNull LogEntryPath.Builder path) { + changedPaths.add(path); + return this; + } + + @NotNull + public LogEntry build() { + return new LogEntry(this); + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogEntryConsumer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogEntryConsumer.java new file mode 100644 index 000000000000..b3269b1afb41 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogEntryConsumer.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2014 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.history; + +import com.intellij.util.ThrowableConsumer; +import org.tmatesoft.svn.core.SVNException; + +/** + * @author Konstantin Kolosovsky. + */ +public interface LogEntryConsumer extends ThrowableConsumer<LogEntry, SVNException> { +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogEntryPath.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogEntryPath.java new file mode 100644 index 000000000000..41215f71f76e --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogEntryPath.java @@ -0,0 +1,132 @@ +/* + * Copyright 2000-2014 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.history; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.api.BaseNodeDescription; +import org.jetbrains.idea.svn.api.NodeKind; +import org.jetbrains.idea.svn.commandLine.CommandUtil; +import org.tmatesoft.svn.core.SVNLogEntryPath; + +import javax.xml.bind.annotation.*; + +/** + * @author Konstantin Kolosovsky. + */ +public class LogEntryPath extends BaseNodeDescription { + + private final String myPath; + private final char myType; + private final String myCopyPath; + private final long myCopyRevision; + + @NotNull + public static LogEntryPath.Builder create(@NotNull SVNLogEntryPath path) { + return new LogEntryPath.Builder().setPath(path.getPath()).setType(path.getType()).setCopyFromPath( + path.getCopyPath()).setCopyFromRevision(path.getCopyRevision()).setKind(NodeKind.from(path.getKind())); + } + + public LogEntryPath(@NotNull LogEntryPath.Builder builder) { + super(builder.kind); + myPath = builder.path; + myType = CommandUtil.getStatusChar(builder.action); + myCopyPath = builder.copyFromPath; + myCopyRevision = builder.copyFromRevision; + } + + public String getCopyPath() { + return myCopyPath; + } + + public long getCopyRevision() { + return myCopyRevision; + } + + public String getPath() { + return myPath; + } + + public char getType() { + return myType; + } + + @NotNull + public NodeKind getKind() { + return myKind; + } + + @XmlAccessorType(XmlAccessType.NONE) + // type explicitly specified not to conflict with LogEntry.Builder + @XmlType(name = "logentrypath") + public static class Builder { + + // empty string could be here if repository was < 1.6 when committing (see comments in schema for svn client xml output , in + // svn source code repository) - this will result in kind = NodeKind.UNKNOWN + @XmlAttribute(name = "kind", required = true) + private NodeKind kind; + + @XmlAttribute(name = "action") + private String action; + + @XmlAttribute(name = "copyfrom-path") + private String copyFromPath; + + @XmlAttribute(name = "copyfrom-rev") + private long copyFromRevision; + + @XmlValue + private String path; + + public String getPath() { + return path; + } + + @NotNull + public Builder setKind(@NotNull NodeKind kind) { + this.kind = kind; + return this; + } + + @NotNull + public Builder setType(char type) { + this.action = String.valueOf(type); + return this; + } + + @NotNull + public Builder setCopyFromPath(String copyFromPath) { + this.copyFromPath = copyFromPath; + return this; + } + + @NotNull + public Builder setCopyFromRevision(long copyFromRevision) { + this.copyFromRevision = copyFromRevision; + return this; + } + + @NotNull + public Builder setPath(String path) { + this.path = path; + return this; + } + + @NotNull + public LogEntryPath build() { + return new LogEntryPath(this); + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/TreeStructureNode.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogHierarchyNode.java index 370f54f9ef22..d9ce35a100e4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/TreeStructureNode.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LogHierarchyNode.java @@ -18,24 +18,24 @@ package org.jetbrains.idea.svn.history; import java.util.LinkedList; import java.util.List; -public class TreeStructureNode<T> { - private final T myMe; - private final List<TreeStructureNode<T>> myChildren; +public class LogHierarchyNode { + private final LogEntry myMe; + private final List<LogHierarchyNode> myChildren; - public TreeStructureNode(final T me) { - myChildren = new LinkedList<TreeStructureNode<T>>(); + public LogHierarchyNode(final LogEntry me) { + myChildren = new LinkedList<LogHierarchyNode>(); myMe = me; } - public void add(final T child) { - myChildren.add(new TreeStructureNode<T>(child)); + public void add(final LogEntry child) { + myChildren.add(new LogHierarchyNode(child)); } - public List<TreeStructureNode<T>> getChildren() { + public List<LogHierarchyNode> getChildren() { return myChildren; } - public T getMe() { + public LogEntry getMe() { return myMe; } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/MergeSourceHierarchyBuilder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/MergeSourceHierarchyBuilder.java index f0a77198925d..87896a739bca 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/MergeSourceHierarchyBuilder.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/MergeSourceHierarchyBuilder.java @@ -20,24 +20,23 @@ import com.intellij.util.Consumer; import com.intellij.util.ThrowableConsumer; import org.jetbrains.annotations.NotNull; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNLogEntry; import java.util.List; /** * @author Konstantin Kolosovsky. */ -public class MergeSourceHierarchyBuilder implements ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException> { +public class MergeSourceHierarchyBuilder implements ThrowableConsumer<Pair<LogEntry, Integer>, SVNException> { - private TreeStructureNode<SVNLogEntry> myCurrentHierarchy; - @NotNull private final Consumer<TreeStructureNode<SVNLogEntry>> myConsumer; + private LogHierarchyNode myCurrentHierarchy; + @NotNull private final Consumer<LogHierarchyNode> myConsumer; - public MergeSourceHierarchyBuilder(@NotNull Consumer<TreeStructureNode<SVNLogEntry>> consumer) { + public MergeSourceHierarchyBuilder(@NotNull Consumer<LogHierarchyNode> consumer) { myConsumer = consumer; } - public void consume(Pair<SVNLogEntry, Integer> svnLogEntryIntegerPair) throws SVNException { - final SVNLogEntry logEntry = svnLogEntryIntegerPair.getFirst(); + public void consume(Pair<LogEntry, Integer> svnLogEntryIntegerPair) throws SVNException { + final LogEntry logEntry = svnLogEntryIntegerPair.getFirst(); final Integer mergeLevel = svnLogEntryIntegerPair.getSecond(); if (mergeLevel < 0) { @@ -45,11 +44,11 @@ public class MergeSourceHierarchyBuilder implements ThrowableConsumer<Pair<SVNLo myConsumer.consume(myCurrentHierarchy); } if (logEntry.hasChildren()) { - myCurrentHierarchy = new TreeStructureNode<SVNLogEntry>(logEntry); + myCurrentHierarchy = new LogHierarchyNode(logEntry); } else { // just pass myCurrentHierarchy = null; - myConsumer.consume(new TreeStructureNode<SVNLogEntry>(logEntry)); + myConsumer.consume(new LogHierarchyNode(logEntry)); } } else { addToLevel(myCurrentHierarchy, logEntry, mergeLevel); @@ -62,12 +61,12 @@ public class MergeSourceHierarchyBuilder implements ThrowableConsumer<Pair<SVNLo } } - private static void addToLevel(final TreeStructureNode<SVNLogEntry> tree, final SVNLogEntry entry, final int left) { + private static void addToLevel(final LogHierarchyNode tree, final LogEntry entry, final int left) { assert tree != null; if (left == 0) { tree.add(entry); } else { - final List<TreeStructureNode<SVNLogEntry>> children = tree.getChildren(); + final List<LogHierarchyNode> children = tree.getChildren(); assert ! children.isEmpty(); addToLevel(children.get(children.size() - 1), entry, left - 1); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java index 6ac6adc3b5cd..d9b37e003961 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java @@ -125,8 +125,9 @@ public class SingleCommittedListProvider { SvnTarget target = SvnTarget.fromURL(url); myVcs.getFactory(target).createHistoryClient().doLog(target, SVNRevision.HEAD, revisionBefore, false, true, false, 0, null, - new ISVNLogEntryHandler() { - public void handleLogEntry(SVNLogEntry logEntry) { + new LogEntryConsumer() { + @Override + public void consume(LogEntry logEntry) { checkDisposed(); // date could be null for lists where there are paths that user has no rights to observe if (logEntry.getDate() != null) { @@ -144,7 +145,7 @@ public class SingleCommittedListProvider { } @NotNull - private SvnChangeList createChangeList(@NotNull SVNLogEntry logEntry) { + private SvnChangeList createChangeList(@NotNull LogEntry logEntry) { return new SvnChangeList(myVcs, svnRootLocation, logEntry, repositoryUrl.toDecodedString()); } @@ -155,8 +156,9 @@ public class SingleCommittedListProvider { } private boolean searchForUrl(@NotNull SVNURL url) throws VcsException { - ISVNLogEntryHandler handler = new ISVNLogEntryHandler() { - public void handleLogEntry(SVNLogEntry logEntry) { + LogEntryConsumer handler = new LogEntryConsumer() { + @Override + public void consume(LogEntry logEntry) { checkDisposed(); // date could be null for lists where there are paths that user has no rights to observe if (logEntry.getDate() != null) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java index f894bb3f423e..01f9a213907c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java @@ -40,10 +40,13 @@ import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.api.Depth; +import org.jetbrains.idea.svn.browse.DirectoryEntry; +import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer; import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.jetbrains.idea.svn.info.Info; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -102,7 +105,7 @@ public class SvnChangeList implements CommittedChangeList { myKnownAsDirectories = new HashSet<String>(0); } - public SvnChangeList(SvnVcs vcs, @NotNull final SvnRepositoryLocation location, final SVNLogEntry logEntry, String repositoryRoot) { + public SvnChangeList(SvnVcs vcs, @NotNull final SvnRepositoryLocation location, final LogEntry logEntry, String repositoryRoot) { myVcs = vcs; myLocation = location; myRevision = logEntry.getRevision(); @@ -114,10 +117,10 @@ public class SvnChangeList implements CommittedChangeList { myCommonPathSearcher = new CommonPathSearcher(); myKnownAsDirectories = new HashSet<String>(0); - for(SVNLogEntryPath entry : logEntry.getChangedPaths().values()) { + for(LogEntryPath entry : logEntry.getChangedPaths().values()) { final String path = entry.getPath(); - if (SVNNodeKind.DIR.equals(entry.getKind())) { + if (entry.isDirectory()) { myKnownAsDirectories.add(path); } @@ -394,8 +397,8 @@ public class SvnChangeList implements CommittedChangeList { // TODO: Logic with detecting "isDirectory" status is not clear enough. Why we can't just collect this info from logEntry and // TODO: if loading from disk - use cached values? Not to invoke separate call here. SVNRevision beforeRevision = SVNRevision.create(getRevision(idxData.second.booleanValue())); - SVNInfo info = myVcs.getInfo(SvnUtil.createUrl(revision.getFullPath()), beforeRevision, beforeRevision); - boolean isDirectory = info != null && SVNNodeKind.DIR.equals(info.getKind()); + Info info = myVcs.getInfo(SvnUtil.createUrl(revision.getFullPath()), beforeRevision, beforeRevision); + boolean isDirectory = info != null && info.isDirectory(); Change replacingChange = new Change(createRevision((SvnRepositoryContentRevision)sourceChange.getBeforeRevision(), isDirectory), createRevision((SvnRepositoryContentRevision)sourceChange.getAfterRevision(), isDirectory)); replacingChange.setIsReplaced(sourceChange.isIsReplaced()); @@ -478,12 +481,14 @@ public class SvnChangeList implements CommittedChangeList { SVNRevision revisionNumber = SVNRevision.create(getRevision(isBefore)); SvnTarget target = SvnTarget.fromURL(fullPath, revisionNumber); - myVcs.getFactory(target).createBrowseClient().list(target, revisionNumber, SVNDepth.INFINITY, new ISVNDirEntryHandler() { - public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException { - final String childPath = path + '/' + dirEntry.getRelativePath(); + myVcs.getFactory(target).createBrowseClient().list(target, revisionNumber, Depth.INFINITY, new DirectoryEntryConsumer() { + + @Override + public void consume(final DirectoryEntry entry) throws SVNException { + final String childPath = path + '/' + entry.getRelativePath(); if (!duplicates.contains(Pair.create(isBefore, childPath))) { - final ContentRevision contentRevision = createRevision(childPath, isBefore, SVNNodeKind.DIR.equals(dirEntry.getKind())); + final ContentRevision contentRevision = createRevision(childPath, isBefore, entry.isDirectory()); result.add(new Change(isBefore ? contentRevision : null, isBefore ? null : contentRevision)); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java index 556ef1e9ebbe..83642894711e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java @@ -49,12 +49,13 @@ import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.actions.ConfigureBranchesAction; +import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.jetbrains.idea.svn.status.Status; +import org.jetbrains.idea.svn.status.StatusConsumer; +import org.jetbrains.idea.svn.status.StatusType; import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.wc.ISVNStatusHandler; import org.tmatesoft.svn.core.wc.SVNRevision; -import org.tmatesoft.svn.core.wc.SVNStatus; -import org.tmatesoft.svn.core.wc.SVNStatusType; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.DataInput; @@ -139,8 +140,8 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi final String repositoryRoot = getRepositoryRoot(svnLocation); final ChangeBrowserSettings.Filter filter = settings.createFilter(); - getCommittedChangesImpl(settings, svnLocation, maxCount, new Consumer<SVNLogEntry>() { - public void consume(final SVNLogEntry svnLogEntry) { + getCommittedChangesImpl(settings, svnLocation, maxCount, new Consumer<LogEntry>() { + public void consume(final LogEntry svnLogEntry) { final SvnChangeList cl = new SvnChangeList(myVcs, svnLocation, svnLogEntry, repositoryRoot); if (filter.accepts(cl)) { consumer.consume(cl); @@ -158,8 +159,8 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi final ArrayList<SvnChangeList> result = new ArrayList<SvnChangeList>(); final String repositoryRoot = getRepositoryRoot(svnLocation); - getCommittedChangesImpl(settings, svnLocation, maxCount, new Consumer<SVNLogEntry>() { - public void consume(final SVNLogEntry svnLogEntry) { + getCommittedChangesImpl(settings, svnLocation, maxCount, new Consumer<LogEntry>() { + public void consume(final LogEntry svnLogEntry) { result.add(new SvnChangeList(myVcs, svnLocation, svnLogEntry, repositoryRoot)); } }, false, true); @@ -169,24 +170,24 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi public void getCommittedChangesWithMergedRevisons(final ChangeBrowserSettings settings, final RepositoryLocation location, final int maxCount, - final PairConsumer<SvnChangeList, TreeStructureNode<SVNLogEntry>> finalConsumer) + final PairConsumer<SvnChangeList, LogHierarchyNode> finalConsumer) throws VcsException { final SvnRepositoryLocation svnLocation = (SvnRepositoryLocation) location; final String repositoryRoot = getRepositoryRoot(svnLocation); - final MergeSourceHierarchyBuilder builder = new MergeSourceHierarchyBuilder(new Consumer<TreeStructureNode<SVNLogEntry>>() { - public void consume(TreeStructureNode<SVNLogEntry> node) { + final MergeSourceHierarchyBuilder builder = new MergeSourceHierarchyBuilder(new Consumer<LogHierarchyNode>() { + public void consume(LogHierarchyNode node) { finalConsumer.consume(new SvnChangeList(myVcs, svnLocation, node.getMe(), repositoryRoot), node); } }); - final SvnMergeSourceTracker mergeSourceTracker = new SvnMergeSourceTracker(new ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException>() { - public void consume(Pair<SVNLogEntry, Integer> svnLogEntryIntegerPair) throws SVNException { + final SvnMergeSourceTracker mergeSourceTracker = new SvnMergeSourceTracker(new ThrowableConsumer<Pair<LogEntry, Integer>, SVNException>() { + public void consume(Pair<LogEntry, Integer> svnLogEntryIntegerPair) throws SVNException { builder.consume(svnLogEntryIntegerPair); } }); - getCommittedChangesImpl(settings, svnLocation, maxCount, new Consumer<SVNLogEntry>() { - public void consume(final SVNLogEntry svnLogEntry) { + getCommittedChangesImpl(settings, svnLocation, maxCount, new Consumer<LogEntry>() { + public void consume(final LogEntry svnLogEntry) { try { mergeSourceTracker.consume(svnLogEntry); } @@ -204,13 +205,7 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi // TODO: Additionally SvnRepositoryLocation could possibly be refactored to always contain FilePath (or similar local item) // TODO: So here we could get repository url without performing remote svn command - SVNURL rootUrl; - try { - rootUrl = SvnUtil.getRepositoryRoot(myVcs, svnLocation.toSvnUrl()); - } - catch (SVNException e) { - throw new SvnBindException(e); - } + SVNURL rootUrl = SvnUtil.getRepositoryRoot(myVcs, svnLocation.toSvnUrl()); if (rootUrl == null) { throw new SvnBindException("Could not resolve repository root url for " + svnLocation); @@ -220,7 +215,7 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi } private void getCommittedChangesImpl(ChangeBrowserSettings settings, final SvnRepositoryLocation location, - final int maxCount, final Consumer<SVNLogEntry> resultConsumer, final boolean includeMergedRevisions, + final int maxCount, final Consumer<LogEntry> resultConsumer, final boolean includeMergedRevisions, final boolean filterOutByDate) throws VcsException { setCollectingChangesProgress(location); @@ -258,11 +253,12 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi } @NotNull - private ISVNLogEntryHandler createLogHandler(final Consumer<SVNLogEntry> resultConsumer, + private LogEntryConsumer createLogHandler(final Consumer<LogEntry> resultConsumer, final boolean filterOutByDate, final String author) { - return new ISVNLogEntryHandler() { - public void handleLogEntry(SVNLogEntry logEntry) { + return new LogEntryConsumer() { + @Override + public void consume(LogEntry logEntry) { if (myProject.isDisposed()) throw new ProcessCanceledException(); ProgressManager.progress2(SvnBundle.message("progress.text2.processing.revision", logEntry.getRevision())); @@ -381,31 +377,26 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi final Set<FilePath> result = ContainerUtil.newHashSet(); File rootFile = root.getIOFile(); - try { - myVcs.getFactory(rootFile).createStatusClient() - .doStatus(rootFile, SVNRevision.UNDEFINED, SVNDepth.INFINITY, true, false, false, false, new ISVNStatusHandler() { - @Override - public void handleStatus(SVNStatus status) throws SVNException { - File file = status.getFile(); - boolean changedOnServer = isNotNone(status.getRemoteContentsStatus()) || - isNotNone(status.getRemoteNodeStatus()) || - isNotNone(status.getRemotePropertiesStatus()); - - if (file != null && changedOnServer) { - result.add(VcsUtil.getFilePath(file, file.isDirectory())); - } + myVcs.getFactory(rootFile).createStatusClient() + .doStatus(rootFile, SVNRevision.UNDEFINED, Depth.INFINITY, true, false, false, false, new StatusConsumer() { + @Override + public void consume(Status status) throws SVNException { + File file = status.getFile(); + boolean changedOnServer = isNotNone(status.getRemoteContentsStatus()) || + isNotNone(status.getRemoteNodeStatus()) || + isNotNone(status.getRemotePropertiesStatus()); + + if (file != null && changedOnServer) { + result.add(VcsUtil.getFilePath(file, file.isDirectory())); } - }, null); - } - catch (SVNException e) { - throw new SvnBindException(e); - } + } + }, null); return result; } - private static boolean isNotNone(@Nullable SVNStatusType status) { - return status != null && !SVNStatusType.STATUS_NONE.equals(status); + private static boolean isNotNone(@Nullable StatusType status) { + return status != null && !StatusType.STATUS_NONE.equals(status); } public boolean refreshCacheByNumber() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCopyPathTracker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCopyPathTracker.java index 70e982aeff8e..413e05bdd781 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCopyPathTracker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCopyPathTracker.java @@ -22,8 +22,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnFileUrlMapping; import org.jetbrains.idea.svn.SvnVcs; -import org.tmatesoft.svn.core.SVNLogEntry; -import org.tmatesoft.svn.core.SVNLogEntryPath; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import java.io.File; @@ -45,12 +43,12 @@ public class SvnCopyPathTracker { myCurrentPath = relativeUrl; } - public void accept(@NotNull final SVNLogEntry entry) { + public void accept(@NotNull final LogEntry entry) { final Map changedPaths = entry.getChangedPaths(); if (changedPaths == null) return; for (Object o : changedPaths.values()) { - final SVNLogEntryPath entryPath = (SVNLogEntryPath) o; + final LogEntryPath entryPath = (LogEntryPath) o; if (entryPath != null && 'A' == entryPath.getType() && entryPath.getCopyPath() != null) { if (myCurrentPath.equals(entryPath.getPath())) { myHadChanged = true; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java index 046e16c148a4..007df92a403b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java @@ -26,12 +26,13 @@ import com.intellij.openapi.vcs.actions.VcsContextFactory; import com.intellij.openapi.vcs.history.VcsFileRevision; 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.tmatesoft.svn.core.SVNLogEntry; +import org.jetbrains.idea.svn.checkin.CommitInfo; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -47,7 +48,7 @@ public class SvnFileRevision implements VcsFileRevision { private final Date myDate; private String myCommitMessage; private final String myAuthor; - private final VcsRevisionNumber myRevisionNumber; + private final SvnRevisionNumber myRevisionNumber; private final SvnVcs myVCS; private final String myURL; private final SVNRevision myPegRevision; @@ -79,7 +80,7 @@ public class SvnFileRevision implements VcsFileRevision { public SvnFileRevision(SvnVcs vcs, SVNRevision pegRevision, - SVNLogEntry logEntry, + LogEntry logEntry, String url, String copyFromPath, Charset charset) { myCharset = charset; @@ -96,6 +97,11 @@ public class SvnFileRevision implements VcsFileRevision { myMergeSources = new ArrayList<SvnFileRevision>(); } + @NotNull + public CommitInfo getCommitInfo() { + return new CommitInfo.Builder(myRevisionNumber.getRevision().getNumber(), myDate, myAuthor).build(); + } + public String getURL() { return myURL; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java index 92b619a7465f..9e9dd7e1befc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java @@ -40,10 +40,11 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.jetbrains.idea.svn.info.Info; 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.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import org.tmatesoft.svn.util.SVNLogType; @@ -284,7 +285,7 @@ public class SvnHistoryProvider } private static class LocalLoader extends LogLoader { - private SVNInfo myInfo; + private Info myInfo; private LocalLoader(SvnVcs vcs, FilePath file, SVNRevision from, SVNRevision to, int limit, SVNRevision peg, boolean showMergeSources) { super(vcs, file, from, to, limit, peg, showMergeSources); @@ -419,7 +420,7 @@ public class SvnHistoryProvider private void loadBackwards(SVNURL svnurl) throws SVNException, VcsException { // this method is called when svnurl does not exist in latest repository revision - thus concrete old revision is used for "info" // command to get repository url - SVNInfo info = myVcs.getInfo(svnurl, myPeg, myPeg); + Info info = myVcs.getInfo(svnurl, myPeg, myPeg); final SVNURL rootURL = info != null ? info.getRepositoryRootURL() : null; final String root = rootURL != null ? rootURL.toString() : ""; String relativeUrl = myUrl; @@ -444,11 +445,11 @@ public class SvnHistoryProvider } private boolean existsNow(SVNURL svnurl) { - final SVNInfo info; + final Info info; try { info = myVcs.getInfo(svnurl, SVNRevision.HEAD, SVNRevision.HEAD); } - catch (SVNException e) { + catch (SvnBindException e) { return false; } return info != null && info.getURL() != null && info.getRevision().isValid(); @@ -470,7 +471,7 @@ public class SvnHistoryProvider return false; } - private static class MyLogEntryHandler implements ISVNLogEntryHandler { + private static class MyLogEntryHandler implements LogEntryConsumer { private final ProgressIndicator myIndicator; protected final SvnVcs myVcs; protected final SvnPathThroughHistoryCorrection myLastPathCorrector; @@ -503,10 +504,10 @@ public class SvnHistoryProvider myPegRevision = pegRevision; myUrl = url; myRepositoryRoot = repoRootURL; - myTracker = new SvnMergeSourceTracker(new ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException>() { + myTracker = new SvnMergeSourceTracker(new ThrowableConsumer<Pair<LogEntry, Integer>, SVNException>() { @Override - public void consume(final Pair<SVNLogEntry, Integer> svnLogEntryIntegerPair) throws SVNException { - final SVNLogEntry logEntry = svnLogEntryIntegerPair.getFirst(); + public void consume(final Pair<LogEntry, Integer> svnLogEntryIntegerPair) throws SVNException { + final LogEntry logEntry = svnLogEntryIntegerPair.getFirst(); if (myIndicator != null) { if (myIndicator.isCanceled()) { @@ -514,12 +515,12 @@ public class SvnHistoryProvider } myIndicator.setText2(SvnBundle.message("progress.text2.revision.processed", logEntry.getRevision())); } - SVNLogEntryPath entryPath = null; + LogEntryPath entryPath = null; String copyPath = null; final int mergeLevel = svnLogEntryIntegerPair.getSecond(); if (! myLastPathCorrector.isRoot()) { - myLastPathCorrector.handleLogEntry(logEntry); + myLastPathCorrector.consume(logEntry); entryPath = myLastPathCorrector.getDirectlyMentioned(); copyPath = null; if (entryPath != null) { @@ -528,7 +529,7 @@ public class SvnHistoryProvider // if there are no path with exact match, check whether parent or child paths had changed // "entry path" is allowed to be null now; if it is null, last path would be taken for revision construction - // Separate SVNLogEntry is issued for each "merge source" revision. These "merge source" revisions are treated as child + // Separate LogEntry is issued for each "merge source" revision. These "merge source" revisions are treated as child // revisions of some other revision - this way we construct merge hierarchy. // mergeLevel >= 0 indicates that we are currently processing some "merge source" revision. This "merge source" revision // contains changes from some other branch - so checkForChildChanges() and checkForParentChanges() return "false". @@ -556,11 +557,11 @@ public class SvnHistoryProvider }); } - private boolean checkForParentChanges(SVNLogEntry logEntry) { + private boolean checkForParentChanges(LogEntry logEntry) { final String lastPathBefore = myLastPathCorrector.getBefore(); String path = SVNPathUtil.removeTail(lastPathBefore); while (path.length() > 0) { - final SVNLogEntryPath entryPath = logEntry.getChangedPaths().get(path); + final LogEntryPath entryPath = logEntry.getChangedPaths().get(path); // A & D are checked since we are not interested in parent folders property changes, only in structure changes // TODO: seems that R (replaced) should also be checked here if (entryPath != null && (entryPath.getType() == 'A' || entryPath.getType() == 'D')) { @@ -576,7 +577,7 @@ public class SvnHistoryProvider // TODO: this makes sense only for directories, but should always return true if something under the directory was changed in revision // TODO: as svn will provide child changes in history for directory - private boolean checkForChildChanges(SVNLogEntry logEntry) { + private boolean checkForChildChanges(LogEntry logEntry) { final String lastPathBefore = myLastPathCorrector.getBefore(); for (String key : logEntry.getChangedPaths().keySet()) { if (SVNPathUtil.isAncestor(lastPathBefore, key)) { @@ -587,7 +588,7 @@ public class SvnHistoryProvider } @Override - public void handleLogEntry(SVNLogEntry logEntry) throws SVNException { + public void consume(LogEntry logEntry) throws SVNException { myTracker.consume(logEntry); } @@ -605,7 +606,7 @@ public class SvnHistoryProvider } } - protected SvnFileRevision createRevision(final SVNLogEntry logEntry, final String copyPath, SVNLogEntryPath entryPath) throws SVNException { + protected SvnFileRevision createRevision(final LogEntry logEntry, final String copyPath, LogEntryPath entryPath) throws SVNException { Date date = logEntry.getDate(); String author = logEntry.getAuthor(); String message = logEntry.getMessage(); @@ -628,7 +629,7 @@ public class SvnHistoryProvider } @Override - protected SvnFileRevision createRevision(final SVNLogEntry logEntry, final String copyPath, SVNLogEntryPath entryPath) + protected SvnFileRevision createRevision(final LogEntry logEntry, final String copyPath, LogEntryPath entryPath) throws SVNException { final SVNURL url = entryPath == null ? myRepositoryRoot.appendPath(myLastPathCorrector.getBefore(), false) : myRepositoryRoot.appendPath(entryPath.getPath(), true); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java index 171b39cad623..f2f91bceec14 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java @@ -20,7 +20,7 @@ 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.wc.SVNInfo; +import org.jetbrains.idea.svn.info.Info; import org.tmatesoft.svn.core.wc.SVNRevision; import java.io.File; @@ -69,7 +69,7 @@ public class SvnHistorySession extends VcsAbstractHistorySession { } public static VcsRevisionNumber getCurrentCommittedRevision(final SvnVcs vcs, final File file) { - SVNInfo info = vcs.getInfo(file); + Info info = vcs.getInfo(file); return info != null ? new SvnRevisionNumber(info.getCommittedRevision()) : null; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java index ca387bc9ca41..0aca8300e420 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java @@ -8,6 +8,7 @@ import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.tmatesoft.svn.core.ISVNLogEntryHandler; import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.wc.SVNLogClient; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -28,22 +29,38 @@ public class SvnKitHistoryClient extends BaseSvnClient implements HistoryClient boolean includeMergedRevisions, long limit, @Nullable String[] revisionProperties, - @Nullable ISVNLogEntryHandler handler) throws VcsException { + @Nullable LogEntryConsumer handler) throws VcsException { try { // TODO: a bug noticed when testing: we should pass "limit + 1" to get "limit" rows SVNLogClient client = myVcs.getSvnKitManager().createLogClient(); if (target.isFile()) { client.doLog(new File[]{target.getFile()}, startRevision, endRevision, target.getPegRevision(), stopOnCopy, discoverChangedPaths, - includeMergedRevisions, limit, revisionProperties, handler); + includeMergedRevisions, limit, revisionProperties, toHandler(handler)); } else { client.doLog(target.getURL(), ArrayUtil.EMPTY_STRING_ARRAY, target.getPegRevision(), startRevision, endRevision, stopOnCopy, - discoverChangedPaths, includeMergedRevisions, limit, revisionProperties, handler); + discoverChangedPaths, includeMergedRevisions, limit, revisionProperties, toHandler(handler)); } } catch (SVNException e) { throw new SvnBindException(e); } } + + @Nullable + private static ISVNLogEntryHandler toHandler(@Nullable final LogEntryConsumer handler) { + ISVNLogEntryHandler result = null; + + if (handler != null) { + result = new ISVNLogEntryHandler() { + @Override + public void handleLogEntry(SVNLogEntry logEntry) throws SVNException { + handler.consume(LogEntry.create(logEntry)); + } + }; + } + + return result; + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogUtil.java index 7f4f25f023a9..878f38e6a748 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogUtil.java @@ -24,8 +24,6 @@ import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnVcs; -import org.tmatesoft.svn.core.ISVNLogEntryHandler; -import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -50,7 +48,7 @@ public class SvnLogUtil implements SvnLogLoader { final int maxCount, final boolean includingYoungest, final boolean includeOldest) throws VcsException { final List<CommittedChangeList> result = new ArrayList<CommittedChangeList>(); - ISVNLogEntryHandler handler = createLogHandler(fromIncluding, toIncluding, includingYoungest, includeOldest, result); + LogEntryConsumer handler = createLogHandler(fromIncluding, toIncluding, includingYoungest, includeOldest, result); SvnTarget target = SvnTarget.fromURL(myLocation.toSvnUrl()); myVcs.getFactory(target).createHistoryClient().doLog(target, fromIncluding, toIncluding, true, true, false, maxCount, null, handler); @@ -59,12 +57,13 @@ public class SvnLogUtil implements SvnLogLoader { } @NotNull - private ISVNLogEntryHandler createLogHandler(final SVNRevision fromIncluding, + private LogEntryConsumer createLogHandler(final SVNRevision fromIncluding, final SVNRevision toIncluding, final boolean includingYoungest, final boolean includeOldest, final List<CommittedChangeList> result) { - return new ISVNLogEntryHandler() { - public void handleLogEntry(SVNLogEntry logEntry) { + return new LogEntryConsumer() { + @Override + public void consume(LogEntry logEntry) { if (myProject.isDisposed()) throw new ProcessCanceledException(); final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); if (progress != null) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeSourceDetails.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeSourceDetails.java index f3ed60277dd5..be0722b6fc0c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeSourceDetails.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeSourceDetails.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.MasterDetailsComponent; import com.intellij.openapi.ui.NamedConfigurable; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.changes.committed.CommittedChangeListRenderer; import com.intellij.openapi.vcs.changes.ui.ChangeListViewerDialog; @@ -73,6 +74,8 @@ public class SvnMergeSourceDetails extends MasterDetailsComponent { final ContentManager contentManager = toolWindow.getContentManager(); final MyDialog dialog = new MyDialog(project, revision, file); + // TODO: Temporary memory leak fix - rewrite this part not to create dialog if only createCenterPanel(), but not show() is invoked + Disposer.register(project, dialog.getDisposable()); Content content = ContentFactory.SERVICE.getInstance().createContent(dialog.createCenterPanel(), SvnBundle.message("merge.source.details.title", (file == null) ? revision.getURL() : file.getName(), revision.getRevisionNumber().asString()), true); @@ -213,7 +216,10 @@ public class SvnMergeSourceDetails extends MasterDetailsComponent { if (list == null) { myPanel = new JPanel(); } else { - myPanel = new ChangeListViewerDialog(myProject, list).createCenterPanel(); + ChangeListViewerDialog dialog = new ChangeListViewerDialog(myProject, list); + // TODO: Temporary memory leak fix - rewrite this part not to create dialog if only createCenterPanel(), but not show() is invoked + Disposer.register(myProject, dialog.getDisposable()); + myPanel = dialog.createCenterPanel(); } } return myPanel; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeSourceTracker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeSourceTracker.java index 53f151876ec9..023d8489d795 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeSourceTracker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeSourceTracker.java @@ -18,24 +18,23 @@ package org.jetbrains.idea.svn.history; import com.intellij.openapi.util.Pair; import com.intellij.util.ThrowableConsumer; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNLogEntry; public class SvnMergeSourceTracker { private int myMergeLevel; // -1 - not merge source; 0 - direct merge source - private ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException> myConsumer; + private ThrowableConsumer<Pair<LogEntry, Integer>, SVNException> myConsumer; - public SvnMergeSourceTracker(final ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException> consumer) { + public SvnMergeSourceTracker(final ThrowableConsumer<Pair<LogEntry, Integer>, SVNException> consumer) { myConsumer = consumer; myMergeLevel = -1; } - public void consume(final SVNLogEntry logEntry) throws SVNException { + public void consume(final LogEntry logEntry) throws SVNException { if (logEntry.getRevision() < 0) { -- myMergeLevel; return; } - myConsumer.consume(new Pair<SVNLogEntry, Integer>(logEntry, myMergeLevel)); + myConsumer.consume(new Pair<LogEntry, Integer>(logEntry, myMergeLevel)); if (logEntry.hasChildren()) { ++ myMergeLevel; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnPathThroughHistoryCorrection.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnPathThroughHistoryCorrection.java index 8ecb8a3b1e90..bf6c08e74759 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnPathThroughHistoryCorrection.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnPathThroughHistoryCorrection.java @@ -17,10 +17,7 @@ package org.jetbrains.idea.svn.history; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.idea.svn.SvnUtil; -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.internal.util.SVNPathUtil; import java.util.Map; @@ -33,10 +30,10 @@ import java.util.Map; * * We consider here, that history is traversed "from now to past" */ -public class SvnPathThroughHistoryCorrection implements ISVNLogEntryHandler { +public class SvnPathThroughHistoryCorrection implements LogEntryConsumer { private String myBefore; private String myPath; - private SVNLogEntryPath myDirectlyMentioned; + private LogEntryPath myDirectlyMentioned; private boolean myRoot; public SvnPathThroughHistoryCorrection(String path) { @@ -46,14 +43,14 @@ public class SvnPathThroughHistoryCorrection implements ISVNLogEntryHandler { } @Override - public void handleLogEntry(SVNLogEntry logEntry) throws SVNException { + public void consume(LogEntry logEntry) throws SVNException { if (myRoot) { return; } myBefore = myPath; myDirectlyMentioned = null; - final Map<String,SVNLogEntryPath> paths = logEntry.getChangedPaths(); - final SVNLogEntryPath entryPath = paths.get(myPath); + final Map<String,LogEntryPath> paths = logEntry.getChangedPaths(); + final LogEntryPath entryPath = paths.get(myPath); if (entryPath != null) { myDirectlyMentioned = entryPath; // exact match @@ -62,7 +59,7 @@ public class SvnPathThroughHistoryCorrection implements ISVNLogEntryHandler { return; } } - for (SVNLogEntryPath path : paths.values()) { + for (LogEntryPath path : paths.values()) { // "the origin path *from where* the item, ..." // TODO: this could incorrectly handle case when parent folder was replaced - see IDEA-103042 // TODO: or several parent folder renames occur IDEA-96825 @@ -89,7 +86,7 @@ public class SvnPathThroughHistoryCorrection implements ISVNLogEntryHandler { return myBefore; } - public SVNLogEntryPath getDirectlyMentioned() { + public LogEntryPath getDirectlyMentioned() { return myDirectlyMentioned; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionsNavigationMediator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionsNavigationMediator.java index 7a11aee32c48..ca69ba7a58ec 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionsNavigationMediator.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionsNavigationMediator.java @@ -28,8 +28,8 @@ import com.intellij.openapi.vcs.changes.committed.CommittedChangesNavigation; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.idea.svn.SvnVcs; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.wc.SVNInfo; +import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.jetbrains.idea.svn.info.Info; import org.tmatesoft.svn.core.wc.SVNRevision; import java.util.*; @@ -56,7 +56,7 @@ public class SvnRevisionsNavigationMediator implements CommittedChangesNavigatio myChunks = new LinkedList<List<Fragment>>(); final VcsException[] exception = new VcsException[1]; - final Ref<SVNInfo> infoRef = new Ref<SVNInfo>(); + final Ref<Info> infoRef = new Ref<Info>(); Runnable process = new Runnable() { @Override @@ -64,17 +64,14 @@ public class SvnRevisionsNavigationMediator implements CommittedChangesNavigatio try { infoRef.set(vcs.getInfo(location.toSvnUrl(), SVNRevision.HEAD)); } - catch (VcsException e) { + catch (SvnBindException e) { exception[0] = e; } - catch (SVNException e) { - exception[0] = new VcsException(e); - } } }; underProgress(exception, process); - SVNInfo info = infoRef.get(); + Info info = infoRef.get(); if (info == null || info.getRevision() == null || info.getRepositoryRootURL() == null) { throw new VcsException("Could not get head info for " + location); } |