package org.tmatesoft.svn.core.internal.wc17; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.db.SVNSqlJetStatement; 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.db.*; import org.tmatesoft.svn.core.internal.wc17.db.statement.SVNWCDbSchema; import org.tmatesoft.svn.core.internal.wc17.db.statement.SVNWCDbStatements; import org.tmatesoft.svn.core.internal.wc2.ng.SvnDiffEditor; import org.tmatesoft.svn.core.wc.*; import org.tmatesoft.svn.core.wc2.SvnChecksum; import org.tmatesoft.svn.util.SVNLogType; import java.io.File; import java.io.InputStream; import java.util.List; public class SVNTreeConflictEditor implements ISVNEditor2 { private final SVNOperation operation; private final SVNConflictVersion oldVersion; private final SVNConflictVersion newVersion; private final SVNWCDb db; private final SVNWCDbRoot wcRoot; private final File moveRootDstRelPath; private ISVNEventHandler eventHandler; private File conflictRootRelPath; public SVNTreeConflictEditor(SVNWCDb db, SVNOperation operation, SVNConflictVersion oldVersion, SVNConflictVersion newVersion, SVNWCDbRoot wcRoot, File moveRootDstRelPath) { this.operation = operation; this.oldVersion = oldVersion; this.newVersion = newVersion; this.db = db; this.wcRoot = wcRoot; this.moveRootDstRelPath = moveRootDstRelPath; } public void addDir(String path, List<String> children, SVNProperties props, long replacesRev) throws SVNException { int opDepth = SVNWCUtils.relpathDepth(moveRootDstRelPath); File relPath = SVNFileUtil.createFilePath(path); db.extendParentDelete(wcRoot.getSDb(), wcRoot.getWcId(), relPath, SVNNodeKind.DIR, opDepth); SVNNodeKind oldKind; ISVNWCDb.SVNWCDbKind moveDstKind; File moveDstReposRelPath; try { Structure<StructureFields.NodeInfo> depthInfo = SvnWcDbShared.getDepthInfo(wcRoot, relPath, SVNWCUtils.relpathDepth(moveRootDstRelPath)); moveDstKind = depthInfo.get(StructureFields.NodeInfo.kind); moveDstReposRelPath = depthInfo.get(StructureFields.NodeInfo.reposRelPath); oldKind = moveDstKind == ISVNWCDb.SVNWCDbKind.Dir ? SVNNodeKind.DIR : SVNNodeKind.FILE; } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_PATH_NOT_FOUND) { oldKind = SVNNodeKind.NONE; moveDstReposRelPath = null; } else { throw e; } } boolean isConflicted = checkTreeConflict(relPath, oldKind, SVNNodeKind.DIR, moveDstReposRelPath, SVNConflictAction.ADD); if (isConflicted) { return; } SVNEventAction action = SVNEventAction.ADD; File absPath = SVNFileUtil.createFilePath(wcRoot.getAbsPath(), relPath); oldKind = SVNFileType.getNodeKind(SVNFileType.getType(absPath)); if (oldKind == SVNNodeKind.FILE) { markTreeConflict(relPath, oldVersion, newVersion, moveRootDstRelPath, operation, oldKind, SVNNodeKind.DIR, moveDstReposRelPath, SVNConflictReason.UNVERSIONED, SVNConflictAction.ADD, null); conflictRootRelPath = relPath; action = SVNEventAction.TREE_CONFLICT; isConflicted = true; } else if (oldKind == SVNNodeKind.NONE) { SVNSkel workItem = SVNWCContext.wqBuildDirInstall(db, absPath); db.wqAdd(wcRoot.getAbsPath(), workItem); } else if (oldKind == SVNNodeKind.DIR) { } if (!isConflicted) { SVNWCDb.updateMoveListAdd(wcRoot, relPath, action, SVNNodeKind.DIR, SVNStatusType.INAPPLICABLE, SVNStatusType.INAPPLICABLE); } } public void addFile(String path, SvnChecksum checksum, InputStream contents, SVNProperties props, long replacesRev) throws SVNException { File relPath = SVNFileUtil.createFilePath(path); int opDepth = SVNWCUtils.relpathDepth(moveRootDstRelPath); db.extendParentDelete(wcRoot.getSDb(), wcRoot.getWcId(), relPath, SVNNodeKind.FILE, opDepth); SVNNodeKind oldKind; File moveDstReposRelPath = null; try { Structure<StructureFields.NodeInfo> depthInfo = SvnWcDbShared.getDepthInfo(wcRoot, relPath, SVNWCUtils.relpathDepth(moveRootDstRelPath)); ISVNWCDb.SVNWCDbKind moveDstKind = depthInfo.get(StructureFields.NodeInfo.kind); moveDstReposRelPath = depthInfo.get(StructureFields.NodeInfo.reposRelPath); oldKind = moveDstKind == ISVNWCDb.SVNWCDbKind.Dir ? SVNNodeKind.DIR : SVNNodeKind.FILE; } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_PATH_NOT_FOUND) { oldKind = SVNNodeKind.NONE; moveDstReposRelPath = null; } else { throw e; } } boolean isConflicted = checkTreeConflict(relPath, oldKind, SVNNodeKind.FILE, moveDstReposRelPath, SVNConflictAction.ADD); if (isConflicted) { return; } File absPath = SVNFileUtil.createFilePath(wcRoot.getAbsPath(), relPath); oldKind = SVNFileType.getNodeKind(SVNFileType.getType(absPath)); if (oldKind != SVNNodeKind.NONE) { markTreeConflict(relPath, oldVersion, newVersion, moveRootDstRelPath, operation, oldKind, SVNNodeKind.FILE, moveDstReposRelPath, SVNConflictReason.UNVERSIONED, SVNConflictAction.ADD, null); conflictRootRelPath = relPath; } SVNSkel workItem = SVNWCContext.wqBuildFileInstall(db, SVNFileUtil.createFilePath(wcRoot.getAbsPath(), relPath), null, false, true); db.wqAdd(wcRoot.getAbsPath(), workItem); SVNWCDb.updateMoveListAdd(wcRoot, relPath, SVNEventAction.UPDATE_ADD, SVNNodeKind.FILE, SVNStatusType.INAPPLICABLE, SVNStatusType.INAPPLICABLE); } public void addSymlink(String path, String target, SVNProperties props, long replacesRev) throws SVNException { SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE); SVNErrorManager.error(errorMessage, SVNLogType.WC); } public void addAbsent(String path, SVNNodeKind kind, long replacesRev) throws SVNException { SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE); SVNErrorManager.error(errorMessage, SVNLogType.WC); } public void alterDir(String path, long revision, List<String> children, SVNProperties props) throws SVNException { assert revision == oldVersion.getPegRevision(); File dstRelPath = SVNFileUtil.createFilePath(path); WorkingNodeVersion oldNodeVersion = new WorkingNodeVersion(); WorkingNodeVersion newNodeVersion = new WorkingNodeVersion(); Structure<StructureFields.NodeInfo> depthInfo = SvnWcDbShared.getDepthInfo(wcRoot, dstRelPath, SVNWCUtils.relpathDepth(moveRootDstRelPath)); ISVNWCDb.SVNWCDbStatus status = depthInfo.get(StructureFields.NodeInfo.status); ISVNWCDb.SVNWCDbKind moveDstKind = depthInfo.get(StructureFields.NodeInfo.kind); File moveDstReposRelPath = depthInfo.get(StructureFields.NodeInfo.reposRelPath); long moveDstRevision = depthInfo.lng(StructureFields.NodeInfo.revision); oldNodeVersion.checksum = depthInfo.get(StructureFields.NodeInfo.checksum); oldNodeVersion.props = depthInfo.get(StructureFields.NodeInfo.propsMod); if ((status == ISVNWCDb.SVNWCDbStatus.Deleted) && moveDstReposRelPath != null) { status = ISVNWCDb.SVNWCDbStatus.NotPresent; } assert(moveDstRevision == revision || status == ISVNWCDb.SVNWCDbStatus.NotPresent); assert(moveDstKind == ISVNWCDb.SVNWCDbKind.Dir); boolean isConflicted = checkTreeConflict(dstRelPath, moveDstKind == ISVNWCDb.SVNWCDbKind.Dir ? SVNNodeKind.DIR : SVNNodeKind.FILE, SVNNodeKind.DIR, moveDstReposRelPath, SVNConflictAction.EDIT); if (isConflicted) { return; } oldNodeVersion.locationAndKind = oldVersion; newNodeVersion.locationAndKind = newVersion; newNodeVersion.checksum = null; newNodeVersion.props = props != null ? props : oldNodeVersion.props; if (props != null) { File dstAbsPath = SVNFileUtil.createFilePath(wcRoot.getAbsPath(), dstRelPath); UpdateWorkingProps updateWorkingProps = updateWorkingProps(null, dstAbsPath, oldNodeVersion, newNodeVersion); SVNSkel conflictSkel = updateWorkingProps.conflictSkel; SVNProperties propChanges = updateWorkingProps.propChanges; SVNProperties actualProps = updateWorkingProps.actualProps; SVNStatusType propState = updateWorkingProps.propState; if (conflictSkel != null) { SVNSkel workItems = createConflictMarkers(dstAbsPath, moveDstReposRelPath, conflictSkel, operation, oldNodeVersion, newNodeVersion, SVNNodeKind.DIR); db.markConflictInternal(wcRoot, dstRelPath, conflictSkel); db.wqAdd(wcRoot.getAbsPath(), workItems); } SVNWCDb.updateMoveListAdd(wcRoot, dstRelPath, SVNEventAction.UPDATE_UPDATE, SVNNodeKind.DIR, SVNStatusType.INAPPLICABLE, propState); } } public void alterFile(String path, long expectedMoveDstRevision, SVNProperties newProps, SvnChecksum newChecksum, InputStream newContents) throws SVNException { WorkingNodeVersion oldNodeVersion = new WorkingNodeVersion(); WorkingNodeVersion newNodeVersion = new WorkingNodeVersion(); File dstRelPath = SVNFileUtil.createFilePath(path); Structure<StructureFields.NodeInfo> depthInfo = SvnWcDbShared.getDepthInfo(wcRoot, dstRelPath, SVNWCUtils.relpathDepth(moveRootDstRelPath), StructureFields.NodeInfo.status, StructureFields.NodeInfo.kind, StructureFields.NodeInfo.revision, StructureFields.NodeInfo.reposRelPath, StructureFields.NodeInfo.checksum, StructureFields.NodeInfo.propsMod); ISVNWCDb.SVNWCDbStatus status = depthInfo.get(StructureFields.NodeInfo.status); ISVNWCDb.SVNWCDbKind moveDstKind = depthInfo.get(StructureFields.NodeInfo.kind); long moveDstRevision = depthInfo.lng(StructureFields.NodeInfo.revision); File moveDstReposRelPath = depthInfo.get(StructureFields.NodeInfo.reposRelPath); oldNodeVersion.checksum = depthInfo.get(StructureFields.NodeInfo.checksum); oldNodeVersion.props = depthInfo.get(StructureFields.NodeInfo.propsMod); if (status == ISVNWCDb.SVNWCDbStatus.Deleted && moveDstReposRelPath != null) { status = ISVNWCDb.SVNWCDbStatus.NotPresent; } assert moveDstRevision == expectedMoveDstRevision || status == ISVNWCDb.SVNWCDbStatus.NotPresent; assert moveDstKind == ISVNWCDb.SVNWCDbKind.File; boolean isConflicted = checkTreeConflict(dstRelPath, moveDstKind == ISVNWCDb.SVNWCDbKind.Dir ? SVNNodeKind.DIR : SVNNodeKind.FILE, SVNNodeKind.FILE, moveDstReposRelPath, SVNConflictAction.EDIT); if (isConflicted) { return; } oldNodeVersion.locationAndKind = oldVersion; newNodeVersion.locationAndKind = newVersion; newNodeVersion.checksum = newChecksum != null ? newChecksum : oldNodeVersion.checksum; newNodeVersion.props = newProps != null ? newProps : oldNodeVersion.props; if (!SvnChecksum.match(newChecksum, oldNodeVersion.checksum) || newProps != null) { updateWorkingFile(dstRelPath, moveDstReposRelPath, operation, oldNodeVersion, newNodeVersion); } } public void alterSymlink(String path, long revision, SVNProperties props, String target) throws SVNException { SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE); SVNErrorManager.error(errorMessage, SVNLogType.WC); } public void delete(String path, long revision) throws SVNException { File relPath = SVNFileUtil.createFilePath(path); int opDepth = SVNWCUtils.relpathDepth(moveRootDstRelPath); boolean mustDeleteWorkingNode = false; File localAbsPath = SVNFileUtil.createFilePath(wcRoot.getAbsPath(), relPath); File parentRelPath = SVNFileUtil.getFileDir(relPath); Structure<StructureFields.NodeInfo> depthInfo = SvnWcDbShared.getDepthInfo(wcRoot, relPath, SVNWCUtils.relpathDepth(moveRootDstRelPath), StructureFields.NodeInfo.kind, StructureFields.NodeInfo.reposRelPath); ISVNWCDb.SVNWCDbKind moveDstKind = depthInfo.get(StructureFields.NodeInfo.kind); File moveDstReposRelPath = depthInfo.get(StructureFields.NodeInfo.reposRelPath); boolean isConflicted = checkTreeConflict(relPath, moveDstKind == ISVNWCDb.SVNWCDbKind.Dir ? SVNNodeKind.DIR : SVNNodeKind.FILE, SVNNodeKind.UNKNOWN, moveDstReposRelPath, SVNConflictAction.DELETE); if (!isConflicted) { SVNWCContext context = new SVNWCContext(db, eventHandler); SVNWCContext.TreeLocalModsInfo treeLocalModsInfo = context.hasLocalMods(localAbsPath, localAbsPath); boolean isModified = treeLocalModsInfo.modificationsFound; boolean isAllDeletes = !treeLocalModsInfo.nonDeleteModificationsFound; if (isModified) { SVNConflictReason reason; if (!isAllDeletes) { SVNSqlJetStatement stmt = wcRoot.getSDb().getStatement(SVNWCDbStatements.UPDATE_OP_DEPTH_RECURSIVE); try { stmt.bindf("isii", wcRoot.getWcId(), relPath, opDepth, SVNWCUtils.relpathDepth(relPath)); stmt.done(); } finally { stmt.reset(); } reason = SVNConflictReason.EDITED; } else { SVNSqlJetStatement stmt = wcRoot.getSDb().getStatement(SVNWCDbStatements.DELETE_WORKING_OP_DEPTH_ABOVE); try { stmt.bindf("isi", wcRoot.getWcId(), relPath, opDepth); stmt.done(); } finally { stmt.reset(); } reason = SVNConflictReason.DELETED; mustDeleteWorkingNode = true; } isConflicted = true; markTreeConflict(relPath, oldVersion, newVersion, moveRootDstRelPath, operation, moveDstKind == ISVNWCDb.SVNWCDbKind.Dir ? SVNNodeKind.DIR : SVNNodeKind.FILE, SVNNodeKind.NONE, moveDstReposRelPath, reason, SVNConflictAction.DELETE, null); conflictRootRelPath = relPath; } } ISVNWCDb.SVNWCDbKind delKind; SVNSqlJetStatement stmt; if (!isConflicted || mustDeleteWorkingNode) { stmt = wcRoot.getSDb().getStatement(SVNWCDbStatements.SELECT_CHILDREN_OP_DEPTH); try { stmt.bindf("isi", wcRoot.getWcId(), relPath, opDepth); boolean haveRow = stmt.next(); while (haveRow) { delKind = SvnWcDbStatementUtil.getColumnKind(stmt, SVNWCDbSchema.NODES__Fields.kind); File delAbsPath = SVNFileUtil.createFilePath(wcRoot.getAbsPath(), stmt.getColumnString(SVNWCDbSchema.NODES__Fields.local_relpath)); SVNSkel workItem; if (delKind == ISVNWCDb.SVNWCDbKind.Dir) { workItem = SVNWCContext.wqBuildDirRemove(db, wcRoot.getAbsPath(), delAbsPath, false); } else { workItem = SVNWCContext.wqBuildFileRemove(db, wcRoot.getAbsPath(), delAbsPath); } db.wqAdd(wcRoot.getAbsPath(), workItem); haveRow = stmt.next(); } } finally { stmt.reset(); } depthInfo = SvnWcDbShared.getDepthInfo(wcRoot, relPath, opDepth, StructureFields.NodeInfo.kind); delKind = depthInfo.get(StructureFields.NodeInfo.kind); SVNSkel workItem; if (delKind == ISVNWCDb.SVNWCDbKind.Dir) { workItem = SVNWCContext.wqBuildDirRemove(db, wcRoot.getAbsPath(), localAbsPath, false); } else { workItem = SVNWCContext.wqBuildFileRemove(db, wcRoot.getAbsPath(), localAbsPath); } db.wqAdd(wcRoot.getAbsPath(), workItem); if (!isConflicted) { SVNWCDb.updateMoveListAdd(wcRoot, relPath, SVNEventAction.UPDATE_DELETE, delKind == ISVNWCDb.SVNWCDbKind.Dir ? SVNNodeKind.DIR : SVNNodeKind.FILE, SVNStatusType.INAPPLICABLE, SVNStatusType.INAPPLICABLE); } } int opDepthBelow = 0; boolean haveRow; stmt = wcRoot.getSDb().getStatement(SVNWCDbStatements.SELECT_HIGHEST_WORKING_NODE); try { stmt.bindf("isi", wcRoot.getWcId(), parentRelPath, opDepth); haveRow = stmt.next(); if (haveRow) { opDepthBelow = (int) stmt.getColumnLong(SVNWCDbSchema.NODES__Fields.op_depth); } } finally { stmt.reset(); } if (haveRow) { stmt = wcRoot.getSDb().getStatement(SVNWCDbStatements.DELETE_NO_LOWER_LAYER); try { stmt.bindf("isii", wcRoot.getWcId(), parentRelPath, opDepth, opDepthBelow); stmt.done(); } finally { stmt.reset(); } stmt = wcRoot.getSDb().getStatement(SVNWCDbStatements.REPLACE_WITH_BASE_DELETED); try { stmt.bindf("isi", wcRoot.getWcId(), relPath, opDepth); } finally { stmt.reset(); } } else { stmt = wcRoot.getSDb().getStatement(SVNWCDbStatements.DELETE_WORKING_OP_DEPTH); try { stmt.bindf("isi", wcRoot.getWcId(), relPath, opDepth); stmt.done(); } finally { stmt.reset(); } } db.retractParentDelete(wcRoot.getSDb(), wcRoot.getWcId(), relPath, opDepth); } public void copy(String srcPath, long srcRevision, String dstPath, long replacesRev) throws SVNException { SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE); SVNErrorManager.error(errorMessage, SVNLogType.WC); } public void move(String srcPath, long srcRevision, String dstPath, long replacesRev) throws SVNException { SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE); SVNErrorManager.error(errorMessage, SVNLogType.WC); } public void rotate(List<String> relPaths, List<String> revisions) throws SVNException { SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE); SVNErrorManager.error(errorMessage, SVNLogType.WC); } public void complete() { } public void abort() { } private static class WorkingNodeVersion { SVNConflictVersion locationAndKind; SVNProperties props; SvnChecksum checksum; } private boolean checkTreeConflict(File localRelPath, SVNNodeKind oldKind, SVNNodeKind newKind, File oldReposRelPath, SVNConflictAction action) throws SVNException { int dstOpDepth = SVNWCUtils.relpathDepth(moveRootDstRelPath); int opDepth = 0; if (this.conflictRootRelPath != null) { if (SVNPathUtil.isAncestor(SVNFileUtil.getFilePath(this.conflictRootRelPath), SVNFileUtil.getFilePath(localRelPath))) { return true; } this.conflictRootRelPath = null; } SVNSqlJetStatement stmt = wcRoot.getSDb().getStatement(SVNWCDbStatements.SELECT_LOWEST_WORKING_NODE); boolean haveRow; try { stmt.bindf("isi", wcRoot.getWcId(), localRelPath, dstOpDepth); haveRow = stmt.next(); if (haveRow) { opDepth = (int) stmt.getColumnLong(SVNWCDbSchema.NODES__Fields.op_depth); } } finally { stmt.reset(); } if (!haveRow) { return false; } boolean isConflicted = true; File conflictRootRelPath = localRelPath; while (SVNWCUtils.relpathDepth(conflictRootRelPath) > opDepth) { conflictRootRelPath = SVNFileUtil.getFileDir(conflictRootRelPath); oldKind = newKind = SVNNodeKind.DIR; if (oldReposRelPath != null) { oldReposRelPath = SVNFileUtil.getFileDir(oldReposRelPath); } action = SVNConflictAction.EDIT; } SVNWCDb.BaseMovedTo movedTo = db.opDepthMovedTo(dstOpDepth, wcRoot, conflictRootRelPath); File moveDstRelPath = movedTo.moveDstRelPath; File moveSrcOpRootRelPath = movedTo.moveSrcOpRootRelPath; markTreeConflict(conflictRootRelPath, oldVersion, newVersion, moveRootDstRelPath, operation, oldKind, newKind, oldReposRelPath, moveDstRelPath != null ? SVNConflictReason.MOVED_AWAY : SVNConflictReason.DELETED, action, moveSrcOpRootRelPath); this.conflictRootRelPath = conflictRootRelPath; return isConflicted; } private UpdateWorkingProps updateWorkingProps(SVNSkel conflictSkel, File localAbsPath, WorkingNodeVersion oldNodeVersion, WorkingNodeVersion newNodeVersion) throws SVNException { UpdateWorkingProps updateWorkingProps = new UpdateWorkingProps(); if (oldNodeVersion.props == null) { oldNodeVersion.props = new SVNProperties(); } if (newNodeVersion.props == null) { newNodeVersion.props = new SVNProperties(); } updateWorkingProps.actualProps = db.readProperties(localAbsPath); updateWorkingProps.propChanges = SvnDiffEditor.computePropDiff(oldNodeVersion.props, newNodeVersion.props); SVNWCContext context = new SVNWCContext(db, eventHandler); SVNWCContext.MergePropertiesInfo mergePropertiesInfo = new SVNWCContext.MergePropertiesInfo(); mergePropertiesInfo.conflictSkel = conflictSkel; mergePropertiesInfo = context.mergeProperties3(mergePropertiesInfo, localAbsPath, oldNodeVersion.props, oldNodeVersion.props, updateWorkingProps.actualProps, updateWorkingProps.propChanges); updateWorkingProps.conflictSkel = mergePropertiesInfo.conflictSkel; SVNProperties newActualProperties = mergePropertiesInfo.newActualProperties; updateWorkingProps.propState = mergePropertiesInfo.mergeOutcome; SVNProperties newPropChanges = SvnDiffEditor.computePropDiff(newNodeVersion.props, newActualProperties); if (newPropChanges.size() > 0) { newActualProperties = null; } db.opSetProps(localAbsPath, newActualProperties, null, SVNWCContext.hasMagicProperty(updateWorkingProps.propChanges), null); return updateWorkingProps; } private static class UpdateWorkingProps { SVNStatusType propState; SVNSkel conflictSkel; SVNProperties propChanges; SVNProperties actualProps; } private SVNSkel createConflictMarkers(File localAbsPath, File reposRelPath, SVNSkel conflictSkel, SVNOperation operation, WorkingNodeVersion oldNodeVersion, WorkingNodeVersion newNodeVersion, SVNNodeKind kind) throws SVNException { File part = SVNFileUtil.skipAncestor(SVNFileUtil.createFilePath(oldVersion.getPath()), reposRelPath); SVNConflictVersion originalVersion = new SVNConflictVersion(oldNodeVersion.locationAndKind.getRepositoryRoot(), SVNFileUtil.getFilePath(reposRelPath), oldNodeVersion.locationAndKind.getPegRevision(), kind); SVNConflictVersion conflictedVersion = new SVNConflictVersion(newNodeVersion.locationAndKind.getRepositoryRoot(), SVNPathUtil.append(oldNodeVersion.locationAndKind.getPath(), SVNFileUtil.getFilePath(part)), newNodeVersion.locationAndKind.getPegRevision(), kind); if (operation == SVNOperation.UPDATE) { SvnWcDbConflicts.conflictSkelOpUpdate(conflictSkel, originalVersion, conflictedVersion); } else { SvnWcDbConflicts.conflictSkelOpSwitch(conflictSkel, originalVersion, conflictedVersion); } SVNWCContext context = new SVNWCContext(db, eventHandler); return context.conflictCreateMarker(conflictSkel, localAbsPath); } private void updateWorkingFile(File localRelPath, File reposRelPath, SVNOperation operation, WorkingNodeVersion oldNodeVersion, WorkingNodeVersion newNodeVersion) throws SVNException { SVNSkel workItems = null; File localAbsPath = SVNFileUtil.createFilePath(wcRoot.getAbsPath(), localRelPath); SVNStatusType contentState; UpdateWorkingProps updateWorkingProps = updateWorkingProps(null, localAbsPath, oldNodeVersion, newNodeVersion); SVNSkel conflictSkel = updateWorkingProps.conflictSkel; SVNStatusType propState = updateWorkingProps.propState; SVNProperties propChanges = updateWorkingProps.propChanges; SVNProperties actualProps = updateWorkingProps.actualProps; if (!SvnChecksum.match(newNodeVersion.checksum, oldNodeVersion.checksum)) { SVNWCContext context = new SVNWCContext(db, eventHandler); boolean isLocallyModified = context.isTextModified(localAbsPath, false); if (!isLocallyModified) { SVNSkel workItem = context.wqBuildFileInstall(localAbsPath, null, false, true); workItems = SVNWCContext.wqMerge(workItems, workItem); contentState = SVNStatusType.CHANGED; } else { File oldPristineAbsPath = SvnWcDbPristines.getPristinePath(wcRoot, oldNodeVersion.checksum); File newPristineAbsPath = SvnWcDbPristines.getPristinePath(wcRoot, newNodeVersion.checksum); SVNWCContext.MergeInfo mergeInfo = context.merge(workItems, conflictSkel, oldPristineAbsPath, newPristineAbsPath, localAbsPath, localAbsPath, null, null, null, actualProps, false, null, propChanges); conflictSkel = mergeInfo.conflictSkel; SVNSkel workItem = mergeInfo.workItems; SVNStatusType mergeOutcome = mergeInfo.mergeOutcome; workItems = SVNWCContext.wqMerge(workItems, workItem); if (mergeOutcome == SVNStatusType.CONFLICTED) { contentState = SVNStatusType.CONFLICTED; } else { contentState = SVNStatusType.MERGED; } } } else { contentState = SVNStatusType.UNCHANGED; } if (conflictSkel != null) { SVNSkel workItem = createConflictMarkers(localAbsPath, reposRelPath, conflictSkel, operation, oldNodeVersion, newNodeVersion, SVNNodeKind.FILE); db.markConflictInternal(wcRoot, localRelPath, conflictSkel); workItems = SVNWCContext.wqMerge(workItems, workItem); } db.wqAdd(wcRoot.getAbsPath(), workItems); SVNWCDb.updateMoveListAdd(wcRoot, localRelPath, SVNEventAction.UPDATE_UPDATE, SVNNodeKind.FILE, contentState, propState); } private void markTreeConflict(File localRelPath, SVNConflictVersion oldVersion, SVNConflictVersion newVersion, File moveRootDstRelPath, SVNOperation operation, SVNNodeKind oldKind, SVNNodeKind newKind, File oldReposRelPath, SVNConflictReason reason, SVNConflictAction action, File moveSrcOpRootRelPath) throws SVNException { File moveSrcOpRootAbsPath = moveSrcOpRootRelPath != null ? SVNFileUtil.createFilePath(wcRoot.getAbsPath(), moveSrcOpRootRelPath) : null; File oldReposRelPathPart = oldReposRelPath != null ? SVNFileUtil.skipAncestor(SVNFileUtil.createFilePath(oldVersion.getPath()), oldReposRelPath) : null; File newReposRelPath = oldReposRelPathPart != null ? SVNFileUtil.createFilePath(SVNFileUtil.createFilePath(newVersion.getPath()), oldReposRelPathPart) : null; if (newReposRelPath == null) { newReposRelPath = SVNFileUtil.createFilePath(newVersion.getPath(), SVNFileUtil.getFilePath(SVNFileUtil.skipAncestor(moveRootDstRelPath, localRelPath))); } SVNSkel conflictSkel; try { conflictSkel = db.readConflictInternal(wcRoot, localRelPath); } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_PATH_NOT_FOUND) { conflictSkel = null; } else { throw e; } } if (conflictSkel != null) { Structure<SvnWcDbConflicts.ConflictInfo> conflictInfoStructure = SvnWcDbConflicts.readConflictInfo(conflictSkel); SVNOperation conflictOperation = conflictInfoStructure.get(SvnWcDbConflicts.ConflictInfo.conflictOperation); boolean treeConflicted = conflictInfoStructure.is(SvnWcDbConflicts.ConflictInfo.treeConflicted); if (conflictOperation != SVNOperation.UPDATE && conflictOperation != SVNOperation.SWITCH) { SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.WC_CONFLICT_RESOLVER_FAILURE, "'{0}' already in conflict", localRelPath); SVNErrorManager.error(errorMessage, SVNLogType.WC); } if (treeConflicted) { Structure<SvnWcDbConflicts.TreeConflictInfo> treeConflictInfoStructure = SvnWcDbConflicts.readTreeConflict(db, wcRoot.getAbsPath(), conflictSkel); SVNConflictReason existingReason = treeConflictInfoStructure.get(SvnWcDbConflicts.TreeConflictInfo.localChange); SVNConflictAction existingAction = treeConflictInfoStructure.get(SvnWcDbConflicts.TreeConflictInfo.incomingChange); File existingAbsPath = treeConflictInfoStructure.get(SvnWcDbConflicts.TreeConflictInfo.moveSrcOpRootAbsPath); if (reason != existingReason || action != existingAction || (reason == SVNConflictReason.MOVED_AWAY && !moveSrcOpRootRelPath.equals(SVNFileUtil.skipAncestor(wcRoot.getAbsPath(), existingAbsPath)))) { SVNErrorMessage errorMessage = SVNErrorMessage.create(SVNErrorCode.WC_CONFLICT_RESOLVER_FAILURE, "'{0}' already in conflict", localRelPath); SVNErrorManager.error(errorMessage, SVNLogType.WC); } return; } } else { conflictSkel = SvnWcDbConflicts.createConflictSkel(); } SvnWcDbConflicts.addTreeConflict(conflictSkel, db, SVNFileUtil.createFilePath(wcRoot.getAbsPath(), localRelPath), reason, action, moveSrcOpRootAbsPath); SVNConflictVersion conflictOldVersion; SVNConflictVersion conflictNewVersion; if (reason != SVNConflictReason.UNVERSIONED && oldReposRelPath != null) { conflictOldVersion = new SVNConflictVersion(oldVersion.getRepositoryRoot(), SVNFileUtil.getFilePath(oldReposRelPath), oldVersion.getPegRevision(), oldKind); } else { conflictOldVersion = null; } conflictNewVersion = new SVNConflictVersion(newVersion.getRepositoryRoot(), SVNFileUtil.getFilePath(newReposRelPath), newVersion.getPegRevision(), newKind); if (operation == SVNOperation.UPDATE) { SvnWcDbConflicts.conflictSkelOpUpdate(conflictSkel, conflictOldVersion, conflictNewVersion); } else { assert operation == SVNOperation.SWITCH; SvnWcDbConflicts.conflictSkelOpSwitch(conflictSkel, conflictOldVersion, conflictNewVersion); } db.markConflictInternal(wcRoot, localRelPath, conflictSkel); SVNWCDb.updateMoveListAdd(wcRoot, localRelPath, SVNEventAction.TREE_CONFLICT, newKind, SVNStatusType.INAPPLICABLE, SVNStatusType.INAPPLICABLE); } }