package org.tmatesoft.svn.core.internal.wc2.ng; import java.io.File; import java.util.List; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.internal.util.SVNSkel; import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; import org.tmatesoft.svn.core.internal.wc.SVNFileType; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; import org.tmatesoft.svn.core.internal.wc17.SVNWCContext; 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.ExternalNodeInfo; import org.tmatesoft.svn.core.internal.wc17.db.StructureFields.NodeInfo; import org.tmatesoft.svn.core.internal.wc17.db.SvnWcDbExternals; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNConflictDescription; import org.tmatesoft.svn.core.wc.SVNStatusType; import org.tmatesoft.svn.core.wc2.ISvnObjectReceiver; import org.tmatesoft.svn.core.wc2.SvnGetStatus; import org.tmatesoft.svn.core.wc2.SvnOperationFactory; import org.tmatesoft.svn.core.wc2.SvnScheduleForRemoval; import org.tmatesoft.svn.core.wc2.SvnStatus; import org.tmatesoft.svn.core.wc2.SvnTarget; import org.tmatesoft.svn.util.SVNLogType; public class SvnNgRemove extends SvnNgOperationRunner<Void, SvnScheduleForRemoval> { @Override protected Void run(SVNWCContext context) throws SVNException { for(SvnTarget target : getOperation().getTargets()) { final File path = target.getFile(); checkCancelled(); final File lockRoot = getWcContext().acquireWriteLock(path, true, true); try { if (!getOperation().isForce() && getOperation().isDeleteFiles()) { checkCanDelete(getOperation().getOperationFactory(), context, path); } if (!getOperation().isDryRun()) { delete(context, path, null, !getOperation().isDeleteFiles(), true, getOperation().getEventHandler()); } } finally { getWcContext().releaseWriteLock(lockRoot); } } return null; } public static void checkCanDelete(SvnOperationFactory opFactory, SVNWCContext context, File path) throws SVNException { Structure<ExternalNodeInfo> info = null; try { info = SvnWcDbExternals.readExternal(context, path, path, ExternalNodeInfo.kind); if (info != null && info.get(ExternalNodeInfo.kind) == SVNWCDbKind.File) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_CANNOT_DELETE_FILE_EXTERNAL, "Cannot remove the external at ''{0}''; please edit or delete the svn:externals property on ''{1}''", path, SVNFileUtil.getParentFile(path)); SVNErrorManager.error(err, SVNLogType.WC); } } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() != SVNErrorCode.WC_PATH_NOT_FOUND) { throw e; } } finally { if (info != null) { info.release(); } } SvnGetStatus status = opFactory.createGetStatus(); status.setSingleTarget(SvnTarget.fromFile(path)); status.setDepth(SVNDepth.INFINITY); status.setReceiver(new ISvnObjectReceiver<SvnStatus>() { public void receive(SvnTarget target, SvnStatus status) throws SVNException { SVNErrorMessage err = null; if (status.getNodeStatus() == SVNStatusType.STATUS_OBSTRUCTED) { err = SVNErrorMessage.create(SVNErrorCode.NODE_UNEXPECTED_KIND, "''{0}'' is in the way of the resource actually under version control", target.getFile()); } else if (!status.isVersioned()) { err = SVNErrorMessage.create(SVNErrorCode.UNVERSIONED_RESOURCE, "''{0}'' is not under version control", target.getFile()); } else if ((status.getNodeStatus() == SVNStatusType.STATUS_ADDED || status.getNodeStatus() == SVNStatusType.STATUS_REPLACED) && status.getTextStatus() == SVNStatusType.STATUS_NORMAL && (status.getPropertiesStatus() == SVNStatusType.STATUS_NONE || status.getPropertiesStatus() == SVNStatusType.STATUS_NORMAL)) { } else if (status.getNodeStatus() != SVNStatusType.STATUS_NORMAL && status.getNodeStatus() != SVNStatusType.STATUS_DELETED && status.getNodeStatus() != SVNStatusType.STATUS_MISSING) { err = SVNErrorMessage.create(SVNErrorCode.CLIENT_MODIFIED, "''{0}'' has local modifications -- commit or revert them first", target.getFile()); } if (err != null) { SVNErrorManager.error(err, SVNLogType.WC); } } }); status.run(); } public static void delete(SVNWCContext context, File path, File movedToAbsPath, boolean keepLocal, boolean deleteUnversioned, ISVNEventHandler handler) throws SVNException { Structure<NodeInfo> info = null; try { info = context.getDb().readInfo(path, NodeInfo.status, NodeInfo.kind, NodeInfo.conflicted); } catch (SVNException e) { if (deleteUnversioned && e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_PATH_NOT_FOUND) { if (SVNFileType.getType(path) == SVNFileType.NONE) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.BAD_FILENAME, "''{0}'' does not exist", path); SVNErrorManager.error(err, SVNLogType.WC); } if (!keepLocal) { SVNFileUtil.deleteAll(path, handler); } return; } throw e; } SVNWCDbStatus status = info.get(NodeInfo.status); if (status == SVNWCDbStatus.Excluded || status == SVNWCDbStatus.NotPresent) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_PATH_NOT_FOUND, "''{0}'' cannot be deleted", path); SVNErrorManager.error(err, SVNLogType.WC); } if (status == SVNWCDbStatus.Normal && info.get(NodeInfo.kind) == SVNWCDbKind.Dir) { if (context.getDb().isWCRoot(path)) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_PATH_UNEXPECTED_STATUS, "''{0}'' is the root of a working copy and cannot be deleted", path); SVNErrorManager.error(err, SVNLogType.WC); } } context.writeCheck(SVNFileUtil.getParentFile(path)); List<SVNConflictDescription> conflicts = null; if (!keepLocal && info.is(NodeInfo.conflicted)) { conflicts = context.getDb().readConflicts(path); } info.release(); SVNSkel workItems = null; //TODO context.getDb().opDelete(path, movedToAbsPath, movedToAbsPath != null || !keepLocal, null, workItems, handler); if (!keepLocal && conflicts != null) { for (SVNConflictDescription conflict : conflicts) { if (conflict.isTextConflict()) { if (conflict.getMergeFiles() != null) { SVNFileUtil.deleteFile(conflict.getMergeFiles().getBaseFile()); SVNFileUtil.deleteFile(conflict.getMergeFiles().getRepositoryFile()); SVNFileUtil.deleteFile(conflict.getMergeFiles().getLocalFile()); } } else if (conflict.isPropertyConflict() && conflict.getMergeFiles() != null) { SVNFileUtil.deleteFile(conflict.getMergeFiles().getRepositoryFile()); } } } if (!keepLocal) { SVNFileUtil.deleteAll(path, handler); } } }