blob: 57f42615b0ded56df2fa98d9c750597217bf8e6f [file] [log] [blame]
/*
* Copyright 2000-2009 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.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.VcsException;
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.jetbrains.idea.svn.commandLine.SvnBindException;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
import java.util.Iterator;
import java.util.List;
public class LiveProvider implements BunchProvider {
private final SvnLogLoader myLoader;
private final SvnRepositoryLocation myLocation;
private final SVNURL myRepositoryUrl;
private boolean myEarliestRevisionWasAccessed;
private final long myYoungestRevision;
private final SvnVcs myVcs;
public LiveProvider(final SvnVcs vcs,
final SvnRepositoryLocation location,
final long latestRevision,
final SvnLogLoader loader,
SVNURL repositoryUrl) {
myVcs = vcs;
myLoader = loader;
myLocation = location;
myYoungestRevision = latestRevision;
myRepositoryUrl = repositoryUrl;
}
public long getEarliestRevision() {
return -1;
}
public boolean isEmpty() {
return false;
}
public Fragment getEarliestBunchInInterval(final long earliestRevision, final long oldestRevision, final int desirableSize,
final boolean includeYoungest, final boolean includeOldest) throws VcsException {
return getEarliestBunchInIntervalImpl(earliestRevision, oldestRevision, desirableSize, includeYoungest, includeOldest, earliestRevision);
}
private Fragment getEarliestBunchInIntervalImpl(long earliestRevision,
final long oldestRevision,
final int desirableSize,
final boolean includeYoungest,
final boolean includeOldest, final long earliestToTake) throws VcsException {
if ((myEarliestRevisionWasAccessed) || ((oldestRevision == myYoungestRevision) && ((! includeYoungest) || (! includeOldest)))) {
return null;
}
final SVNRevision youngRevision = (earliestRevision == -1) ? SVNRevision.HEAD : SVNRevision.create(earliestRevision);
final Ref<List<CommittedChangeList>> refToList = new Ref<List<CommittedChangeList>>();
final Ref<VcsException> exceptionRef = new Ref<VcsException>();
final Runnable loader = new Runnable() {
public void run() {
try {
refToList.set(
myLoader.loadInterval(youngRevision, SVNRevision.create(oldestRevision), desirableSize, includeYoungest, includeOldest));
}
catch (VcsException e) {
exceptionRef.set(e);
}
}
};
final Application application = ApplicationManager.getApplication();
if (application.isUnitTestMode() || ! application.isDispatchThread()) {
loader.run();
} else {
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
public void run() {
final ProgressIndicator ind = ProgressManager.getInstance().getProgressIndicator();
if (ind != null) {
ind.setText(SvnBundle.message("progress.live.provider.loading.revisions.details.text"));
}
loader.run();
}
}, SvnBundle.message("progress.live.provider.loading.revisions.text"), false, myVcs.getProject());
}
if (!exceptionRef.isNull()) {
final VcsException e = exceptionRef.get();
if (isElementNotFound(e)) {
// occurs when target URL is deleted in repository
// try to find latest existent revision. expensive ...
final LatestExistentSearcher searcher = new LatestExistentSearcher(oldestRevision, myYoungestRevision, (oldestRevision != 0),
myVcs, myLocation.toSvnUrl(), myRepositoryUrl);
final long existent = searcher.getLatestExistent();
if ((existent == -1) || (existent == earliestRevision)) {
myEarliestRevisionWasAccessed = true;
return null;
}
return getEarliestBunchInIntervalImpl(existent, oldestRevision, includeYoungest ? desirableSize : (desirableSize + 1), true,
includeOldest,
Math.min(existent, earliestRevision));
}
throw e;
}
final List<CommittedChangeList> list = refToList.get();
if (list.isEmpty()) {
myEarliestRevisionWasAccessed = (oldestRevision == 0);
return null;
}
if (earliestToTake > 0) {
for (Iterator<CommittedChangeList> iterator = list.iterator(); iterator.hasNext(); ) {
final CommittedChangeList changeList = iterator.next();
if (changeList.getNumber() > earliestToTake) iterator.remove();
}
}
myEarliestRevisionWasAccessed = (oldestRevision == 0) && ((list.size() + ((! includeOldest) ? 1 : 0) + ((! includeYoungest) ? 1 : 0)) < desirableSize);
return new Fragment(Origin.LIVE, list, true, true, null);
}
private static boolean isElementNotFound(@NotNull VcsException e) {
return e instanceof SvnBindException && ((SvnBindException)e).contains(SVNErrorCode.FS_NOT_FOUND);
}
public boolean isEarliestRevisionWasAccessed() {
return myEarliestRevisionWasAccessed;
}
}