SVNURL srcRepoRoot = null;
SVNURL dstRepoRoot = null;
boolean versionedDst = false;
SVNWCAccess dstAccess = createWCAccess();
try {
dstAccess.probeOpen(dst, false, 0);
SVNEntry dstEntry = dstAccess.getEntry(dst, false);
if (dstEntry != null) {
if (!dstEntry.isScheduledForAddition() && !dstEntry.isScheduledForReplacement()) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_ATTRIBUTE_INVALID, "Cannot perform 'virtual' {0}: ''{1}'' is scheduled neither for addition nor for replacement", new Object[]{opName, dst});
SVNErrorManager.error(err, SVNLogType.WC);
}
versionedDst = true;
dstRepoRoot = dstEntry.getRepositoryRootURL();
}
} finally {
dstAccess.close();
}
SVNWCAccess srcAccess = createWCAccess();
String cfURL = null;
boolean added = false;
long cfRevision = -1;
try {
srcAccess.probeOpen(src, false, 0);
SVNEntry srcEntry = srcAccess.getEntry(src, false);
if (srcEntry == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", src);
SVNErrorManager.error(err, SVNLogType.WC);
}
srcRepoRoot = srcEntry.getRepositoryRootURL();
if (srcEntry.isCopied() && !srcEntry.isScheduledForAddition()) {
cfURL = getCopyFromURL(src.getParentFile(), SVNEncodingUtil.uriEncode(src.getName()));
cfRevision = getCopyFromRevision(src.getParentFile());
if (cfURL == null || cfRevision < 0) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "Cannot locate copied directory root for ''{0}''", src);
SVNErrorManager.error(err, SVNLogType.WC);
}
added = false;
} else {
cfURL = srcEntry.isCopied() ? srcEntry.getCopyFromURL() : srcEntry.getURL();
cfRevision = srcEntry.isCopied() ? srcEntry.getCopyFromRevision() : srcEntry.getRevision();
added = srcEntry.isScheduledForAddition() && !srcEntry.isCopied();
}
} finally {
srcAccess.close();
}
if (added && !versionedDst) {
if (move) {
myWCClient.doDelete(src, true, false);
}
myWCClient.doAdd(dst, true, false, false, SVNDepth.EMPTY, false, false);
return;
}
dstAccess = createWCAccess();
srcAccess = createWCAccess();
try {
SVNAdminArea dstArea = dstAccess.probeOpen(dst, true, 0);
SVNEntry dstEntry = dstAccess.getEntry(dst, false);
if (dstEntry != null && !dstEntry.isScheduledForAddition() && !dstEntry.isScheduledForReplacement()) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_ATTRIBUTE_INVALID, "Cannot perform 'virtual' {0}: ''{1}'' is scheduled neither for addition nor for replacement", new Object[]{opName, dst});
SVNErrorManager.error(err, SVNLogType.WC);
}
if (srcRepoRoot != null && dstRepoRoot != null && !dstRepoRoot.equals(srcRepoRoot)) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_ATTRIBUTE_INVALID, "Cannot perform 'virtual' {0}: paths belong to different repositories", opName);
SVNErrorManager.error(err, SVNLogType.WC);
}
SVNAdminArea srcArea = srcAccess.probeOpen(src, false, 0);
SVNVersionedProperties srcProps = srcArea.getProperties(src.getName());
SVNVersionedProperties srcBaseProps = srcArea.getBaseProperties(src.getName());
SVNVersionedProperties dstProps = dstArea.getProperties(dst.getName());
SVNVersionedProperties dstBaseProps = dstArea.getBaseProperties(dst.getName());
dstProps.removeAll();
dstBaseProps.removeAll();
srcProps.copyTo(dstProps);
srcBaseProps.copyTo(dstBaseProps);
dstEntry = dstArea.addEntry(dst.getName());
dstEntry.setCopyFromURL(cfURL);
dstEntry.setCopyFromRevision(cfRevision);
dstEntry.setCopied(true);
dstEntry.setKind(SVNNodeKind.FILE);
File baseSrc = srcArea.getBaseFile(src.getName(), false);
File baseDst = dstArea.getBaseFile(dst.getName(), false);
SVNFileUtil.copyFile(baseSrc, baseDst, false);
if (dstEntry.isScheduledForDeletion()) {
dstEntry.unschedule();
dstEntry.scheduleForReplacement();
} else if (!dstEntry.isScheduledForReplacement()) {
dstEntry.unschedule();
dstEntry.scheduleForAddition();
}
dstArea.saveEntries(false);
SVNLog log = dstArea.getLog();
dstArea.saveVersionedProperties(log, true);
log.save();
dstArea.runLogs();
SVNEvent event = SVNEventFactory.createSVNEvent(dst, SVNNodeKind.FILE, null, SVNRepository.INVALID_REVISION, SVNEventAction.ADD, null, null, null);
dispatchEvent(event);
} finally {
srcAccess.close();
dstAccess.close();
}
if (move) {
myWCClient.doDelete(src, true, false);
}