package org.tmatesoft.svn.core.internal.wc2.ng;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
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.SVNEncodingUtil;
import org.tmatesoft.svn.core.internal.util.SVNHashSet;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.util.SVNURLUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb;
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb.WCDbBaseInfo.BaseInfoField;
import org.tmatesoft.svn.core.internal.wc17.SVNWCContext;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import org.tmatesoft.svn.util.SVNLogType;
import org.tmatesoft.svn.core.internal.wc2.ng.SvnNgOperationRunner;
public class SvnNgLockUtil {
public static SVNURL collectLockInfo(SvnNgOperationRunner opRunner, SVNWCContext context, SvnNgRepositoryAccess wcAccess, Collection<SvnTarget> targets, Map lockInfo, Map lockPaths, boolean lock, boolean stealLock) throws SVNException {
String[] paths = new String[targets.size()];
int i = 0;
for (SvnTarget target : targets) {
paths[i] = target.getFile().getAbsolutePath();
paths[i] = paths[i].replace(File.separatorChar, '/');
i++;
}
Collection<String> condencedPaths = new ArrayList<String>();
String commonParentPath = SVNPathUtil.condencePaths(paths, condencedPaths, false);
if (condencedPaths.isEmpty()) {
condencedPaths.add(SVNPathUtil.tail(commonParentPath));
commonParentPath = SVNPathUtil.removeTail(commonParentPath);
}
if (commonParentPath == null || "".equals(commonParentPath)) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE, "No common parent found, unable to operate on dijoint arguments");
SVNErrorManager.error(err, SVNLogType.WC);
}
paths = (String[]) condencedPaths.toArray(new String[condencedPaths.size()]);
int depth = 0;
for (i = 0; i < paths.length; i++) {
int segments = SVNPathUtil.getSegmentsCount(paths[i]);
if (depth < segments) {
depth = segments;
}
}
for (i = 0; i < paths.length; i++) {
File file = new File(commonParentPath, paths[i]);
SVNURL url = context.getNodeUrl(file);
if (url == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", file);
SVNErrorManager.error(err, SVNLogType.WC);
}
ISVNWCDb.WCDbBaseInfo baseInfo = context.getDb().getBaseInfo(file, BaseInfoField.lock, BaseInfoField.kind);
if (baseInfo.kind != ISVNWCDb.SVNWCDbKind.File) {
SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.WC_NOT_FILE, "The node ''{0}'' is not a file", file);
SVNErrorManager.error(errorMessage, SVNLogType.WC);
}
if (lock) {
SVNRevision revision = stealLock ? SVNRevision.UNDEFINED :
SVNRevision.create(context.getNodeBaseRev(file));
lockInfo.put(url, new LockInfo(file, revision));
} else {
ISVNWCDb.SVNWCDbLock dbLock = baseInfo.lock;
if (!stealLock && dbLock == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_MISSING_LOCK_TOKEN, "''{0}'' is not locked in this working copy", file);
SVNErrorManager.error(err, SVNLogType.WC);
}
lockInfo.put(url, new LockInfo(file, stealLock ? null : dbLock.token));
}
}
opRunner.checkCancelled();
SVNURL[] urls = (SVNURL[]) lockInfo.keySet().toArray(new SVNURL[lockInfo.size()]);
Collection<String> urlPaths = new SVNHashSet();
final SVNURL topURL = SVNURLUtil.condenceURLs(urls, urlPaths, false);
if (urlPaths.isEmpty()) {
urlPaths.add("");
}
if (topURL == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE, "Unable to lock/unlock across multiple repositories");
SVNErrorManager.error(err, SVNLogType.WC);
}
for (Iterator<String> encodedPaths = urlPaths.iterator(); encodedPaths.hasNext();) {
String encodedPath = encodedPaths.next();
SVNURL fullURL = topURL.appendPath(encodedPath, true);
LockInfo info = (LockInfo) lockInfo.get(fullURL);
encodedPath = SVNEncodingUtil.uriDecode(encodedPath);
if (lock) {
if (info.myRevision == SVNRevision.UNDEFINED) {
lockPaths.put(encodedPath, null);
} else {
lockPaths.put(encodedPath, new Long(info.myRevision.getNumber()));
}
} else {
lockPaths.put(encodedPath, info.myToken);
}
}
return topURL;
}
public static class LockInfo {
public LockInfo(File file, SVNRevision rev) {
myFile = file;
myRevision = rev;
}
public LockInfo(File file, String token) {
myFile = file;
myToken = token;
}
private File myFile;
private SVNRevision myRevision;
private String myToken;
public File getFile(){
return myFile;
}
public SVNRevision getRevision(){
return myRevision;
}
public String getToken(){
return myToken;
}
}
}