package org.tmatesoft.svn.core.internal.wc2.remote;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.tmatesoft.svn.core.SVNCommitInfo;
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.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNHashMap;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.ISVNCommitPathHandler;
import org.tmatesoft.svn.core.internal.wc.SVNCommitUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.internal.wc.SVNEventFactory;
import org.tmatesoft.svn.core.internal.wc.SVNPropertiesManager;
import org.tmatesoft.svn.core.internal.wc17.SVNWCUtils;
import org.tmatesoft.svn.core.internal.wc2.SvnRemoteOperationRunner;
import org.tmatesoft.svn.core.io.ISVNEditor;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
import org.tmatesoft.svn.core.wc.SVNEventAction;
import org.tmatesoft.svn.core.wc2.SvnCommitItem;
import org.tmatesoft.svn.core.wc2.SvnRemoteDelete;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import org.tmatesoft.svn.util.SVNLogType;
public class SvnRemoteRemoteDelete extends SvnRemoteOperationRunner<SVNCommitInfo, SvnRemoteDelete> {
@Override
protected SVNCommitInfo run() throws SVNException {
if (getOperation().getTargets().size() == 0) {
return SVNCommitInfo.NULL;
}
SVNHashMap reposInfo = new SVNHashMap();
SVNHashMap relPathInfo = new SVNHashMap();
try {
for (SvnTarget target : getOperation().getTargets()) {
SVNURL url = target.getURL();
SVNRepository repository = null;
SVNURL reposRoot = null;
String reposRelPath = null;
ArrayList<String> relPaths;
SVNNodeKind kind;
for (Iterator rootUrls = reposInfo.keySet().iterator(); rootUrls.hasNext(); ) {
reposRoot = (SVNURL) rootUrls.next();
reposRelPath = SVNWCUtils.isChild(reposRoot, url);
if (reposRelPath != null) {
repository = (SVNRepository) reposInfo.get(reposRoot);
relPaths = (ArrayList<String>) relPathInfo.get(reposRoot);
relPaths.add(reposRelPath);
break; //appropriate SVNRepository/root was found, stop searching
}
}
if (repository == null) {
repository = getRepositoryAccess().createRepository(url, null, false);
reposRoot = repository.getRepositoryRoot(true);
repository.setLocation(reposRoot, false);
reposInfo.put(reposRoot, repository);
reposRelPath = SVNWCUtils.isChild(reposRoot, url);
relPaths = new ArrayList<String>();
relPathInfo.put(reposRoot, relPaths);
relPaths.add(reposRelPath);
}
if (reposRelPath == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.RA_ILLEGAL_URL, "URL ''{0}'' not within a repository", url);
SVNErrorManager.error(err, SVNLogType.WC);
}
kind = repository.checkPath(reposRelPath, -1);
if (kind == SVNNodeKind.NONE) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.FS_NOT_FOUND, "URL ''{0}'' does not exist", url);
SVNErrorManager.error(err, SVNLogType.WC);
}
}
SVNPropertiesManager.validateRevisionProperties(getOperation().getRevisionProperties());
SVNCommitInfo info = null;
for (Iterator rootUrls = reposInfo.keySet().iterator(); rootUrls.hasNext(); ) {
SVNURL reposRoot = (SVNURL) rootUrls.next();
SVNRepository repository = (SVNRepository) reposInfo.get(reposRoot);
List<String> paths = (List<String>) relPathInfo.get(reposRoot);
info = singleRepositoryDelete(repository, reposRoot, paths);
if (info != null) {
getOperation().receive(SvnTarget.fromURL(reposRoot), info);
}
}
return info != null ? info : SVNCommitInfo.NULL;
} finally {
// SvnRepositoryAccess won't close repositories that are created with SvnRepositoryAccess#createRepository
// if mayReuse=false, so close all repositories ourselves
for (Object entry : reposInfo.entrySet()) {
SVNRepository svnRepository = (SVNRepository) (((Map.Entry) entry).getValue());
if (svnRepository != null) {
svnRepository.closeSession();
}
}
}
}
private SVNCommitInfo singleRepositoryDelete(SVNRepository repository, SVNURL rootURL, List<String> paths) throws SVNException {
if (paths.isEmpty()) {
paths.add(SVNPathUtil.tail(rootURL.getURIEncodedPath()));
rootURL = rootURL.removePathTail();
}
String commitMessage;
if (getOperation().getCommitHandler() != null) {
SvnCommitItem[] commitItems = new SvnCommitItem[paths.size()];
for (int i = 0; i < commitItems.length; i++) {
String path = (String) paths.get(i);
SvnCommitItem item = new SvnCommitItem();
item.setKind(SVNNodeKind.NONE);
item.setUrl(rootURL.appendPath(path, true));
item.setFlags(SvnCommitItem.DELETE);
commitItems[i] = item;
}
commitMessage = getOperation().getCommitHandler().getCommitMessage(getOperation().getCommitMessage(), commitItems);
if (commitMessage == null) {
return SVNCommitInfo.NULL;
}
}
else {
commitMessage = getOperation().getCommitMessage();
}
commitMessage = commitMessage == null ? "" : SVNCommitUtil.validateCommitMessage(commitMessage);
final String[] pathsArray = new String[paths.size()];
paths.toArray(pathsArray);
final List<String> condencedPaths = new ArrayList<String>();
String commonParentPath = SVNPathUtil.condencePaths(pathsArray, condencedPaths, false);
if (condencedPaths.isEmpty()) {
condencedPaths.add(SVNPathUtil.tail(commonParentPath));
commonParentPath = SVNPathUtil.removeTail(commonParentPath);
}
repository.setLocation(rootURL.appendPath(commonParentPath, false), false);
ISVNEditor commitEditor = repository.getCommitEditor(commitMessage, null, false, getOperation().getRevisionProperties(), null);
ISVNCommitPathHandler deleter = new ISVNCommitPathHandler() {
public boolean handleCommitPath(String commitPath, ISVNEditor commitEditor) throws SVNException {
commitEditor.deleteEntry(commitPath, -1);
return false;
}
};
SVNCommitInfo info;
try {
SVNCommitUtil.driveCommitEditor(deleter, condencedPaths, commitEditor, -1);
info = commitEditor.closeEdit();
} catch (SVNException e) {
try {
commitEditor.abortEdit();
} catch (SVNException inner) {
}
throw e;
}
if (info != null && info.getNewRevision() >= 0) {
handleEvent(SVNEventFactory.createSVNEvent(null, SVNNodeKind.NONE, null, info.getNewRevision(), SVNEventAction.COMMIT_COMPLETED, null, null, null), ISVNEventHandler.UNKNOWN);
}
return info != null ? info : SVNCommitInfo.NULL;
}
}