diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java index 5380bac9ccae..b7147758667a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java @@ -33,6 +33,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.history.CopyData; import org.jetbrains.idea.svn.history.FirstInBranch; +import org.jetbrains.idea.svn.history.FirstInBranchAccurate; import java.io.DataInput; import java.io.DataOutput; @@ -248,7 +249,7 @@ public class SvnBranchPointsCalculator { public WrapperInvertor convert(final KeyData keyData) { final Ref> result = new Ref>(); - new FirstInBranch(myVcs, keyData.getRepoUrl(), keyData.getTargetUrl(), keyData.getSourceUrl(), new Consumer() { + final Consumer consumer = new Consumer() { public void consume(CopyData copyData) { if (copyData != null) { final boolean correct = copyData.isTrunkSupposedCorrect(); @@ -256,19 +257,29 @@ public class SvnBranchPointsCalculator { if (correct) { branchCopyData = new BranchCopyData(keyData.getSourceUrl(), copyData.getCopySourceRevision(), keyData.getTargetUrl(), copyData.getCopyTargetRevision()); - } else { + } + else { branchCopyData = new BranchCopyData(keyData.getTargetUrl(), copyData.getCopySourceRevision(), keyData.getSourceUrl(), copyData.getCopyTargetRevision()); } - result.set(new WrapperInvertor(! correct, branchCopyData)); + result.set(new WrapperInvertor(!correct, branchCopyData)); } } - }).run(); + }; + + new FirstInBranch(myVcs, keyData.getRepoUrl(), keyData.getTargetUrl(), keyData.getSourceUrl(), consumer).run(); - final WrapperInvertor invertor = result.get(); + WrapperInvertor invertor = result.get(); if (LOG.isDebugEnabled()) { LOG.debug("Loader returned: for key: " + keyData.toString() + " result: " + (invertor == null ? null : invertor.toString())); } + if (invertor == null) { + new FirstInBranchAccurate(myVcs, keyData.getRepoUrl(), keyData.getTargetUrl(), keyData.getSourceUrl(), consumer).run(); + invertor = result.get(); + if (LOG.isDebugEnabled()) { + LOG.debug("Accurate Loader returned: for key: " + keyData.toString() + " result: " + (invertor == null ? null : invertor.toString())); + } + } return invertor; } } 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 97df183ba6f1..cea878769e11 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java @@ -15,73 +15,32 @@ */ package org.jetbrains.idea.svn.history; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Ref; -import com.intellij.openapi.vcs.ConcurrentTasks; import com.intellij.util.Consumer; import org.jetbrains.idea.svn.SvnVcs; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.internal.util.SVNPathUtil; +import org.tmatesoft.svn.core.ISVNLogEntryHandler; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNLogEntry; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNLogClient; import org.tmatesoft.svn.core.wc.SVNRevision; -import java.util.Map; - -public class FirstInBranch implements Runnable { - private final static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.history.FirstInBranch"); - private final SvnVcs myVcs; - private final String myFullBranchUrl; - private final String myFullTrunkUrl; - private final String myBranchUrl; - private final String myTrunkUrl; - private final Consumer myConsumer; - - public FirstInBranch(final SvnVcs vcs, final String repositoryRoot, final String branchUrl, final String trunkUrl, final Consumer consumer) { - if (LOG.isDebugEnabled()) { - LOG.debug("FirstInBranch created with: repoRoot: " + repositoryRoot + " branchUrl: " + branchUrl + - " trunkUrl: " + trunkUrl); - } - myVcs = vcs; - myConsumer = consumer; - - myFullBranchUrl = branchUrl; - myFullTrunkUrl = trunkUrl; - myBranchUrl = relativePath(repositoryRoot, branchUrl); - myTrunkUrl = relativePath(repositoryRoot, trunkUrl); +public class FirstInBranch extends FirstInBranchAbstractBase { + public FirstInBranch(SvnVcs vcs, + String repositoryRoot, + String branchUrl, + String trunkUrl, + Consumer consumer) { + super(vcs, repositoryRoot, branchUrl, trunkUrl, consumer); } - private String relativePath(final String parent, final String child) { - String path = SVNPathUtil.getRelativePath(parent, child); - return path.startsWith("/") ? path : "/" + path; - } - - public void run() { - final SVNURL branchURL; - final SVNURL trunkURL; - try { - branchURL = SVNURL.parseURIEncoded(myFullBranchUrl); - trunkURL = SVNURL.parseURIEncoded(myFullTrunkUrl); - } - catch (SVNException e) { - LOG.info(e); - myConsumer.consume(null); - return; - } - - final ConcurrentTasks tasks = - new ConcurrentTasks(ProgressManager.getInstance().getProgressIndicator(), createTask(branchURL), createTask(trunkURL)); - tasks.compute(); - if (tasks.isResultKnown()) { - myConsumer.consume(tasks.getResult()); - } else { - myConsumer.consume(null); - } - } - - private Consumer> createTask(final SVNURL branchURL) { + protected Consumer> createTask(final SVNURL branchURL) { return new Consumer>() { public void consume(final Consumer copyDataConsumer) { + if (LOG.isDebugEnabled()) { + LOG.debug("FirstInBranch started for: " + branchURL.toString()); + } final SVNLogClient logClient = myVcs.createLogClient(); final long start1 = getStart(logClient, branchURL); if (start1 > 0) { @@ -96,11 +55,17 @@ public class FirstInBranch implements Runnable { LOG.info(e); } } + if (LOG.isDebugEnabled()) { + LOG.debug("FirstInBranch finished for: " + branchURL.toString()); + } } }; } private static long getStart(final SVNLogClient logClient, final SVNURL url) { + if (LOG.isDebugEnabled()) { + LOG.debug("getting start revision for: " + url); + } final Ref myRevisionCandidate = new Ref(0L); try { logClient.doLog(url, null, SVNRevision.UNDEFINED, SVNRevision.HEAD, SVNRevision.create(0), @@ -109,36 +74,18 @@ public class FirstInBranch implements Runnable { ProgressManager.checkCanceled(); myRevisionCandidate.set(logEntry.getRevision()); + if (LOG.isDebugEnabled()) { + LOG.debug("setting in cycle start revision for: " + url + " as: " + myRevisionCandidate.get()); + } } }); } catch (SVNException e) { LOG.info(e); } + if (LOG.isDebugEnabled()) { + LOG.debug("start revision for: " + url + " is: " + myRevisionCandidate.get()); + } return myRevisionCandidate.get(); } - - private void checkForCopy(final SVNLogEntry logEntry, final Consumer result) { - final Map map = logEntry.getChangedPaths(); - for (Object o : map.values()) { - final SVNLogEntryPath path = (SVNLogEntryPath) o; - final String localPath = path.getPath(); - final String copyPath = path.getCopyPath(); - if (LOG.isDebugEnabled()) { - LOG.debug("localPath: " + localPath + " copy path: " + copyPath); - } - - if ('A' == path.getType()) { - if ((myBranchUrl.equals(localPath) || SVNPathUtil.isAncestor(localPath, myBranchUrl)) && - ((myTrunkUrl.equals(copyPath)) || SVNPathUtil.isAncestor(copyPath, myTrunkUrl))) { - result.consume(new CopyData(path.getCopyRevision(), logEntry.getRevision(), true)); - } else { - if ((myBranchUrl.equals(copyPath) || SVNPathUtil.isAncestor(copyPath, myBranchUrl)) && - ((myTrunkUrl.equals(localPath)) || SVNPathUtil.isAncestor(localPath, myTrunkUrl))) { - result.consume(new CopyData(path.getCopyRevision(), logEntry.getRevision(), false)); - } - } - } - } - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranchAbstractBase.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranchAbstractBase.java new file mode 100644 index 000000000000..1626bd2078bd --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranchAbstractBase.java @@ -0,0 +1,114 @@ +/* + * Copyright 2000-2011 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.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.vcs.ConcurrentTasks; +import com.intellij.util.Consumer; +import org.jetbrains.idea.svn.SvnVcs; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNLogEntry; +import org.tmatesoft.svn.core.SVNLogEntryPath; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; + +import java.util.Map; + +/** + * Created by IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 11/15/11 + * Time: 1:30 PM + */ +public abstract class FirstInBranchAbstractBase implements Runnable { + protected final static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.history.FirstInBranch"); + protected final SvnVcs myVcs; + protected final String myFullBranchUrl; + protected final String myFullTrunkUrl; + protected final String myBranchUrl; + protected final String myTrunkUrl; + protected final Consumer myConsumer; + + public FirstInBranchAbstractBase(final SvnVcs vcs, final String repositoryRoot, final String branchUrl, final String trunkUrl, + final Consumer consumer) { + if (LOG.isDebugEnabled()) { + LOG.debug("FirstInBranchAbstractBase created with: repoRoot: " + repositoryRoot + " branchUrl: " + branchUrl + + " trunkUrl: " + trunkUrl); + } + myVcs = vcs; + myConsumer = consumer; + + myFullBranchUrl = branchUrl; + myFullTrunkUrl = trunkUrl; + myBranchUrl = relativePath(repositoryRoot, branchUrl); + myTrunkUrl = relativePath(repositoryRoot, trunkUrl); + } + + private String relativePath(final String parent, final String child) { + String path = SVNPathUtil.getRelativePath(parent, child); + return path.startsWith("/") ? path : "/" + path; + } + + public void run() { + final SVNURL branchURL; + final SVNURL trunkURL; + try { + branchURL = SVNURL.parseURIEncoded(myFullBranchUrl); + trunkURL = SVNURL.parseURIEncoded(myFullTrunkUrl); + } + catch (SVNException e) { + LOG.info(e); + myConsumer.consume(null); + return; + } + + final ConcurrentTasks tasks = + new ConcurrentTasks(ProgressManager.getInstance().getProgressIndicator(), createTask(branchURL), createTask(trunkURL)); + tasks.compute(); + if (tasks.isResultKnown()) { + myConsumer.consume(tasks.getResult()); + } else { + myConsumer.consume(null); + } + } + + protected abstract Consumer> createTask(final SVNURL branchURL); + + protected void checkForCopy(final SVNLogEntry logEntry, final Consumer result) { + final Map map = logEntry.getChangedPaths(); + for (Object o : map.values()) { + final SVNLogEntryPath path = (SVNLogEntryPath) o; + final String localPath = path.getPath(); + final String copyPath = path.getCopyPath(); + if (LOG.isDebugEnabled()) { + LOG.debug("localPath: " + localPath + " copy path: " + copyPath + " revision: " + logEntry.getRevision()); + } + + if ('A' == path.getType()) { + if ((myBranchUrl.equals(localPath) || SVNPathUtil.isAncestor(localPath, myBranchUrl)) && + ((myTrunkUrl.equals(copyPath)) || SVNPathUtil.isAncestor(copyPath, myTrunkUrl))) { + result.consume(new CopyData(path.getCopyRevision(), logEntry.getRevision(), true)); + } else { + if ((myBranchUrl.equals(copyPath) || SVNPathUtil.isAncestor(copyPath, myBranchUrl)) && + ((myTrunkUrl.equals(localPath)) || SVNPathUtil.isAncestor(localPath, myTrunkUrl))) { + result.consume(new CopyData(path.getCopyRevision(), logEntry.getRevision(), false)); + } + } + } + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranchAccurate.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranchAccurate.java new file mode 100644 index 000000000000..a733183a487b --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranchAccurate.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2011 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.Consumer; +import org.jetbrains.idea.svn.SvnVcs; +import org.tmatesoft.svn.core.ISVNLogEntryHandler; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNLogEntry; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.wc.SVNLogClient; +import org.tmatesoft.svn.core.wc.SVNRevision; + +/** + * Created by IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 11/15/11 + * Time: 1:23 PM + */ +public class FirstInBranchAccurate extends FirstInBranchAbstractBase { + public FirstInBranchAccurate(SvnVcs vcs, + String repositoryRoot, + String branchUrl, + String trunkUrl, + Consumer consumer) { + super(vcs, repositoryRoot, branchUrl, trunkUrl, consumer); + } + + @Override + protected Consumer> createTask(final SVNURL branchURL) { + return new Consumer>() { + public void consume(final Consumer copyDataConsumer) { + if (LOG.isDebugEnabled()) { + LOG.debug("FirstInBranchAccurate started for: " + branchURL.toString()); + } + final SVNLogClient logClient = myVcs.createLogClient(); + try { + logClient.doLog(branchURL, null, SVNRevision.UNDEFINED, SVNRevision.HEAD, SVNRevision.create(0), true, true, 1, new ISVNLogEntryHandler() { + public void handleLogEntry(SVNLogEntry logEntry) throws SVNException { + checkForCopy(logEntry, copyDataConsumer); + } + }); + } catch (SVNException e) { + LOG.info(e); + } + if (LOG.isDebugEnabled()) { + LOG.debug("FirstInBranchAccurate finished for: " + branchURL.toString()); + } + } + }; + } +}