/** * 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; import java.util.Arrays; /** * Change current path in repository. * <p> * <pre> * get-locations * params: ( path:string peg-rev:number ( rev:number ... ) ) * Before sending response, server sends location entries, ending with "done". * location-entry: ( rev:number abs-path:number ) | done * response: ( ) * </pre> * * @author a.navrotskiy */ public final class GetLocationsCmd extends BaseCmd<GetLocationsCmd.Params> { public static class Params { @NotNull private final String path; private final int pegRev; @NotNull private final int[] revs; public Params(@NotNull String path, int pegRev, @NotNull int[] revs) { this.path = path; this.pegRev = pegRev; this.revs = revs; } } @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[] sortedRevs = Arrays.copyOf(args.revs, args.revs.length); Arrays.sort(sortedRevs); String fullPath = context.getRepositoryPath(args.path); int lastChange = context.getRepository().getLastChange(fullPath, args.pegRev); if (lastChange < 0) { writer.word("done"); throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_NOT_FOUND, "File not found: " + fullPath + "@" + args.pegRev)); } for (int i = sortedRevs.length - 1; i >= 0; --i) { int revision = sortedRevs[i]; if (revision > args.pegRev) { writer.word("done"); throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_NOT_FOUND, "File not found: " + fullPath + "@" + args.pegRev + " at revision " + revision)); } while ((revision < lastChange) && (lastChange >= 0)) { int change = context.getRepository().getLastChange(fullPath, lastChange - 1); if (change >= 0) { lastChange = change; continue; } final VcsCopyFrom copyFrom = context.getRepository().getRevisionInfo(lastChange).getCopyFrom(fullPath); if (copyFrom != null) { lastChange = copyFrom.getRevision(); fullPath = copyFrom.getPath(); } else { lastChange = -1; break; } } if (lastChange < 0) break; if (revision >= lastChange) { writer .listBegin() .number(revision) .string(fullPath) .listEnd(); } } writer .word("done"); writer .listBegin() .word("success") .listBegin() .listEnd() .listEnd(); } }