package org.tmatesoft.svn.core.internal.wc2.ng; import java.io.File; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; import org.tmatesoft.svn.core.internal.wc17.SVNWCContext; import org.tmatesoft.svn.core.internal.wc17.SVNWCContext.SVNWCNodeReposInfo; import org.tmatesoft.svn.core.internal.wc17.SVNWCUtils; import org.tmatesoft.svn.core.internal.wc17.db.Structure; import org.tmatesoft.svn.core.internal.wc17.db.StructureFields.NodeInfo; import org.tmatesoft.svn.core.internal.wc17.db.StructureFields.NodeOriginInfo; import org.tmatesoft.svn.core.internal.wc2.SvnRepositoryAccess; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.ISvnOperationOptionsProvider; import org.tmatesoft.svn.core.wc2.SvnCopySource; import org.tmatesoft.svn.core.wc2.SvnTarget; import org.tmatesoft.svn.util.SVNLogType; public class SvnNgRepositoryAccess extends SvnRepositoryAccess { public SvnNgRepositoryAccess(ISvnOperationOptionsProvider operationOptionsProvider, SVNWCContext context) throws SVNException { super(operationOptionsProvider, context); } @Override public Structure<RepositoryInfo> createRepositoryFor(SvnTarget target, SVNRevision revision, SVNRevision pegRevision, File baseDirectory) throws SVNException { SVNURL url = getTargetURL(target); if (url == null) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", target.getFile()); SVNErrorManager.error(err, SVNLogType.WC); } SVNRevision[] resolvedRevisions = resolveRevisions(pegRevision, revision, target.isURL(), true); SVNRevision pegRev = resolvedRevisions[0]; SVNRevision startRev = resolvedRevisions[1]; SVNRepository repository = createRepository(url, baseDirectory); if (target.isURL() && !url.equals(repository.getLocation())) { url = repository.getLocation(); } Structure<LocationsInfo> locationsInfo = getLocations(repository, target, pegRev, startRev, SVNRevision.UNDEFINED); long rev = locationsInfo.lng(LocationsInfo.startRevision); url = locationsInfo.<SVNURL>get(LocationsInfo.startUrl); locationsInfo.release(); repository.setLocation(url, false); if (rev < 0) { Structure<RevisionsPair> revs = getRevisionNumber(repository, target, SVNRevision.HEAD, null); rev = revs.lng(RevisionsPair.revNumber); revs.release(); } Structure<RepositoryInfo> result = Structure.obtain(RepositoryInfo.class); result.set(RepositoryInfo.revision, rev); result.set(RepositoryInfo.repository, repository); result.set(RepositoryInfo.url, url); return result; } public Structure<UrlInfo> getURLFromPath(SvnTarget path, SVNRevision revision, SVNRepository repository) throws SVNException { Structure<UrlInfo> urlInfo = Structure.obtain(UrlInfo.class); SVNURL url = null; if (revision == SVNRevision.WORKING) { Structure<NodeOriginInfo> nodeOrigin = getWCContext().getNodeOrigin(path.getFile(), false); urlInfo.set(UrlInfo.pegRevision, nodeOrigin.lng(NodeOriginInfo.revision)); if (nodeOrigin.hasValue(NodeOriginInfo.reposRelpath)) { url = SVNWCUtils.join(nodeOrigin.<SVNURL>get(NodeOriginInfo.reposRootUrl), nodeOrigin.<File>get(NodeOriginInfo.reposRelpath)); } if (url != null && nodeOrigin.hasValue(NodeOriginInfo.isCopy) && nodeOrigin.is(NodeOriginInfo.isCopy) && repository != null) { if (!url.equals(repository.getLocation())) { urlInfo.set(UrlInfo.dropRepsitory, true); repository = null; } } } if (url == null) { url = getWCContext().getNodeUrl(path.getFile()); } if (url == null) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", path.getFile()); SVNErrorManager.error(err, SVNLogType.WC); } urlInfo.set(UrlInfo.url, url); return urlInfo; } @Override public Structure<RevisionsPair> getRevisionNumber(SVNRepository repository, SvnTarget path, SVNRevision revision, Structure<RevisionsPair> youngestRevision) throws SVNException { Structure<RevisionsPair> result = youngestRevision == null ? Structure.obtain(RevisionsPair.class) : youngestRevision; if (youngestRevision == null) { // initial value for the latest rev num result.set(RevisionsPair.youngestRevision, -1); } if (repository == null && (revision == SVNRevision.HEAD || revision.getDate() != null)) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_RA_ACCESS_REQUIRED); SVNErrorManager.error(err, SVNLogType.WC); } if (revision == SVNRevision.UNDEFINED) { result.set(RevisionsPair.revNumber, -1); } else if (revision.getNumber() >= 0) { result.set(RevisionsPair.revNumber, revision.getNumber()); } else if (revision == SVNRevision.HEAD) { if (youngestRevision != null && youngestRevision.lng(RevisionsPair.youngestRevision) >= 0) { result.set(RevisionsPair.revNumber, youngestRevision.lng(RevisionsPair.youngestRevision)); } else { if (repository == null) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_RA_ACCESS_REQUIRED); SVNErrorManager.error(err, SVNLogType.WC); } long youngest = repository.getLatestRevision(); result.set(RevisionsPair.revNumber, youngest); result.set(RevisionsPair.youngestRevision, youngest); } } else if (revision == SVNRevision.WORKING || revision == SVNRevision.BASE) { if (path == null) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_VERSIONED_PATH_REQUIRED); SVNErrorManager.error(err, SVNLogType.WC); } else if (!path.isFile()) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_BAD_REVISION, "PREV, BASE or COMMITTTED revision keywords are invalid for URL"); SVNErrorManager.error(err, SVNLogType.WC); } long revnum = -1; try { revnum = getWCContext().getNodeCommitBaseRev(path.getFile()); } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_PATH_NOT_FOUND) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", path.getFile()); SVNErrorManager.error(err, SVNLogType.WC); } throw e; } if (revnum < 0) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_BAD_REVISION, "Path ''{0}'' has no committed revision", path.getFile()); SVNErrorManager.error(err, SVNLogType.WC); } result.set(RevisionsPair.revNumber, revnum); } else if (revision == SVNRevision.COMMITTED || revision == SVNRevision.PREVIOUS) { if (path == null) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_VERSIONED_PATH_REQUIRED); SVNErrorManager.error(err, SVNLogType.WC); } else if (!path.isFile()) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_BAD_REVISION, "PREV, BASE or COMMITTTED revision keywords are invalid for URL"); SVNErrorManager.error(err, SVNLogType.WC); } long revnum = -1; try { Structure<NodeInfo> info = getWCContext().getDb().readInfo(path.getFile(), NodeInfo.changedRev); revnum = info.lng(NodeInfo.changedRev); info.release(); } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_PATH_NOT_FOUND) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", path.getFile()); SVNErrorManager.error(err, SVNLogType.WC); } throw e; } if (revnum < 0) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_BAD_REVISION, "Path ''{0}'' has no committed revision", path.getFile()); SVNErrorManager.error(err, SVNLogType.WC); } if (revision == SVNRevision.PREVIOUS) { revnum = revnum - 1; } result.set(RevisionsPair.revNumber, revnum); } else if (revision.getDate() != null) { if (repository == null) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_RA_ACCESS_REQUIRED); SVNErrorManager.error(err, SVNLogType.WC); } long revnum = repository.getDatedRevision(revision.getDate()); result.set(RevisionsPair.revNumber, revnum); } else { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_BAD_REVISION, "Unrecognized revision type requested for ''{0}''", path.getFile()); SVNErrorManager.error(err, SVNLogType.WC); } if (youngestRevision != null && (revision == SVNRevision.HEAD || revision.getDate() != null) && youngestRevision.lng(RevisionsPair.youngestRevision) >= 0 && result.lng(RevisionsPair.revNumber) >= 0 && result.lng(RevisionsPair.revNumber) > youngestRevision.lng(RevisionsPair.youngestRevision)) { result.set(RevisionsPair.revNumber, youngestRevision.lng(RevisionsPair.youngestRevision)); } return result; } public SVNRepository createRepository(SVNURL url, File baseDirectory) throws SVNException { String expectedUuid = null; if (baseDirectory != null) { SVNWCNodeReposInfo nodeReposInfo = null; try { nodeReposInfo = getWCContext().getNodeReposInfo(baseDirectory); expectedUuid = nodeReposInfo.reposUuid; } catch (SVNException e) { SVNErrorCode errorCode = e.getErrorMessage().getErrorCode(); if (!(errorCode == SVNErrorCode.WC_NOT_WORKING_COPY || errorCode == SVNErrorCode.WC_PATH_NOT_FOUND || errorCode == SVNErrorCode.WC_UPGRADE_REQUIRED)) { throw e; } } } return createRepository(url, expectedUuid, true); } public SvnCopySource createRemoteCopySource(SVNWCContext context, SvnCopySource localCopySource) throws SVNException { Structure<NodeOriginInfo> origin = context.getNodeOrigin(localCopySource.getSource().getFile(), true, NodeOriginInfo.reposRelpath, NodeOriginInfo.reposRootUrl, NodeOriginInfo.revision); SVNURL url = origin.get(NodeOriginInfo.reposRootUrl); url = url.appendPath(SVNFileUtil.getFilePath(origin.<File>get(NodeOriginInfo.reposRelpath)), false); SVNRevision pegRevision = localCopySource.getSource().getResolvedPegRevision(); SVNRevision revision = localCopySource.getRevision(); if (pegRevision == SVNRevision.UNDEFINED || pegRevision == SVNRevision.WORKING || pegRevision == SVNRevision.BASE) { pegRevision = SVNRevision.create(origin.lng(NodeOriginInfo.revision)); } if (revision == SVNRevision.BASE) { revision = SVNRevision.create(origin.lng(NodeOriginInfo.revision)); } origin.release(); localCopySource = SvnCopySource.create(SvnTarget.fromURL(url, pegRevision), revision); return localCopySource; } protected SVNURL getTargetURL(SvnTarget target) throws SVNException { if (target.isURL()) { return target.getURL(); } return getWCContext().getNodeUrl(target.getFile()); } }