/**
* This file is part of git-as-svn. It is subject to the license terms
* in the LICENSE file found in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn,
* including this file, may be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
package svnserver.server.command;
import org.jetbrains.annotations.NotNull;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import svnserver.parser.SvnServerWriter;
import svnserver.repository.VcsCopyFrom;
import svnserver.server.SessionContext;
import java.io.IOException;
/**
* Change current path in repository.
* <p>
* <pre>
* get-location-segments
* params: ( path:string [ start-rev:number ] [ end-rev:number ] )
* Before sending response, server sends location entries, ending with "done".
* location-entry: ( range-start:number range-end:number [ abs-path:string ] ) | done
* response: ( )
* </pre>
*
* @author a.navrotskiy
*/
public final class GetLocationSegmentsCmd extends BaseCmd<GetLocationSegmentsCmd.Params> {
public static class Params {
@NotNull
private final String path;
private final int[] pegRev;
private final int[] startRev;
private final int[] endRev;
public Params(@NotNull String path, int[] pegRev, int[] startRev, int[] endRev) {
this.path = path;
this.pegRev = pegRev;
this.startRev = startRev;
this.endRev = endRev;
}
}
@NotNull
@Override
public Class<Params> getArguments() {
return Params.class;
}
@Override
protected void processCommand(@NotNull SessionContext context, @NotNull Params args) throws IOException, SVNException {
final SvnServerWriter writer = context.getWriter();
final int endRev = getRevision(args.endRev, 0);
final int pegRev = getRevision(args.pegRev, () -> context.getRepository().getLatestRevision().getId());
final int startRev = getRevision(args.startRev, pegRev);
if ((endRev > startRev) || (startRev > pegRev)) {
writer.word("done");
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.UNKNOWN, "Invalid revision range: peg: " + pegRev + ", start: " + startRev + ", end " + endRev));
}
String fullPath = context.getRepositoryPath(args.path);
final int lastChange = context.getRepository().getLastChange(fullPath, pegRev);
if (lastChange < 0) {
writer.word("done");
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_NOT_FOUND, "File not found: " + fullPath + "@" + pegRev));
}
int maxRev = pegRev;
while (maxRev >= endRev) {
int minRev = maxRev;
while (true) {
int change = context.getRepository().getLastChange(fullPath, minRev - 1);
if (change >= 0) {
minRev = change;
} else {
break;
}
}
if (minRev <= startRev) {
writer
.listBegin()
.number(Math.max(minRev, endRev))
.number(Math.min(maxRev, startRev))
.listBegin().string(fullPath).listEnd()
.listEnd();
}
final VcsCopyFrom copyFrom = context.getRepository().getRevisionInfo(minRev).getCopyFrom(fullPath);
if (copyFrom != null) {
maxRev = copyFrom.getRevision();
fullPath = copyFrom.getPath();
} else {
break;
}
}
writer
.word("done");
writer
.listBegin()
.word("success")
.listBegin()
.listEnd()
.listEnd();
}
}