* Also newURL or oldURL could be null, when external property is added or
* removed by update itself (someone else has changed it). For instance,
* oldURL is always null during checkout or export operation.
*/
private void handleExternalChange(SVNWCAccess access, String targetDir, ExternalDiff externalDiff) throws SVNException {
File target = new Resource(externalDiff.owner, targetDir);
SVNURL oldURL = null;
SVNURL newURL = null;
String externalDefinition = null;
if (externalDiff.oldExternal != null && !externalDiff.isExport) {
oldURL = externalDiff.oldExternal.resolveURL(externalDiff.rootURL, externalDiff.ownerURL);
externalDefinition = externalDiff.oldExternal.getRawValue();
}
SVNRevision externalRevision = SVNRevision.UNDEFINED;
SVNRevision externalPegRevision = SVNRevision.UNDEFINED;
if (externalDiff.newExternal != null) {
newURL = externalDiff.newExternal.resolveURL(externalDiff.rootURL, externalDiff.ownerURL);
externalRevision = externalDiff.newExternal.getRevision();
externalPegRevision = externalDiff.newExternal.getPegRevision();
externalDefinition = externalDiff.newExternal.getRawValue();
}
if (oldURL == null && newURL == null) {
return;
}
SVNRevision[] revs = getExternalsHandler().handleExternal(target, newURL, externalRevision,
externalPegRevision, externalDefinition, SVNRevision.UNDEFINED);
if (revs == null) {
SVNEvent event = SVNEventFactory.createSVNEvent(target, SVNNodeKind.DIR, null, SVNRepository.INVALID_REVISION,
SVNEventAction.SKIP, SVNEventAction.UPDATE_EXTERNAL, null, null);
dispatchEvent(event);
return;
}
externalRevision = revs.length > 0 && revs[0] != null ? revs[0] : externalRevision;
externalPegRevision = revs.length > 1 && revs[1] != null ? revs[1] : externalPegRevision;
SVNRepository repository = null;
SVNNodeKind kind = null;
SVNURL reposRootURL = null;
if (newURL != null) {
long[] rev = { SVNRepository.INVALID_REVISION };
repository = createRepository(newURL, null, null, externalPegRevision, externalRevision, rev);
reposRootURL = repository.getRepositoryRoot(true);
kind = repository.checkPath("", rev[0]);
if (kind == SVNNodeKind.NONE) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.RA_ILLEGAL_URL, "URL ''{0}'' at revision {1} doesn''t exist",
new Object[] { repository.getLocation(), String.valueOf(rev[0]) });
SVNErrorManager.error(err, SVNLogType.WC);
}
if (kind != SVNNodeKind.DIR && kind != SVNNodeKind.FILE) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.RA_ILLEGAL_URL, "URL ''{0}'' at revision {1} is not a file or a directory",
new Object[] { repository.getLocation(), String.valueOf(rev[0]) });
SVNErrorManager.error(err, SVNLogType.WC);
}
}
try {
setEventPathPrefix("path");
if (oldURL == null) {
if (kind == SVNNodeKind.DIR) {
target.mkdirs();
dispatchEvent(SVNEventFactory.createSVNEvent(target, SVNNodeKind.DIR, null, SVNRepository.INVALID_REVISION,
SVNEventAction.UPDATE_EXTERNAL, null, null, null));
if (externalDiff.isExport) {
doExport(newURL, target, externalPegRevision, externalRevision, null, true, SVNDepth.INFINITY);
} else {
doCheckout(newURL, target, externalPegRevision, externalRevision, SVNDepth.INFINITY, false);
}
} else if (kind == SVNNodeKind.FILE) {
dispatchEvent(SVNEventFactory.createSVNEvent(target, SVNNodeKind.FILE, null, SVNRepository.INVALID_REVISION,
SVNEventAction.UPDATE_EXTERNAL, null, null, null));
if (externalDiff.isExport) {
boolean ignoreExternals = isIgnoreExternals();
setIgnoreExternals(true);
doExport(newURL, target, externalPegRevision, externalRevision, null, false, SVNDepth.INFINITY);
setIgnoreExternals(ignoreExternals);
} else {
switchFileExternal(access, target, newURL, externalPegRevision, externalRevision, reposRootURL);
}
}
} else if (newURL == null) {
SVNWCAccess wcAccess = createWCAccess();
SVNAdminArea area = wcAccess.open(target, true, SVNWCAccess.INFINITE_DEPTH);
SVNException error = null;
try {
area.removeFromRevisionControl(area.getThisDirName(), true, false);
} catch (SVNException svne) {
error = svne;
}
if (error == null || error.getErrorMessage().getErrorCode() == SVNErrorCode.WC_LEFT_LOCAL_MOD) {
try {
wcAccess.close();
} catch (SVNException svne) {
error = error == null ? svne : error;
}
}
if (error != null && error.getErrorMessage().getErrorCode() != SVNErrorCode.WC_LEFT_LOCAL_MOD) {
throw error;
}
} else if (externalDiff.isUpdateUnchanged || !externalDiff.compareExternals(oldURL, newURL)) {
if (kind == SVNNodeKind.DIR) {
SVNFileType fileType = SVNFileType.getType(target);
boolean empty = false;
if (fileType == SVNFileType.DIRECTORY) {
File[] children = target.listFiles();
if (children != null && children.length == 0) {
empty = true;
}
}
if (fileType == SVNFileType.DIRECTORY && !empty) {
dispatchEvent(SVNEventFactory.createSVNEvent(target, SVNNodeKind.DIR, null, SVNRepository.INVALID_REVISION, SVNEventAction.UPDATE_EXTERNAL, null, null, null));
SVNWCAccess wcAccess = createWCAccess();
SVNAdminArea area = wcAccess.open(target, true, 0);
SVNEntry entry = area.getEntry(area.getThisDirName(), false);
wcAccess.close();
String url = entry.getURL();
if (entry != null && entry.getURL() != null) {
if (newURL.toString().equals(url)) {
doUpdate(target, externalRevision, SVNDepth.UNKNOWN, true, false);
return;
} else if (entry.getRepositoryRoot() != null) {
if (!SVNPathUtil.isAncestor(entry.getRepositoryRoot(), newURL.toString())) {
SVNRepository repos = createRepository(newURL, null, null, true);
SVNURL reposRoot = repos.getRepositoryRoot(true);
try {
doRelocate(target, entry.getSVNURL(), reposRoot, true);
} catch (SVNException svne) {
if (svne.getErrorMessage().getErrorCode() == SVNErrorCode.WC_INVALID_RELOCATION ||
svne.getErrorMessage().getErrorCode() == SVNErrorCode.CLIENT_INVALID_RELOCATION) {
deleteExternal(target);
target.mkdirs();
doCheckout(newURL, target, externalPegRevision, externalRevision, SVNDepth.INFINITY, false);
return;
}
throw svne;
}
}
doSwitch(target, newURL, externalPegRevision,
externalRevision, SVNDepth.INFINITY, false, true);
return;
}
}
deleteExternal(target);
target.mkdirs();
dispatchEvent(SVNEventFactory.createSVNEvent(target, SVNNodeKind.DIR, null, SVNRepository.INVALID_REVISION, SVNEventAction.UPDATE_EXTERNAL, null, null, null));
doCheckout(newURL, target, externalPegRevision, externalRevision, SVNDepth.INFINITY, false);
return;
}
if (fileType != SVNFileType.DIRECTORY) {
target.mkdirs();
}
dispatchEvent(SVNEventFactory.createSVNEvent(target, SVNNodeKind.DIR, null, SVNRepository.INVALID_REVISION, SVNEventAction.UPDATE_EXTERNAL, null, null, null));
doCheckout(newURL, target, externalPegRevision, externalRevision, SVNDepth.INFINITY, true);
} else {
dispatchEvent(SVNEventFactory.createSVNEvent(target, SVNNodeKind.FILE, null, SVNRepository.INVALID_REVISION,