package org.tmatesoft.svn.core.internal.wc2.ng;
import java.io.File;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNProperty;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.db.SVNSqlJetDb;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.internal.wc.SVNEventFactory;
import org.tmatesoft.svn.core.internal.wc.SVNExternal;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.internal.wc17.SVNWCContext;
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb;
import org.tmatesoft.svn.core.internal.wc17.db.SVNWCDb;
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
import org.tmatesoft.svn.core.wc.SVNEvent;
import org.tmatesoft.svn.core.wc.SVNEventAction;
import org.tmatesoft.svn.core.wc2.ISvnObjectReceiver;
import org.tmatesoft.svn.core.wc2.SvnGetProperties;
import org.tmatesoft.svn.core.wc2.SvnGetStatus;
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
import org.tmatesoft.svn.core.wc2.SvnStatus;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import org.tmatesoft.svn.core.wc2.SvnUpgrade;
import org.tmatesoft.svn.util.SVNLogType;
public class SvnNgUpgrade extends SvnNgOperationRunner<SvnWcGeneration, SvnUpgrade> {
@Override
protected SvnWcGeneration run(SVNWCContext context) throws SVNException {
ISVNWCDb db = context.getDb();
if (db != null && db instanceof SVNWCDb) {
final File localAbsPath = getFirstTarget();
SVNWCDb.DirParsedInfo dirParsedInfo = ((SVNWCDb) db).parseDir(localAbsPath, SVNSqlJetDb.Mode.ReadOnly, true, false);
int format = dirParsedInfo.wcDbDir.getWCRoot().getFormat();
if (format < getOperation().getTargetWorkingCopyFormat()) {
SvnNgUpgradeSDb.upgrade(localAbsPath, (SVNWCDb) db, db.getSDb(dirParsedInfo.wcDbDir.getWCRoot().getAbsPath()), format, context.getEventHandler());
}
final SVNURL[] lastRepos = {null};
final String[] lastUuid = {null};
final SvnGetProperties getProperties = getOperation().getOperationFactory().createGetProperties();
getProperties.setDepth(SVNDepth.INFINITY);
getProperties.setSingleTarget(getOperation().getFirstTarget());
getProperties.setReceiver(new ISvnObjectReceiver<SVNProperties>() {
public void receive(SvnTarget target, SVNProperties properties) throws SVNException {
File externalsParentAbsPath = target.getFile();
File externalsParentRelPath = SVNFileUtil.skipAncestor(localAbsPath, externalsParentAbsPath);
String externalsValuesString = properties.getStringValue(SVNProperty.EXTERNALS);
try {
SVNWCContext.SVNWCNodeReposInfo nodeReposInfo = getWcContext().getNodeReposInfo(externalsParentAbsPath);
SVNURL externalsParentReposRootUrl = nodeReposInfo.reposRootUrl;
SVNURL externalsParentUrl = externalsParentReposRootUrl.appendPath(SVNFileUtil.getFilePath(externalsParentRelPath), false);
if (externalsValuesString != null) {
SVNExternal[] externals = SVNExternal.parseExternals(externalsParentAbsPath, externalsValuesString);
for (SVNExternal external : externals) {
File externalsAbsPath = SVNFileUtil.createFilePath(externalsParentAbsPath, external.getPath());
try {
SVNURL resolvedUrl = external.resolveURL(externalsParentReposRootUrl, externalsParentUrl);
boolean upgradeRequired = false;
SVNNodeKind externalKind;
try {
externalKind = getWcContext().getDb().readKind(externalsAbsPath, true, true, false);
try {
SvnGetStatus getStatus = getOperation().getOperationFactory().createGetStatus();
getStatus.setDepth(SVNDepth.EMPTY);
getStatus.setSingleTarget(SvnTarget.fromFile(externalsAbsPath));
SvnStatus status = getStatus.run();
if (status != null) {
int workingCopyFormat = status.getWorkingCopyFormat();
if (workingCopyFormat < getOperation().getTargetWorkingCopyFormat()) {
upgradeRequired = true;
}
}
} catch (SVNException e) {
}
} catch (SVNException e) {
if (e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_UPGRADE_REQUIRED) {
upgradeRequired = true;
} else {
throw e;
}
}
if (upgradeRequired) {
SvnOperationFactory operationFactory = getOperation().getOperationFactory();
SvnUpgrade upgrade = operationFactory.createUpgrade();
upgrade.setSingleTarget(SvnTarget.fromFile(externalsAbsPath));
upgrade.run();
}
externalKind = getWcContext().getDb().readKind(externalsAbsPath, true, true, false);
SVNWCContext.SVNWCNodeReposInfo reposInfo = getWcContext().getNodeReposInfo(externalsAbsPath);
SVNURL reposRootUrl = reposInfo.reposRootUrl;
String reposUuid = reposInfo.reposUuid;
File reposRelPath = reposInfo.reposRelPath;
if (resolvedUrl != null && reposRootUrl != null && !resolvedUrl.equals(reposRootUrl.appendPath(SVNFileUtil.getFilePath(reposRelPath), false))) {
SVNWCDb.ReposInfo fetchedReposInfo = fetchReposInfo(resolvedUrl, lastRepos[0], lastUuid[0]);
lastRepos[0] = SVNURL.parseURIEncoded(fetchedReposInfo.reposRootUrl);
lastUuid[0] = fetchedReposInfo.reposUuid;
reposRelPath = SVNFileUtil.createFilePath(SVNPathUtil.getRelativePath(reposRootUrl.toDecodedString(), resolvedUrl.toDecodedString()));
externalKind = SVNNodeKind.UNKNOWN;
}
long pegRevision = external.getPegRevision().getNumber();
long revision = external.getRevision().getNumber();
upgradeAddExternalInfo(externalsAbsPath, externalKind, externalsParentAbsPath, reposRelPath, reposRootUrl, reposUuid, pegRevision, revision);
} catch (SVNException e) {
SVNEvent event = SVNEventFactory.createSVNEvent(externalsAbsPath, SVNNodeKind.UNKNOWN, null, -1, SVNEventAction.FAILED_EXTERNAL, SVNEventAction.FAILED_EXTERNAL, e.getErrorMessage(), null);
ISVNEventHandler eventHandler = getOperation().getEventHandler();
if (eventHandler != null) {
eventHandler.handleEvent(event, UNKNOWN);
}
}
}
}
} catch (SVNException e) {
if (e.getErrorMessage().getErrorCode() != SVNErrorCode.CLIENT_INVALID_EXTERNALS_DESCRIPTION) {
throw e;
}
SVNEvent event = SVNEventFactory.createSVNEvent(localAbsPath, SVNNodeKind.UNKNOWN, null, -1, SVNEventAction.FAILED_EXTERNAL, SVNEventAction.FAILED_EXTERNAL, e.getErrorMessage(), null);
ISVNEventHandler eventHandler = getOperation().getEventHandler();
if (eventHandler != null) {
eventHandler.handleEvent(event, UNKNOWN);
}
}
}
});
getProperties.run();
} else {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_INVALID_OP_ON_CWD, "Can''t upgrade ''{0}'' as it is not a pre-1.7 working copy directory",
getOperation().getFirstTarget().getFile().getAbsolutePath());
SVNErrorManager.error(err, SVNLogType.WC);
}
return SvnWcGeneration.V17;
}
public void upgradeAddExternalInfo(File localAbsPath, SVNNodeKind kind, File defLocalAbsPath, File reposRelPath, SVNURL reposRootUrl, String reposUuid, long defPegRevision, long defRevision) throws SVNException {
SVNNodeKind dbKind = SVNNodeKind.UNKNOWN;
if (kind == SVNNodeKind.DIR) {
dbKind = SVNNodeKind.DIR;
} else if (kind == SVNNodeKind.FILE) {
dbKind = SVNNodeKind.FILE;
} else if (kind == SVNNodeKind.UNKNOWN) {
dbKind = SVNNodeKind.UNKNOWN;
} else {
SVNErrorManager.assertionFailure(false, null, SVNLogType.WC);
}
getWcContext().getDb().upgradeInsertExternal(localAbsPath, dbKind, SVNFileUtil.getParentFile(localAbsPath), defLocalAbsPath, reposRelPath, reposRootUrl, reposUuid, defPegRevision, defRevision);
}
public SVNWCDb.ReposInfo fetchReposInfo(SVNURL url, SVNURL lastRepos, String lastUuid) throws SVNException {
if (lastRepos != null && SVNPathUtil.isAncestor(lastRepos.toString(), url.toString())) {
SVNWCDb.ReposInfo reposInfo = new SVNWCDb.ReposInfo();
reposInfo.reposRootUrl = lastRepos.toString();
reposInfo.reposUuid = lastUuid;
return reposInfo;
}
SVNRepository repository = getRepositoryAccess().createRepository(url, null, true);
SVNWCDb.ReposInfo reposInfo = new SVNWCDb.ReposInfo();
reposInfo.reposRootUrl = repository.getRepositoryRoot(true).toString();
reposInfo.reposUuid = repository.getRepositoryUUID(true);
return reposInfo;
}
}