package org.tmatesoft.svn.core.internal.wc2.remote;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;
import org.tmatesoft.svn.core.ISVNLogEntryHandler;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.util.SVNURLUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.internal.wc17.db.Structure;
import org.tmatesoft.svn.core.internal.wc2.SvnRemoteOperationRunner;
import org.tmatesoft.svn.core.internal.wc2.SvnRepositoryAccess;
import org.tmatesoft.svn.core.internal.wc2.SvnRepositoryAccess.RepositoryInfo;
import org.tmatesoft.svn.core.internal.wc2.SvnRepositoryAccess.RevisionsPair;
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnCat;
import org.tmatesoft.svn.core.wc2.SvnLog;
import org.tmatesoft.svn.core.wc2.SvnRevisionRange;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import org.tmatesoft.svn.util.SVNLogType;
public class SvnRemoteLog extends SvnRemoteOperationRunner<SVNLogEntry, SvnLog> implements ISVNLogEntryHandler {
public boolean isApplicable(SvnCat operation, SvnWcGeneration wcGeneration) throws SVNException {
return true;
}
@Override
protected SVNLogEntry run() throws SVNException {
String[] targetPaths = null;
SVNRevision pegRevision = getOperation().getFirstTarget().getPegRevision();
SvnTarget baseTarget = getOperation().getFirstTarget();
SVNRevision sessionRevision = SVNRevision.UNDEFINED;
List<SvnRevisionRange> editedRevisionRanges = new LinkedList<SvnRevisionRange>();
for (Iterator<SvnRevisionRange> revRangesIter = getOperation().getRevisionRanges().iterator(); revRangesIter.hasNext();) {
SvnRevisionRange revRange = (SvnRevisionRange) revRangesIter.next();
if (revRange.getStart().isValid() && !revRange.getEnd().isValid()) {
revRange = SvnRevisionRange.create(revRange.getStart(), revRange.getStart());
} else if (!revRange.getStart().isValid()) {
SVNRevision start = SVNRevision.UNDEFINED;
SVNRevision end = SVNRevision.UNDEFINED;
if (!getOperation().getFirstTarget().getPegRevision().isValid()) {
if (getOperation().hasRemoteTargets()) {
start = SVNRevision.HEAD;
} else {
start = SVNRevision.BASE;
}
} else {
start = getOperation().getFirstTarget().getPegRevision();
}
if (!revRange.getEnd().isValid()) {
end = SVNRevision.create(0);
}
revRange = SvnRevisionRange.create(start, end);
}
if (!revRange.getStart().isValid() || !revRange.getEnd().isValid()) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_BAD_REVISION, "Missing required revision specification");
SVNErrorManager.error(err, SVNLogType.WC);
}
if (getOperation().hasRemoteTargets()) {
if (isRevisionLocalToWc(revRange.getStart()) || isRevisionLocalToWc(revRange.getEnd())) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_BAD_REVISION, "Revision type requires a working copy path, not a URL");
SVNErrorManager.error(err, SVNLogType.WC);
}
}
editedRevisionRanges.add(revRange);
if (!sessionRevision.isValid()) {
SVNRevision start = revRange.getStart();
SVNRevision end = revRange.getEnd();
if (SVNRevision.isValidRevisionNumber(start.getNumber()) && SVNRevision.isValidRevisionNumber(end.getNumber())) {
sessionRevision = start.getNumber() > end.getNumber() ? start : end;
} else if (start.getDate() != null && end.getDate() != null) {
sessionRevision = start.getDate().compareTo(end.getDate()) > 0 ? start : end;
} else if (start == SVNRevision.HEAD || end == SVNRevision.HEAD) {
sessionRevision = SVNRevision.HEAD;
}
}
}
if (getOperation().hasRemoteTargets()) {
if (getOperation().getTargetPaths() == null) {
targetPaths = new String[] {""};
} else {
targetPaths = getOperation().getTargetPaths();
}
} else {
if (!pegRevision.isValid()) {
pegRevision = SVNRevision.WORKING;
}
SVNURL[] targetUrls = new SVNURL[getOperation().getTargets().size()];
Collection<String> wcPaths = new ArrayList<String>();
int i = 0;
Structure<RepositoryInfo> repositoryInfo =
getRepositoryAccess().createRepositoryFor(
baseTarget,
sessionRevision,
pegRevision,
null);
SVNRepository repository = repositoryInfo.<SVNRepository>get(RepositoryInfo.repository);
repositoryInfo.release();
for (SvnTarget target : getOperation().getTargets()) {
checkCancelled();
File path = target.getFile();
wcPaths.add(path.getAbsolutePath().replace(File.separatorChar, '/'));
Structure<SvnRepositoryAccess.UrlInfo> locationsInfo = getRepositoryAccess().getURLFromPath(target, target.getResolvedPegRevision(), repository);
targetUrls[i++] = locationsInfo.<SVNURL>get(SvnRepositoryAccess.UrlInfo.url);
}
if (targetUrls.length == 0) {
return null;
}
Collection<String> targets = new TreeSet<String>();
SVNURL baseURL = SVNURLUtil.condenceURLs(targetUrls, targets, true);
if (baseURL == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ILLEGAL_TARGET, "target log paths belong to different repositories");
SVNErrorManager.error(err, SVNLogType.WC);
return null;
}
if (targets.isEmpty()) {
targets.add("");
}
targetPaths = (String[]) targets.toArray(new String[targets.size()]);
for (i = 0; i < targetPaths.length; i++) {
targetPaths[i] = SVNEncodingUtil.uriDecode(targetPaths[i]);
}
if (isRevisionLocalToWc(pegRevision)) {
String rootWCPath = SVNPathUtil.condencePaths((String[]) wcPaths.toArray(new String[wcPaths.size()]), null, true);
baseTarget = SvnTarget.fromFile(new File(rootWCPath), pegRevision);
}
}
Structure<RepositoryInfo> repositoryInfo =
getRepositoryAccess().createRepositoryFor(
baseTarget,
sessionRevision,
pegRevision,
null);
SVNRepository repository = repositoryInfo.<SVNRepository>get(RepositoryInfo.repository);
repositoryInfo.release();
for (Iterator<SvnRevisionRange> revRangesIter = editedRevisionRanges.iterator(); revRangesIter.hasNext();) {
checkCancelled();
SvnRevisionRange revRange = (SvnRevisionRange) revRangesIter.next();
checkCancelled();
Structure<RevisionsPair> pair = getRepositoryAccess().getRevisionNumber(repository, baseTarget, revRange.getStart(), null);
long startRev = pair.lng(RevisionsPair.revNumber);
pair = getRepositoryAccess().getRevisionNumber(repository, baseTarget, revRange.getEnd(), pair);
long endRev = pair.lng(RevisionsPair.revNumber);
pair.release();
repository.log(
targetPaths,
startRev,
endRev,
getOperation().isDiscoverChangedPaths(),
getOperation().isStopOnCopy(),
getOperation().getLimit(),
getOperation().isUseMergeHistory(),
getOperation().getRevisionProperties(),
this);
}
return getOperation().first();
}
public void handleLogEntry(SVNLogEntry logEntry) throws SVNException {
checkCancelled();
getOperation().receive(null, logEntry);
}
}