package org.tmatesoft.svn.core.internal.wc2.ng;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.internal.util.SVNDate;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.util.SVNSkel;
import org.tmatesoft.svn.core.internal.wc.*;
import org.tmatesoft.svn.core.internal.wc17.SVNWCContext;
import org.tmatesoft.svn.core.internal.wc17.SVNWCContext.ConflictInfo;
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb;
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb.SVNWCDbKind;
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb.SVNWCDbStatus;
import org.tmatesoft.svn.core.internal.wc17.db.Structure;
import org.tmatesoft.svn.core.internal.wc17.db.StructureFields.NodeInfo;
import org.tmatesoft.svn.core.internal.wc17.db.SvnWcDbRevert;
import org.tmatesoft.svn.core.wc.*;
import org.tmatesoft.svn.core.wc2.*;
import org.tmatesoft.svn.util.SVNLogType;
public class SvnNgAdd extends SvnNgOperationRunner<Void, SvnScheduleForAddition> {
@Override
protected Void run(SVNWCContext context) throws SVNException {
final Map<File, List<SvnTarget>> rootToTargets = new HashMap<File, List<SvnTarget>>();
for (SvnTarget target : getOperation().getTargets()) {
final File targetFile = target.getFile();
final File root;
final SVNFileType targetType = SVNFileType.getType(target.getFile());
if (targetType == SVNFileType.FILE || !getWcContext().getDb().isWCRoot(targetFile, true)) {
File parentPath = SVNFileUtil.getParentFile(targetFile);
if (getOperation().isAddParents()) {
parentPath = findExistingParent(parentPath);
}
root = getWcContext().getDb().getWCRoot(parentPath);
} else {
root = targetFile;
}
List<SvnTarget> targets = rootToTargets.get(root);
if (targets == null) {
targets = new ArrayList<SvnTarget>();
rootToTargets.put(root, targets);
}
targets.add(target);
}
for (File root : rootToTargets.keySet()) {
final List<SvnTarget> targets = rootToTargets.get(root);
final File lockRoot = getWcContext().acquireWriteLock(root, false, true);
try {
for (SvnTarget target : targets) {
add(target);
}
}
finally {
getWcContext().releaseWriteLock(lockRoot);
}
}
return null;
}
private void add(SvnTarget target) throws SVNException {
if (target.isURL()) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ILLEGAL_TARGET, "''{0}'' is not a local path", target.getURL());
SVNErrorManager.error(err, SVNLogType.WC);
}
File path = target.getFile();
File existingParent = path;
File parentPath = path;
if (!getWcContext().getDb().isWCRoot(path, true)) {
parentPath = SVNFileUtil.getParentFile(path);
existingParent = parentPath;
if (getOperation().isAddParents()) {
existingParent = findExistingParent(parentPath);
}
}
SVNFileType targetType = SVNFileType.getType(path);
if (!getOperation().isAddParents() && getOperation().isMkDir() && targetType != SVNFileType.NONE) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ILLEGAL_TARGET, "Can''t create directory " +
"''{0}'': Cannot create a file when that file already exists.", path);
SVNErrorManager.error(err, SVNLogType.WC);
} else if (getOperation().isMkDir() && getOperation().isAddParents()) {
SVNFileUtil.ensureDirectoryExists(path);
} else if (targetType == SVNFileType.NONE && getOperation().isMkDir()) {
SVNFileUtil.ensureDirectoryExists(path);
}
try {
add(path, parentPath, existingParent);
} catch (SVNException e) {
if (targetType == SVNFileType.NONE) {
SVNFileUtil.deleteAll(path, true);
}
throw e;
}
}
private void add(File path, File parentPath, File existingParentPath) throws SVNException {
if (!existingParentPath.equals(parentPath)) {
String parent = parentPath.getAbsolutePath().replace(File.separatorChar, '/');
String existingParent = existingParentPath.getAbsolutePath().replace(File.separatorChar, '/');
String relativeChildPath = SVNPathUtil.getRelativePath(existingParent, parent);
parentPath = existingParentPath;
for(StringTokenizer components = new StringTokenizer(relativeChildPath, "/"); components.hasMoreTokens();) {
String component = components.nextToken();
checkCancelled();
parentPath = SVNFileUtil.createFilePath(parentPath, component);
SVNFileType pathType = SVNFileType.getType(parentPath);
if (pathType != SVNFileType.NONE && pathType != SVNFileType.DIRECTORY) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_NO_VERSIONED_PARENT,
"''{0}'' prevents creating of '''{1}''", parentPath, path);
SVNErrorManager.error(err, SVNLogType.WC);
}
SVNFileUtil.ensureDirectoryExists(parentPath);
addFromDisk(parentPath, null, true);
}
}
SVNNodeKind kind = SVNFileType.getNodeKind(SVNFileType.getType(path));
try {
if (kind == SVNNodeKind.DIR) {
addDirectory(path, getOperation().getDepth(), !getOperation().isIncludeIgnored());
} else if (kind == SVNNodeKind.FILE) {
addFile(path);
} else if (kind == SVNNodeKind.NONE) {
ConflictInfo conflictInfo = null;
try {
conflictInfo = getWcContext().getConflicted(path, false, false, true);
} catch (SVNException e) {
}
if (conflictInfo != null && conflictInfo.treeConflicted) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_FOUND_CONFLICT,
"''{0}'' is an existing item in conflict; please mark the conflict as resolved before adding a new item here",
path);
SVNErrorManager.error(err, SVNLogType.WC);
}
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_PATH_NOT_FOUND,
"''{0}'' not found", path);
SVNErrorManager.error(err, SVNLogType.WC);
} else {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE,
"Unsupported node kind for path ''{0}''", path);
SVNErrorManager.error(err, SVNLogType.WC);
}
} catch (SVNException e) {
if (!(getOperation().isForce() && e.getErrorMessage().getErrorCode() == SVNErrorCode.ENTRY_EXISTS)) {
throw e;
}
}
}
private void addFile(final File path) throws SVNException {
final boolean special = SVNFileType.getType(path) == SVNFileType.SYMLINK;
SVNProperties properties = null;
if (!special) {
if (getOperation().isApplyAutoProperties()) {
final Map<?, ?> autoProps = getAllAutoProperties(getOperation().getOptions(), path);
if (autoProps != null && !autoProps.isEmpty()) {
properties = SVNProperties.wrap(autoProps);
}
}
} else {
properties = new SVNProperties();
properties.put(SVNProperty.SPECIAL, "*");
}
addFromDisk(path, null, false);
if (properties != null) {
final ISvnAddParameters addParameters = getOperation().getAddParameters() == null ?
ISvnAddParameters.DEFAULT :
getOperation().getAddParameters();
SvnNgPropertiesManager.setAutoProperties(getWcContext(), path, properties, addParameters, new Runnable() {
public void run() {
doRevert(path);
}
});
}
handleEvent(SVNEventFactory.createSVNEvent(path,
SVNNodeKind.FILE,
properties != null ?
properties.getStringValue(SVNProperty.MIME_TYPE) : null, -1,
SVNEventAction.ADD,
SVNEventAction.ADD,
null, null, 1, 1));
}
private Map getAllAutoProperties(ISVNOptions options, File file) throws SVNException {
Map<String, String> allAutoProperties = new HashMap<String, String>();
Map configAutoProperties = SVNPropertiesManager.computeAutoProperties(options, file, null);
if (configAutoProperties != null) {
allAutoProperties.putAll(configAutoProperties);
}
SVNProperties regularProperties;
SVNRevision revision = SVNRevision.WORKING;
File parentFile = SVNFileUtil.getParentFile(file);
final List<SvnInheritedProperties>[] inheritedConfigAutoProperties = new List[1];
do {
SvnGetProperties getProperties = getOperation().getOperationFactory().createGetProperties();
getProperties.setSingleTarget(SvnTarget.fromFile(parentFile, revision));
getProperties.setRevision(revision);
getProperties.setDepth(SVNDepth.EMPTY);
getProperties.setTargetInheritedPropertiesReceiver(new ISvnObjectReceiver<List<SvnInheritedProperties>>() {
public void receive(SvnTarget target, List<SvnInheritedProperties> inheritedProperties) throws SVNException {
inheritedConfigAutoProperties[0] = inheritedProperties;
}
});
try {
regularProperties = getProperties.run();
break;
} catch (SVNException e) {
if (e.getErrorMessage().getErrorCode() != SVNErrorCode.UNVERSIONED_RESOURCE) {
throw e;
}
parentFile = findExistingParent(parentFile);
}
} while (true);
if (inheritedConfigAutoProperties[0] != null) {
for (SvnInheritedProperties inheritedConfigAutoProperty : inheritedConfigAutoProperties[0]) {
SVNProperties inheritedProperties = inheritedConfigAutoProperty.getProperties();
Map<String, SVNPropertyValue> inheritedPropertiesMap = inheritedProperties.asMap();
for (Map.Entry<String, SVNPropertyValue> entry : inheritedPropertiesMap.entrySet()) {
String propertyName = entry.getKey();
if (!SVNProperty.INHERITABLE_AUTO_PROPS.equals(propertyName)) {
continue;
}
SVNPropertyValue propertyValue = entry.getValue();
allAutoProperties.putAll(SvnNgPropertiesManager.getMatchedAutoProperties(file.getName(), SvnNgPropertiesManager.parseAutoProperties(propertyValue, null)));
}
}
}
if (regularProperties != null) {
Map<String, SVNPropertyValue> regularPropertiesMap = regularProperties.asMap();
for (Map.Entry<String, SVNPropertyValue> entry : regularPropertiesMap.entrySet()) {
String propertyName = entry.getKey();
if (!SVNProperty.INHERITABLE_AUTO_PROPS.equals(propertyName)) {
continue;
}
SVNPropertyValue propertyValue = entry.getValue();
allAutoProperties.putAll(SvnNgPropertiesManager.getMatchedAutoProperties(file.getName(), SvnNgPropertiesManager.parseAutoProperties(propertyValue, null)));
}
}
return allAutoProperties;
}
private void doRevert(File path) {
try {
try {
getWcContext().getDb().opRevert(path, SVNDepth.EMPTY);
SvnNgRevert.restore(getWcContext(), path, SVNDepth.EMPTY, false, true, null);
} finally {
SvnWcDbRevert.dropRevertList(getWcContext(), path);
}
} catch (SVNException svne) {
//
}
}
private void addDirectory(File path, SVNDepth depth, boolean refreshIgnores) throws SVNException {
boolean entryExists = false;
checkCancelled();
try {
addFromDisk(path, null, true);
} catch (SVNException e) {
if (!(getOperation().isForce() && e.getErrorMessage().getErrorCode() == SVNErrorCode.ENTRY_EXISTS)) {
throw e;
}
entryExists = true;
}
if (depth.compareTo(SVNDepth.EMPTY) <= 0) {
return;
}
Collection<String> ignorePatterns = null;
if (refreshIgnores) {
ignorePatterns = SvnNgPropertiesManager.getEffectiveIgnores(getWcContext(), path, null);
}
File[] children = SVNFileListUtil.listFiles(path);
for (int i = 0; children != null && i < children.length; i++) {
checkCancelled();
String name = children[i].getName();
if (name.equals(SVNFileUtil.getAdminDirectoryName())) {
continue;
}
if (ignorePatterns != null && SvnNgPropertiesManager.isIgnored(name, ignorePatterns)) {
continue;
}
SVNNodeKind childKind = SVNFileType.getNodeKind(SVNFileType.getType(children[i]));
if (childKind == SVNNodeKind.DIR && depth.compareTo(SVNDepth.IMMEDIATES) >= 0) {
SVNDepth depthBelow = depth;
if (depth == SVNDepth.IMMEDIATES) {
depthBelow = SVNDepth.EMPTY;
}
if (refreshIgnores && !entryExists) {
refreshIgnores = false;
}
addDirectory(children[i], depthBelow, refreshIgnores);
} else if (childKind == SVNNodeKind.FILE && depth.compareTo(SVNDepth.FILES) >= 0) {
try {
addFile(children[i]);
} catch (SVNException e) {
if (!(getOperation().isForce() && e.getErrorMessage().getErrorCode() == SVNErrorCode.ENTRY_EXISTS)) {
throw e;
}
}
}
}
}
public void addFromDisk(File path, SVNProperties props, boolean fireEvent) throws SVNException {
SVNNodeKind kind = checkCanAddNode(path);
checkCanAddtoParent(path);
if (kind == SVNNodeKind.FILE) {
SVNSkel workItem = null;
if (props != null && (props.getSVNPropertyValue(SVNProperty.EXECUTABLE) != null || props.getSVNPropertyValue(SVNProperty.NEEDS_LOCK) != null)) {
workItem = getWcContext().wqBuildSyncFileFlags(path);
}
getWcContext().getDb().opAddFile(path, props, workItem);
if (workItem != null) {
getWcContext().wqRun(path);
}
} else {
getWcContext().getDb().opAddDirectory(path, props, null);
}
if (fireEvent) {
handleEvent(SVNEventFactory.createSVNEvent(path, kind, null, -1, SVNEventAction.ADD,
SVNEventAction.ADD, null, null, 1, 1));
}
}
protected void add(File localAbsPath, SVNDepth depth, SVNURL copyFromUrl, long copyFromRevision, boolean fireEvent) throws SVNException {
CheckCanAddNode checkCanAddNode = checkCanAddNode(localAbsPath, copyFromUrl, copyFromRevision);
SVNNodeKind kind = checkCanAddNode.kind;
boolean dbRowExists = checkCanAddNode.dbRowExists;
boolean isWcRoot = checkCanAddNode.isWcRoot;
CheckCanAddToParent checkCanAddToParent = checkCanAddtoParent(localAbsPath);
SVNURL reposRootUrl = checkCanAddToParent.reposRootUrl;
String reposUuid = checkCanAddToParent.reposUuid;
if (copyFromUrl != null && !SVNPathUtil.isAncestor(reposRootUrl.toString(), copyFromUrl.toString())) {
SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE, "The URL ''{0}'' has a different repository root than its parent", copyFromUrl);
SVNErrorManager.error(errorMessage, SVNLogType.WC);
}
if (isWcRoot) {
ISVNWCDb.WCDbRepositoryInfo repositoryInfo = getWcContext().getDb().scanBaseRepository(localAbsPath, ISVNWCDb.WCDbRepositoryInfo.RepositoryInfoField.relPath, ISVNWCDb.WCDbRepositoryInfo.RepositoryInfoField.rootUrl, ISVNWCDb.WCDbRepositoryInfo.RepositoryInfoField.uuid);
File reposRelPath = repositoryInfo.relPath;
SVNURL innerReposRootUrl = repositoryInfo.rootUrl;
String innerReposUuid = repositoryInfo.uuid;
if (!innerReposUuid.equals(reposUuid) || !reposRootUrl.equals(innerReposRootUrl)) {
SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE,
"Can't schedule the working copy at ''{0}'' from repository ''{1}'' with uuid ''{2}'' " +
"for addition under a working copy from repository ''{3}'' with uuid ''{4}''.",
localAbsPath, innerReposRootUrl, innerReposUuid, reposRootUrl, reposUuid);
SVNErrorManager.error(errorMessage, SVNLogType.WC);
}
SVNURL innerUrl = reposRootUrl.appendPath(SVNFileUtil.getFilePath(reposRelPath), false);
if (!innerUrl.equals(copyFromUrl)) {
SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE, "Can't add ''{0}'' with URL ''{1}'', but with the data from ''{2}''", localAbsPath, copyFromUrl, innerUrl);
SVNErrorManager.error(errorMessage, SVNLogType.WC);
}
}
if (copyFromUrl == null) {
addFromDisk(localAbsPath, null, false);
if (kind == SVNNodeKind.DIR && !dbRowExists) {
boolean ownsLock = getWcContext().getDb().isWCLockOwns(localAbsPath, false);
if (!ownsLock) {
getWcContext().getDb().obtainWCLock(localAbsPath, 0, false);
}
}
} else if (!isWcRoot) {
if (kind == SVNNodeKind.FILE) {
SvnNgReposToWcCopy.addFileToWc(getWcContext(), localAbsPath, null, null, null, null, copyFromUrl, copyFromRevision);
} else {
File reposRelPath = SVNFileUtil.createFilePath(SVNPathUtil.getRelativePath(reposRootUrl.toDecodedString(), copyFromUrl.toDecodedString()));
getWcContext().getDb().opCopyDir(localAbsPath, new SVNProperties(), copyFromRevision, SVNDate.NULL, null,
reposRelPath, reposRootUrl, reposUuid, copyFromRevision, null, false, null, null, null);
}
} else {
integrateNestedWcAsCopy(localAbsPath);
}
if (fireEvent && getWcContext().getEventHandler() != null) {
SVNEvent event = SVNEventFactory.createSVNEvent(localAbsPath, kind, null, -1, SVNEventAction.ADD, SVNEventAction.ADD, null, null);
getWcContext().getEventHandler().handleEvent(event, UNKNOWN);
}
}
private CheckCanAddToParent checkCanAddtoParent(File localAbsPath) throws SVNException {
File parentPath = SVNFileUtil.getParentFile(localAbsPath);
getWcContext().writeCheck(parentPath);
CheckCanAddToParent result = new CheckCanAddToParent();
try {
Structure<NodeInfo> info = getWcContext().getDb().readInfo(parentPath, NodeInfo.status, NodeInfo.kind, NodeInfo.reposRootUrl, NodeInfo.reposUuid);
ISVNWCDb.SVNWCDbStatus status = info.<ISVNWCDb.SVNWCDbStatus>get(NodeInfo.status);
ISVNWCDb.SVNWCDbKind kind = info.<ISVNWCDb.SVNWCDbKind>get(NodeInfo.kind);
result.reposRootUrl = info.get(NodeInfo.reposRootUrl);
result.reposUuid = info.get(NodeInfo.reposUuid);
if (status == SVNWCDbStatus.NotPresent || status == SVNWCDbStatus.Excluded || status == SVNWCDbStatus.ServerExcluded) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND,
"Can''t find parent directory''s node while trying to add ''{0}''", localAbsPath);
SVNErrorManager.error(err, SVNLogType.WC);
}
if (status == SVNWCDbStatus.Deleted) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_SCHEDULE_CONFLICT,
"Can''t add ''{0}'' to a parent directory scheduled for deletion", localAbsPath);
SVNErrorManager.error(err, SVNLogType.WC);
} else if (kind != SVNWCDbKind.Dir) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_SCHEDULE_CONFLICT,
"Can''t schedule an addition of ''{0}'' below a not-directory node", localAbsPath);
SVNErrorManager.error(err, SVNLogType.WC);
}
if (result.reposRootUrl == null || result.reposUuid == null) {
if (status == SVNWCDbStatus.Added) {
ISVNWCDb.WCDbAdditionInfo additionInfo = getWcContext().getDb().scanAddition(parentPath, ISVNWCDb.WCDbAdditionInfo.AdditionInfoField.reposRootUrl, ISVNWCDb.WCDbAdditionInfo.AdditionInfoField.reposUuid);
result.reposRootUrl = additionInfo.reposRootUrl;
result.reposUuid = additionInfo.reposUuid;
} else {
ISVNWCDb.WCDbRepositoryInfo repositoryInfo = getWcContext().getDb().scanBaseRepository(parentPath, ISVNWCDb.WCDbRepositoryInfo.RepositoryInfoField.rootUrl, ISVNWCDb.WCDbRepositoryInfo.RepositoryInfoField.uuid);
result.reposRootUrl = repositoryInfo.rootUrl;
result.reposUuid = repositoryInfo.uuid;
}
}
info.release();
} catch (SVNException e) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND,
"Can''t find parent directory''s node while trying to add ''{0}''", localAbsPath);
SVNErrorManager.error(err, SVNLogType.WC);
}
return result;
}
private CheckCanAddNode checkCanAddNode(File localAbsPath, SVNURL copyFromUrl, long copyFromRevision) throws SVNException {
String name = SVNFileUtil.getFileName(localAbsPath);
assert SVNFileUtil.isAbsolute(localAbsPath);
assert (copyFromUrl == null || SVNRevision.isValidRevisionNumber(copyFromRevision));
if (SVNFileUtil.getAdminDirectoryName().equals(name)) {
SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.ENTRY_FORBIDDEN, "Can't create an entry with a reserved name while trying to add ''{0}''", localAbsPath);
SVNErrorManager.error(errorMessage, SVNLogType.WC);
}
SVNFileType pathType = SVNFileType.getType(localAbsPath);
if (pathType == SVNFileType.NONE) {
SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.WC_PATH_NOT_FOUND, "''{0}'' not found", localAbsPath);
SVNErrorManager.error(errorMessage, SVNLogType.WC);
}
if (pathType == SVNFileType.UNKNOWN) {
SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE, "Unsupported node kind for ''{0}''", localAbsPath);
SVNErrorManager.error(errorMessage, SVNLogType.WC);
}
CheckCanAddNode result = new CheckCanAddNode();
result.kind = SVNFileType.getNodeKind(pathType);
try {
Structure<NodeInfo> nodeInfo = getWcContext().getDb().readInfo(localAbsPath, true, NodeInfo.status, NodeInfo.conflicted);
result.isWcRoot = false;
result.dbRowExists = true;
if (nodeInfo.is(NodeInfo.conflicted)) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_FOUND_CONFLICT,
"''{0}'' is an existing item in conflict; please mark the conflict as resolved before adding a new item here",
localAbsPath);
SVNErrorManager.error(err, SVNLogType.WC);
}
switch(nodeInfo.<ISVNWCDb.SVNWCDbStatus>get(NodeInfo.status)) {
case NotPresent:
break;
case Deleted:
break;
case Normal:
result.isWcRoot = getWcContext().getDb().isWCRoot(localAbsPath);
if (result.isWcRoot && copyFromUrl != null) {
break;
} else if (result.isWcRoot && pathType == SVNFileType.SYMLINK) {
break;
}
// only deal when copy from.
default:
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_EXISTS,
"''{0}'' is already under version control", localAbsPath);
SVNErrorManager.error(err, SVNLogType.WC);
}
nodeInfo.release();
} catch (SVNException e) {
if (e.getErrorMessage().getErrorCode() != SVNErrorCode.WC_PATH_NOT_FOUND) {
throw e;
}
result.dbRowExists = false;
result.isWcRoot = false;
}
return result;
}
private SVNNodeKind checkCanAddNode(File path) throws SVNException {
CheckCanAddNode checkCanAddNode = checkCanAddNode(path, null, -1);
return checkCanAddNode.kind;
}
private File findExistingParent(File parentPath) throws SVNException {
SVNNodeKind kind = getWcContext().readKind(parentPath, false);
if (kind == SVNNodeKind.DIR) {
if (!getWcContext().isNodeStatusDeleted(parentPath)) {
return parentPath;
}
}
if (parentPath.getParentFile() == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_NO_VERSIONED_PARENT);
SVNErrorManager.error(err, SVNLogType.WC);
}
if (SVNFileUtil.getAdminDirectoryName().equals(SVNFileUtil.getFileName(parentPath))) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.RESERVED_FILENAME_SPECIFIED,
"''{0}'' ends in a reserved name", parentPath);
SVNErrorManager.error(err, SVNLogType.WC);
}
parentPath = SVNFileUtil.getParentFile(parentPath);
checkCancelled();
return findExistingParent(parentPath);
}
private void integrateNestedWcAsCopy(File localAbsPath) throws SVNException {
getWcContext().getDb().dropRoot(localAbsPath);
File tempDir = getWcContext().getDb().getWCRootTempDir(localAbsPath);
File movedAbsPath = SVNFileUtil.createUniqueFile(tempDir, "", "", false);
try {
SVNFileUtil.ensureDirectoryExists(movedAbsPath);
File admAbsPath = SVNFileUtil.createFilePath(localAbsPath, SVNFileUtil.getAdminDirectoryName());
File movedAdmAbsPath = SVNFileUtil.createFilePath(movedAbsPath, SVNFileUtil.getAdminDirectoryName());
SVNFileUtil.moveDir(admAbsPath, movedAdmAbsPath);
SvnNgWcToWcCopy svnNgWcToWcCopy = new SvnNgWcToWcCopy();
svnNgWcToWcCopy.copy(getWcContext(), movedAbsPath, localAbsPath, true);
getWcContext().getDb().dropRoot(movedAbsPath);
} finally {
SVNFileUtil.deleteAll(movedAbsPath, null);
}
boolean ownsLock = getWcContext().getDb().isWCLockOwns(localAbsPath, false);
if (!ownsLock) {
getWcContext().getDb().obtainWCLock(localAbsPath, 0, false);
}
}
private static class CheckCanAddNode {
public SVNNodeKind kind;
public boolean dbRowExists;
public boolean isWcRoot;
}
private static class CheckCanAddToParent {
public SVNURL reposRootUrl;
public String reposUuid;
}
}