package org.tmatesoft.svn.core.internal.wc2.ng;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
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.util.SVNURLUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.internal.wc.SVNExternal;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.internal.wc17.SVNExternalsStore;
import org.tmatesoft.svn.core.internal.wc17.SVNWCContext;
import org.tmatesoft.svn.core.internal.wc17.db.SvnWcDbRelocate;
import org.tmatesoft.svn.core.internal.wc17.db.SvnWcDbRelocate.ISvnRelocateValidator;
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc2.SvnRelocate;
import org.tmatesoft.svn.util.SVNLogType;
public class SvnNgRelocate extends SvnNgOperationRunner<SVNURL, SvnRelocate> implements ISvnRelocateValidator {
private Map<String, SVNURL> collectedUuids;
@Override
protected SVNURL run(SVNWCContext context) throws SVNException {
if (getOperation().getFromUrl() == null) {
SVNURL fromURL = context.getNodeUrl(getFirstTarget());
getOperation().setFromUrl(fromURL);
}
if (getOperation().isIgnoreExternals()) {
SvnWcDbRelocate.relocate(context, getFirstTarget(), getOperation().getFromUrl(), getOperation().getToUrl(), this);
return getOperation().getToUrl();
}
SVNURL oldReposRootUrl = context.getNodeReposInfo(getFirstTarget()).reposRootUrl;
SvnWcDbRelocate.relocate(context, getFirstTarget(), getOperation().getFromUrl(), getOperation().getToUrl(), this);
SVNURL newReposRootUrl = context.getNodeReposInfo(getFirstTarget()).reposRootUrl;
SVNExternalsStore externalsStore = new SVNExternalsStore();
context.getDb().gatherExternalDefinitions(getFirstTarget(), externalsStore);
for(File externalAbsPath : externalsStore.getNewExternals().keySet()) {
String externalDefinition = externalsStore.getNewExternals().get(externalAbsPath);
SVNExternal[] externals = SVNExternal.parseExternals(externalAbsPath, externalDefinition);
if (externals != null && externals.length > 0) {
relocateExternals(externalAbsPath, externals, oldReposRootUrl, newReposRootUrl);
}
}
return getOperation().getToUrl();
}
private void relocateExternals(File localAbsPath, SVNExternal[] externals, SVNURL oldReposRootUrl, SVNURL newReposRootUrl) throws SVNException {
for (int i = 0; i < externals.length; i++) {
String rawUrl = externals[i].getUnresolvedUrl();
if (!(rawUrl.startsWith("../") || rawUrl.startsWith("^/"))) {
continue;
}
File targetPath = SVNFileUtil.createFilePath(localAbsPath, externals[i].getPath());
try {
SVNURL targetRepositoryRootUrl = getWcContext().getNodeReposInfo(targetPath).reposRootUrl;
if (targetRepositoryRootUrl.equals(oldReposRootUrl)) {
SvnWcDbRelocate.relocate(getWcContext(), targetPath, oldReposRootUrl, newReposRootUrl, this);
}
} catch (SVNException e) {
if (e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_PATH_NOT_FOUND) {
continue;
}
}
}
}
public void validateRelocation(String uuid, SVNURL url, SVNURL rootUrl) throws SVNException {
String urlUuid = null;
SVNURL urlRoot = null;
for (String uu : collectedUuids.keySet()) {
SVNURL root = collectedUuids.get(uu);
if (SVNURLUtil.getRelativeURL(root, url, false) != null) {
urlUuid = uu;
urlRoot = root;
break;
}
}
if (urlUuid == null) {
SVNRepository repository = getRepositoryAccess().createRepository(url, null);
urlUuid = repository.getRepositoryUUID(true);
urlRoot = repository.getRepositoryRoot(true);
}
if (rootUrl != null && !rootUrl.equals(urlRoot)) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_INVALID_RELOCATION, "''{0}'' is not the root of the repository", url);
SVNErrorManager.error(err, SVNLogType.WC);
}
if (uuid != null && !uuid.equals(urlUuid)) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_INVALID_RELOCATION,
"The repository at ''{0}'' has uuid ''{1}'', but the WC has ''{2}''", url, urlUuid, uuid);
SVNErrorManager.error(err, SVNLogType.WC);
}
}
@Override
public void reset(SvnWcGeneration wcGeneration) {
super.reset(wcGeneration);
collectedUuids = new HashMap<String, SVNURL>();
}
}