package org.tmatesoft.svn.core.internal.wc2.ng; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.tmatesoft.svn.core.SVNCancelException; 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.internal.wc.SVNErrorManager; import org.tmatesoft.svn.core.internal.wc.SVNEventFactory; import org.tmatesoft.svn.core.internal.wc17.SVNWCContext; import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb; import org.tmatesoft.svn.core.internal.wc17.db.Structure; import org.tmatesoft.svn.core.internal.wc17.db.StructureFields; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNEvent; import org.tmatesoft.svn.core.wc.SVNEventAction; import org.tmatesoft.svn.core.wc2.SvnMarkReplaced; import org.tmatesoft.svn.core.wc2.SvnTarget; import org.tmatesoft.svn.util.SVNLogType; public class SvnNgMarkReplaced extends SvnNgOperationRunner<Void, SvnMarkReplaced> { @Override protected Void run(SVNWCContext context) throws SVNException { for (SvnTarget target : getOperation().getTargets()) { final File path = target.getFile(); final File lock = getWcContext().acquireWriteLock(path, true, true); try { final ISVNWCDb db = context.getDb(); final SVNWCContext.ScheduleInternalInfo schedule = context.getNodeScheduleInternal(path, true, false); final boolean alreadyReplaced = schedule.schedule == SVNWCContext.SVNWCSchedule.replace; if (!alreadyReplaced) { doReplace(db, path); } } finally { getWcContext().releaseWriteLock(lock); } } return null; } private ISVNWCDb.SVNWCDbKind getKind(ISVNWCDb db, File path) throws SVNException { final Structure<StructureFields.NodeInfo> info = db.readInfo(path, StructureFields.NodeInfo.kind); final ISVNWCDb.SVNWCDbKind kind = info.get(StructureFields.NodeInfo.kind); info.release(); return kind; } private void doReplace(ISVNWCDb db, File path) throws SVNException { if (db.isWCRoot(path)) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_PATH_UNEXPECTED_STATUS, "''{0}'' is the root of a working copy and cannot be replaced", path); SVNErrorManager.error(err, SVNLogType.WC); } final List<File> deletedPaths = markDeletedRecursively(db, path); Collections.sort(deletedPaths); for (File deletedPath : deletedPaths) { markAdded(db, deletedPath); //deleted + added = replaced } } private void markAdded(ISVNWCDb db, File path) throws SVNException { final ISVNWCDb.SVNWCDbKind kind = getKind(db, path); if (kind == ISVNWCDb.SVNWCDbKind.Dir) { db.opAddDirectory(path, null, null); } else if (kind == ISVNWCDb.SVNWCDbKind.File) { db.opAddFile(path, null, null); } final SVNEvent event = SVNEventFactory.createSVNEvent(path, kind == ISVNWCDb.SVNWCDbKind.Dir ? SVNNodeKind.DIR : SVNNodeKind.FILE, null, -1, SVNEventAction.ADD, SVNEventAction.ADD, null, null, 1, 1); handleEvent(event); } private List<File> markDeletedRecursively(ISVNWCDb db, File path) throws SVNException { final List<File> deletedPaths = new ArrayList<File>(); final ISVNEventHandler eventHandler = getOperation().getEventHandler(); db.opDelete(path, null, true, null, null, new ISVNEventHandler() { public void handleEvent(SVNEvent event, double progress) throws SVNException { if (event != null && event.getAction() == SVNEventAction.DELETE) { deletedPaths.add(event.getFile()); } if (eventHandler != null) { eventHandler.handleEvent(event, progress); } } public void checkCancelled() throws SVNCancelException { if (eventHandler != null) { eventHandler.checkCancelled(); } } }); return deletedPaths; } }