mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
SVN: rework of history loading for tree conflicts details
This commit is contained in:
@@ -44,8 +44,6 @@ import org.jetbrains.idea.svn.SvnVcs;
|
||||
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.io.SVNRepositoryFactory;
|
||||
import org.tmatesoft.svn.core.wc.*;
|
||||
import org.tmatesoft.svn.util.SVNLogType;
|
||||
|
||||
@@ -301,7 +299,7 @@ public class SvnHistoryProvider
|
||||
.doLog(new File[]{new File(myFile.getIOFile().getAbsolutePath())},
|
||||
myFrom == null ? SVNRevision.HEAD : myFrom, myTo == null ? SVNRevision.create(1) : myTo, myPeg,
|
||||
false, true, mySupport15, myLimit, null,
|
||||
new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl, myConsumer, repoRootURL, myFile.getCharset()));
|
||||
new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl, createConsumerAdapter(myConsumer), repoRootURL, myFile.getCharset()));
|
||||
}
|
||||
catch (SVNCancelException e) {
|
||||
//
|
||||
@@ -315,6 +313,15 @@ public class SvnHistoryProvider
|
||||
}
|
||||
}
|
||||
|
||||
private static ThrowableConsumer<VcsFileRevision, SVNException> createConsumerAdapter(final Consumer<VcsFileRevision> consumer) {
|
||||
return new ThrowableConsumer<VcsFileRevision, SVNException>() {
|
||||
@Override
|
||||
public void consume(VcsFileRevision revision) throws SVNException {
|
||||
consumer.consume(revision);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class RepositoryLoader extends LogLoader {
|
||||
private final boolean myForceBackwards;
|
||||
|
||||
@@ -339,13 +346,17 @@ public class SvnHistoryProvider
|
||||
if (myPI != null) {
|
||||
myPI.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", myUrl));
|
||||
}
|
||||
if (myForceBackwards) {
|
||||
loadBackwards();
|
||||
return;
|
||||
}
|
||||
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
try {
|
||||
if (myForceBackwards) {
|
||||
SVNURL svnurl = SVNURL.parseURIEncoded(myUrl);
|
||||
if (! existsNow(svnurl)) {
|
||||
loadBackwards(svnurl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SVNWCClient wcClient = myVcs.createWCClient();
|
||||
final SVNURL svnurl = SVNURL.parseURIEncoded(myUrl);
|
||||
SVNInfo info = null;
|
||||
SVNRevision operationalFrom = myFrom == null ? SVNRevision.HEAD : myFrom;
|
||||
@@ -356,9 +367,9 @@ public class SvnHistoryProvider
|
||||
relativeUrl = myUrl.substring(root.length());
|
||||
}
|
||||
SVNLogClient client = myVcs.createLogClient();
|
||||
client.doLog(svnurl, new String[]{}, myPeg,
|
||||
client.doLog(svnurl, new String[]{}, myPeg == null ? myFrom : myPeg,
|
||||
operationalFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, mySupport15, myLimit, null,
|
||||
new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl, myConsumer,
|
||||
new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl, createConsumerAdapter(myConsumer),
|
||||
info.getRepositoryRootURL()));
|
||||
}
|
||||
catch (SVNCancelException e) {
|
||||
@@ -372,11 +383,8 @@ public class SvnHistoryProvider
|
||||
}
|
||||
}
|
||||
|
||||
private void loadBackwards() {
|
||||
try {
|
||||
final SVNURL svnurl = SVNURL.parseURIEncoded(myUrl);
|
||||
SVNRevision operationalFrom = myFrom == null ? SVNRevision.HEAD : myFrom;
|
||||
final SVNURL rootURL = getRepositoryRoot(svnurl, operationalFrom);
|
||||
private void loadBackwards(SVNURL svnurl) throws SVNException, VcsException {
|
||||
final SVNURL rootURL = getRepositoryRoot(svnurl, myFrom);
|
||||
final String root = rootURL.toString();
|
||||
String relativeUrl = myUrl;
|
||||
if (myUrl.startsWith(root)) {
|
||||
@@ -386,35 +394,50 @@ public class SvnHistoryProvider
|
||||
SVNLogClient client = myVcs.createLogClient();
|
||||
|
||||
final RepositoryLogEntryHandler repositoryLogEntryHandler =
|
||||
new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl, myConsumer, rootURL);
|
||||
new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl,
|
||||
new ThrowableConsumer<VcsFileRevision, SVNException>() {
|
||||
@Override
|
||||
public void consume(VcsFileRevision revision) throws SVNException {
|
||||
myConsumer.consume(revision);
|
||||
throw new SVNCancelException(); // load only one revision
|
||||
}
|
||||
}, rootURL);
|
||||
repositoryLogEntryHandler.setThrowCancelOnMeetPathCreation(true);
|
||||
|
||||
SVNRevision current = operationalFrom;
|
||||
client.doLog(rootURL, new String[]{}, current, myTo, current, false, true, mySupport15, myLimit, null, repositoryLogEntryHandler);
|
||||
}
|
||||
catch (SVNCancelException e) {
|
||||
//
|
||||
}
|
||||
catch (SVNException e) {
|
||||
myException = new VcsException(e);
|
||||
}
|
||||
catch (VcsException e) {
|
||||
myException = e;
|
||||
}
|
||||
client.doLog(rootURL, new String[]{}, myFrom, myFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, mySupport15, 0, null, repositoryLogEntryHandler);
|
||||
}
|
||||
|
||||
private SVNURL getRepositoryRoot(SVNURL svnurl, SVNRevision operationalFrom) throws SVNException {
|
||||
final SVNWCClient wcClient = myVcs.createWCClient();
|
||||
return myVcs.createRepository(svnurl).getRepositoryRoot(false);
|
||||
/*final SVNWCClient wcClient = myVcs.createWCClient();
|
||||
try {
|
||||
final SVNInfo info;
|
||||
info = wcClient.doInfo(svnurl, myPeg, operationalFrom);
|
||||
return info.getRepositoryRootURL();
|
||||
}
|
||||
catch (SVNException e) {
|
||||
final SVNInfo info;
|
||||
info = wcClient.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.UNDEFINED);
|
||||
return info.getRepositoryRootURL();
|
||||
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();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private boolean existsNow(SVNURL svnurl) {
|
||||
final SVNWCClient wcClient = myVcs.createWCClient();
|
||||
final SVNInfo info;
|
||||
try {
|
||||
info = wcClient.doInfo(svnurl, SVNRevision.HEAD, SVNRevision.HEAD);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
return false;
|
||||
}
|
||||
return info != null && info.getURL() != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,9 +456,9 @@ public class SvnHistoryProvider
|
||||
private static class MyLogEntryHandler implements ISVNLogEntryHandler {
|
||||
private final ProgressIndicator myIndicator;
|
||||
protected final SvnVcs myVcs;
|
||||
private String myLastPath;
|
||||
protected String myLastPath;
|
||||
private final Charset myCharset;
|
||||
protected final Consumer<VcsFileRevision> myResult;
|
||||
protected final ThrowableConsumer<VcsFileRevision, SVNException> myResult;
|
||||
private VcsFileRevision myPrevious;
|
||||
private final SVNRevision myPegRevision;
|
||||
protected final String myUrl;
|
||||
@@ -450,7 +473,7 @@ public class SvnHistoryProvider
|
||||
public MyLogEntryHandler(SvnVcs vcs, final String url,
|
||||
final SVNRevision pegRevision,
|
||||
String lastPath,
|
||||
final Consumer<VcsFileRevision> result,
|
||||
final ThrowableConsumer<VcsFileRevision, SVNException> result,
|
||||
SVNURL repoRootURL, Charset charset)
|
||||
throws SVNException, VcsException {
|
||||
myVcs = vcs;
|
||||
@@ -480,15 +503,20 @@ public class SvnHistoryProvider
|
||||
String path = SVNPathUtil.removeTail(myLastPath);
|
||||
while (path.length() > 0) {
|
||||
entryPath = (SVNLogEntryPath)logEntry.getChangedPaths().get(path);
|
||||
if (entryPath != null) {
|
||||
if (entryPath != null && (entryPath.getType() == 'A' || entryPath.getType() == 'D')) {
|
||||
String relativePath = myLastPath.substring(entryPath.getPath().length());
|
||||
copyPath = entryPath.getCopyPath() + relativePath;
|
||||
if (entryPath.getCopyPath() != null) {
|
||||
copyPath = entryPath.getCopyPath() + relativePath;
|
||||
}
|
||||
break;
|
||||
}
|
||||
path = SVNPathUtil.removeTail(path);
|
||||
}
|
||||
}
|
||||
if (entryPath == null) return; // skip this revision: no our path in it
|
||||
if (entryPath == null) {
|
||||
if (! checkForChildChanges(logEntry)) return;
|
||||
}
|
||||
//if (entryPath == null) return; // skip this revision: no our path in it
|
||||
|
||||
final int mergeLevel = svnLogEntryIntegerPair.getSecond();
|
||||
final SvnFileRevision revision = createRevision(logEntry, copyPath, entryPath);
|
||||
@@ -504,7 +532,7 @@ public class SvnHistoryProvider
|
||||
myResult.consume(revision);
|
||||
myPrevious = revision;
|
||||
}
|
||||
if (myThrowCancelOnMeetPathCreation && myUrl.equals(revision.getURL()) && entryPath.getType() == 'A') {
|
||||
if (myThrowCancelOnMeetPathCreation && myUrl.equals(revision.getURL()) && entryPath != null && entryPath.getType() == 'A') {
|
||||
throw new SVNCancelException();
|
||||
}
|
||||
}
|
||||
@@ -512,6 +540,15 @@ public class SvnHistoryProvider
|
||||
});
|
||||
}
|
||||
|
||||
private boolean checkForChildChanges(SVNLogEntry logEntry) {
|
||||
for (String key : logEntry.getChangedPaths().keySet()) {
|
||||
if (SVNPathUtil.isAncestor(myLastPath, key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String correctLastPathAccordingToFolderRenames(String lastPath, SVNLogEntry logEntry) {
|
||||
final Map<String,SVNLogEntryPath> paths = logEntry.getChangedPaths();
|
||||
for (Map.Entry<String, SVNLogEntryPath> entry : paths.entrySet()) {
|
||||
@@ -562,7 +599,7 @@ public class SvnHistoryProvider
|
||||
public RepositoryLogEntryHandler(final SvnVcs vcs, final String url,
|
||||
final SVNRevision pegRevision,
|
||||
String lastPath,
|
||||
final Consumer<VcsFileRevision> result,
|
||||
final ThrowableConsumer<VcsFileRevision, SVNException> result,
|
||||
SVNURL repoRootURL)
|
||||
throws VcsException, SVNException {
|
||||
super(vcs, url, pegRevision, lastPath, result, repoRootURL, null);
|
||||
@@ -571,7 +608,8 @@ public class SvnHistoryProvider
|
||||
@Override
|
||||
protected SvnFileRevision createRevision(final SVNLogEntry logEntry, final String copyPath, SVNLogEntryPath entryPath)
|
||||
throws SVNException {
|
||||
final SVNURL url = myRepositoryRoot.appendPath(entryPath.getPath(), true);
|
||||
final SVNURL url = entryPath == null ? myRepositoryRoot.appendPath(myLastPath, true) :
|
||||
myRepositoryRoot.appendPath(entryPath.getPath(), true);
|
||||
return new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, url.toString(), copyPath, null);
|
||||
}
|
||||
}
|
||||
|
||||
+58
-294
@@ -27,19 +27,15 @@ import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.*;
|
||||
import com.intellij.openapi.vcs.history.*;
|
||||
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
|
||||
import com.intellij.util.BeforeAfter;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.VcsBackgroundTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.ConflictedSvnChange;
|
||||
import org.jetbrains.idea.svn.SvnRevisionNumber;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.history.SvnHistoryProvider;
|
||||
import org.jetbrains.idea.svn.history.SvnHistorySession;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNNodeKind;
|
||||
import org.tmatesoft.svn.core.internal.wc.SVNConflictVersion;
|
||||
@@ -52,7 +48,6 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -123,60 +118,44 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel {
|
||||
if (myChange.getBeforeRevision() != null) {
|
||||
myCommittedRevision = SvnHistorySession.getCurrentCommittedRevision(myVcs, myPath.getIOFile());
|
||||
}
|
||||
final SVNRevision pegFromLeft = description.getSourceLeftVersion() == null ?
|
||||
null : SVNRevision.create(description.getSourceLeftVersion().getPegRevision());
|
||||
ConflictSidePresentation rightSide = createSide(description.getSourceRightVersion(), pegFromLeft, false);
|
||||
final SidesProcessorMarker marker;
|
||||
ConflictSidePresentation leftSide;
|
||||
if (description.getSourceLeftVersion() != null && description.getSourceRightVersion() != null &&
|
||||
! Comparing.equal(description.getSourceLeftVersion().getPath(), description.getSourceRightVersion().getPath())) {
|
||||
leftSide = createSide(description.getSourceLeftVersion(), pegFromLeft, true);
|
||||
marker = new TwoSidesProcessor((AbstractConflictSide) leftSide, (AbstractConflictSide) rightSide, UniversalComparator.getInstance());
|
||||
} else {
|
||||
leftSide = EmptyConflictSide.getInstance();
|
||||
if (rightSide instanceof AbstractConflictSide) {
|
||||
marker = new OneSideProcessor(
|
||||
description.getSourceLeftVersion() == null ? SVNRevision.create(1) : SVNRevision.create(description.getSourceLeftVersion().getPegRevision()), (AbstractConflictSide) rightSide);
|
||||
boolean differentURLs = description.getSourceLeftVersion() != null && description.getSourceRightVersion() != null &&
|
||||
! Comparing.equal(description.getSourceLeftVersion().getPath(), description.getSourceRightVersion().getPath());
|
||||
|
||||
ConflictSidePresentation leftSide = null;
|
||||
ConflictSidePresentation rightSide = null;
|
||||
try {
|
||||
if (differentURLs) {
|
||||
leftSide = createSide(description.getSourceLeftVersion(), null, true);
|
||||
rightSide = createSide(description.getSourceRightVersion(), null, false);
|
||||
leftSide.load();
|
||||
rightSide.load();
|
||||
} else {
|
||||
marker = SidesProcessorMarker.EMPTY;
|
||||
//only one side
|
||||
leftSide = EmptyConflictSide.getInstance();
|
||||
final SVNRevision pegFromLeft = description.getSourceLeftVersion() == null ?
|
||||
null : SVNRevision.create(description.getSourceLeftVersion().getPegRevision());
|
||||
rightSide = createSide(description.getSourceRightVersion(), pegFromLeft, false);
|
||||
rightSide.load();
|
||||
return new BeforeAfter<ConflictSidePresentation>(leftSide, rightSide);
|
||||
}
|
||||
} catch (SVNException e) {
|
||||
throw new VcsException(e);
|
||||
} finally {
|
||||
if (leftSide != null) {
|
||||
myChildDisposables.add(leftSide);
|
||||
}
|
||||
if (rightSide != null) {
|
||||
myChildDisposables.add(rightSide);
|
||||
}
|
||||
}
|
||||
marker.run();
|
||||
myChildDisposables.add(leftSide);
|
||||
myChildDisposables.add(rightSide);
|
||||
|
||||
return new BeforeAfter<ConflictSidePresentation>(leftSide, rightSide);
|
||||
}
|
||||
|
||||
private static class UniversalComparator<Object> implements Comparator<Object> {
|
||||
private final static UniversalComparator ourComparator = new UniversalComparator();
|
||||
|
||||
public static UniversalComparator getInstance() {
|
||||
return ourComparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Object o1, Object o2) {
|
||||
long number1 = get(o1).getNumber();
|
||||
long number2 = get(o2).getNumber();
|
||||
return number1 < number2 ? -1 : (number1 == number2 ? 0 : 1);
|
||||
}
|
||||
|
||||
private SVNRevision get(final Object o) {
|
||||
if (o instanceof VcsFileRevision) {
|
||||
return ((SvnRevisionNumber) ((VcsFileRevision) o).getRevisionNumber()).getRevision();
|
||||
}
|
||||
if (o instanceof CommittedChangeList) {
|
||||
return SVNRevision.create(((CommittedChangeList) o).getNumber());
|
||||
}
|
||||
assert true;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ConflictSidePresentation createSide(SVNConflictVersion version, final SVNRevision pegFromLeft, final boolean isLeft) throws VcsException {
|
||||
private ConflictSidePresentation createSide(SVNConflictVersion version, final SVNRevision untilThisOther, final boolean isLeft) throws VcsException {
|
||||
if (version == null) return EmptyConflictSide.getInstance();
|
||||
SvnRevisionNumber number = null;
|
||||
if (myChange.getBeforeRevision() != null) {
|
||||
if (myChange.getBeforeRevision() != null && myCommittedRevision != null) {
|
||||
number = (SvnRevisionNumber) myCommittedRevision;
|
||||
if (isLeft && number.getRevision().isValid() && number.getRevision().getNumber() == version.getPegRevision()) {
|
||||
return EmptyConflictSide.getInstance();
|
||||
@@ -188,7 +167,7 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel {
|
||||
} else {
|
||||
return new HistoryConflictSide(myVcs, version);
|
||||
}*/
|
||||
return new HistoryConflictSide(myVcs, version, number == null ? pegFromLeft : number.getRevision());
|
||||
return new HistoryConflictSide(myVcs, version, untilThisOther);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -267,27 +246,6 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel {
|
||||
};
|
||||
}
|
||||
|
||||
private void acceptOne(final SVNTreeConflictDescription description, final SVNConflictChoice choice, final String title) {
|
||||
ProgressManager.getInstance().run(new VcsBackgroundTask<SVNTreeConflictDescription>(myVcs.getProject(), title + myPath,
|
||||
BackgroundFromStartOption.getInstance(), Collections.singletonList(description), true) {
|
||||
@Override
|
||||
protected void process(SVNTreeConflictDescription d) throws VcsException {
|
||||
try {
|
||||
myVcs.createWCClient().doResolve(d.getPath(), SVNDepth.INFINITY, choice);
|
||||
}
|
||||
catch (SVNException e1) {
|
||||
throw new VcsException(e1);
|
||||
}
|
||||
VcsDirtyScopeManager dirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
|
||||
if (myPath.isDirectory()) {
|
||||
dirtyScopeManager.dirDirtyRecursively(myPath);
|
||||
} else {
|
||||
dirtyScopeManager.fileDirty(myPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private ActionListener createLeft(final SVNTreeConflictDescription description) {
|
||||
return new ActionListener() {
|
||||
@Override
|
||||
@@ -358,6 +316,7 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel {
|
||||
|
||||
private interface ConflictSidePresentation extends Disposable {
|
||||
JPanel createPanel();
|
||||
void load() throws SVNException, VcsException;
|
||||
}
|
||||
|
||||
private static class EmptyConflictSide implements ConflictSidePresentation {
|
||||
@@ -375,9 +334,13 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel {
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() throws SVNException {
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class AbstractConflictSide<T> implements ConflictSidePresentation {
|
||||
private static abstract class AbstractConflictSide<T> implements ConflictSidePresentation, Convertor<T, VcsRevisionNumber> {
|
||||
protected final Project myProject;
|
||||
protected final SVNConflictVersion myVersion;
|
||||
|
||||
@@ -385,191 +348,15 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel {
|
||||
myProject = project;
|
||||
myVersion = version;
|
||||
}
|
||||
|
||||
public abstract List<T> step(StopMarker marker) throws VcsException;
|
||||
public abstract void cutTo(final T t);
|
||||
}
|
||||
|
||||
private interface StopMarker {
|
||||
<T> boolean isEof(final List<T> list);
|
||||
}
|
||||
|
||||
private static class ToRevision implements StopMarker {
|
||||
private final SVNRevision myRevision;
|
||||
|
||||
private ToRevision(SVNRevision revision) {
|
||||
myRevision = revision;
|
||||
}
|
||||
|
||||
public SVNRevision getRevision() {
|
||||
return myRevision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean isEof(List<T> list) {
|
||||
// should be ok, check would have be like an assertion -> we asked until the revision
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Portion implements StopMarker {
|
||||
private final static int ourStep = 10;
|
||||
|
||||
public static int getOurStep() {
|
||||
return ourStep;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean isEof(List<T> list) {
|
||||
return list.size() < ourStep;
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoLimit implements StopMarker {
|
||||
private final static NoLimit ourInstance = new NoLimit();
|
||||
|
||||
public static NoLimit getInstance() {
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean isEof(List<T> list) {
|
||||
// we loaded all
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private interface SidesProcessorMarker extends ThrowableRunnable<VcsException> {
|
||||
SidesProcessorMarker EMPTY = new SidesProcessorMarker() {
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class OneSideProcessor<T> implements SidesProcessorMarker {
|
||||
private final AbstractConflictSide<T> mySide;
|
||||
private final SVNRevision myLimitingRevision;
|
||||
|
||||
private OneSideProcessor(SVNRevision limitingRevision, AbstractConflictSide<T> side) {
|
||||
myLimitingRevision = limitingRevision;
|
||||
mySide = side;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() throws VcsException {
|
||||
mySide.step(new ToRevision(myLimitingRevision));
|
||||
}
|
||||
}
|
||||
|
||||
private static class TwoSidesProcessor<Left, Right> implements SidesProcessorMarker {
|
||||
private final AbstractConflictSide<Left> myLeft;
|
||||
private final AbstractConflictSide<Right> myRight;
|
||||
private final Comparator myComparator;
|
||||
|
||||
private TwoSidesProcessor(@NotNull AbstractConflictSide<Left> left, @NotNull AbstractConflictSide<Right> right,
|
||||
final Comparator comparator) {
|
||||
myLeft = left;
|
||||
myRight = right;
|
||||
myComparator = comparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() throws VcsException {
|
||||
final SteppableSide<Left> left = new SteppableSide<Left>(myLeft);
|
||||
final SteppableSide<Right> right = new SteppableSide<Right>(myRight);
|
||||
|
||||
left.init();
|
||||
right.init();
|
||||
|
||||
while (! left.isEof() || ! right.isEof()) {
|
||||
while (left.hasNext() && right.hasNext()) {
|
||||
Left leftItem = left.get();
|
||||
Right rightItem = right.get();
|
||||
int compare = myComparator.compare(leftItem, rightItem);
|
||||
if (compare == 0) {
|
||||
myLeft.cutTo(leftItem);
|
||||
myRight.cutTo(rightItem);
|
||||
return;
|
||||
} else if (compare < 0) {
|
||||
left.step();
|
||||
} else {
|
||||
right.step();
|
||||
}
|
||||
}
|
||||
boolean loadLeft = ! left.hasNext();
|
||||
left.loadStep(loadLeft, right.isEof());
|
||||
right.loadStep(! loadLeft, left.isEof());
|
||||
}
|
||||
}
|
||||
|
||||
private static class SteppableSide<T> {
|
||||
private List<T> myList;
|
||||
private int myIdx;
|
||||
private boolean myEof;
|
||||
private AbstractConflictSide mySide;
|
||||
|
||||
private SteppableSide(AbstractConflictSide side) {
|
||||
mySide = side;
|
||||
myList = Collections.emptyList();
|
||||
myEof = false;
|
||||
myIdx = 0;
|
||||
}
|
||||
|
||||
public void init() throws VcsException {
|
||||
loadPiece(false);
|
||||
}
|
||||
|
||||
public boolean isEof() {
|
||||
return myEof;
|
||||
}
|
||||
|
||||
public void loadStep(final boolean forceAdvanceMe, final boolean foreignEof) throws VcsException {
|
||||
if ((forceAdvanceMe || foreignEof) && ! myEof) {
|
||||
loadPiece(foreignEof);
|
||||
}
|
||||
}
|
||||
|
||||
public void step() {
|
||||
++ myIdx;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return myList.get(myIdx);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return myIdx < myList.size();
|
||||
}
|
||||
|
||||
private void loadPiece(boolean foreignEof) throws VcsException {
|
||||
StopMarker stopMarker = foreignEof ? NoLimit.getInstance() : new Portion();
|
||||
myList = mySide.step(stopMarker);
|
||||
myEof = stopMarker.isEof(myList);
|
||||
myList.clear();
|
||||
myIdx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadPiece(boolean thisEof, boolean foreignEof, final List<Left> list) throws VcsException {
|
||||
//if ((loadThis || foreignEof) && ! thisEof) {
|
||||
StopMarker stopMarker = foreignEof ? NoLimit.getInstance() : new Portion();
|
||||
List<Left> step = myLeft.step(stopMarker);
|
||||
thisEof = stopMarker.isEof(step);
|
||||
list.clear();
|
||||
list.addAll(step);
|
||||
//}
|
||||
return thisEof;
|
||||
}
|
||||
}
|
||||
|
||||
private static class HistoryConflictSide extends AbstractConflictSide<VcsFileRevision> {
|
||||
public static final int LIMIT = 10;
|
||||
private final VcsAppendableHistoryPartnerAdapter mySessionAdapter;
|
||||
private final SvnHistoryProvider myProvider;
|
||||
private final FilePath myPath;
|
||||
private final SvnVcs myVcs;
|
||||
private final SVNRevision myPeg;
|
||||
private SVNRevision myRevisionTo;
|
||||
private FileHistoryPanelImpl myFileHistoryPanel;
|
||||
|
||||
private HistoryConflictSide(SvnVcs vcs, SVNConflictVersion version, final SVNRevision peg) throws VcsException {
|
||||
@@ -585,51 +372,24 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel {
|
||||
}
|
||||
|
||||
mySessionAdapter = new VcsAppendableHistoryPartnerAdapter();
|
||||
mySessionAdapter.reportCreatedEmptySession(new SvnHistorySession(myVcs, Collections.<VcsFileRevision>emptyList(),
|
||||
myPath, SvnUtil.checkRepositoryVersion15(myVcs, version.getPath()), null, true));
|
||||
/*mySessionAdapter.reportCreatedEmptySession(new SvnHistorySession(myVcs, Collections.<VcsFileRevision>emptyList(),
|
||||
myPath, SvnUtil.checkRepositoryVersion15(myVcs, version.getPath()), null, true));*/
|
||||
myProvider = (SvnHistoryProvider) myVcs.getVcsHistoryProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VcsFileRevision> step(StopMarker marker) throws VcsException {
|
||||
List<VcsFileRevision> list = mySessionAdapter.getSession().getRevisionList();
|
||||
int limit = 0;
|
||||
SVNRevision from;
|
||||
if (list.isEmpty()) {
|
||||
myRevisionTo = SVNRevision.create(1);
|
||||
if (marker instanceof ToRevision) {
|
||||
myRevisionTo = ((ToRevision)marker).getRevision();
|
||||
}
|
||||
from = SVNRevision.create(myVersion.getPegRevision());
|
||||
} else {
|
||||
from = ((SvnRevisionNumber) list.get(list.size() - 1).getRevisionNumber()).getRevision();
|
||||
}
|
||||
if (marker instanceof Portion) {
|
||||
limit = Portion.getOurStep();
|
||||
}
|
||||
|
||||
VcsAppendableHistoryPartnerAdapter adapter = new VcsAppendableHistoryPartnerAdapter();
|
||||
myProvider.reportAppendableHistory(myPath, adapter, myRevisionTo, from, limit, myPeg, true);
|
||||
final List<VcsFileRevision> newRevisions = adapter.getSession().getRevisionList();
|
||||
list.addAll(newRevisions);
|
||||
return newRevisions;
|
||||
public VcsRevisionNumber convert(VcsFileRevision o) {
|
||||
return o.getRevisionNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cutTo(VcsFileRevision endRevision) {
|
||||
List<VcsFileRevision> list = mySessionAdapter.getSession().getRevisionList();
|
||||
int i = 0;
|
||||
for (; i < list.size(); i++) {
|
||||
final VcsFileRevision revision = list.get(i);
|
||||
// it is same exactly object so ok if even equals is not overriden
|
||||
if (endRevision.equals(revision)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < list.size()) {
|
||||
final ArrayList<VcsFileRevision> copy = new ArrayList<VcsFileRevision>(list.subList(0, i + 1));
|
||||
list.clear();
|
||||
list.addAll(copy);
|
||||
public void load() throws SVNException, VcsException {
|
||||
SVNRevision from = SVNRevision.create(myVersion.getPegRevision());
|
||||
if (myPeg == null) {
|
||||
// just a portion of history
|
||||
myProvider.reportAppendableHistory(myPath, mySessionAdapter, from, myPeg, LIMIT, myPeg, true);
|
||||
} else {
|
||||
myProvider.reportAppendableHistory(myPath, mySessionAdapter, myPeg, from, 0, myPeg, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,13 +402,17 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel {
|
||||
|
||||
@Override
|
||||
public JPanel createPanel() {
|
||||
// todo do not forget to call dispose
|
||||
// todo remove refresh
|
||||
VcsAbstractHistorySession session = mySessionAdapter.getSession();
|
||||
if (session == null) return EmptyConflictSide.getInstance().createPanel();
|
||||
List<VcsFileRevision> list = session.getRevisionList();
|
||||
if (list.isEmpty()) {
|
||||
return EmptyConflictSide.getInstance().createPanel();
|
||||
}
|
||||
Collections.reverse(list);
|
||||
VcsFileRevision last = null;
|
||||
if (! list.isEmpty() && myRevisionTo.getNumber() > 0 &&
|
||||
myRevisionTo.equals(((SvnRevisionNumber) list.get(list.size() - 1).getRevisionNumber()).getRevision())) {
|
||||
if (! list.isEmpty() && myPeg == null && list.size() == LIMIT ||
|
||||
(myPeg != null && myPeg.getNumber() > 0 &&
|
||||
myPeg.equals(((SvnRevisionNumber) list.get(list.size() - 1).getRevisionNumber()).getRevision()))) {
|
||||
last = list.remove(list.size() - 1);
|
||||
}
|
||||
myFileHistoryPanel = new FileHistoryPanelImpl(myVcs, myPath, session, myProvider, null, new FileHistoryRefresherI() {
|
||||
|
||||
Reference in New Issue
Block a user