public void deleteNode(String path) throws SVNException {
    FSTransactionRoot txnRoot = getTxnRoot();
    FSParentPath parentPath = txnRoot.openPath(path, true, true);
    SVNNodeKind kind = parentPath.getRevNode().getType();
    if (parentPath.getParent() == null) {
      SVNErrorMessage err =
          SVNErrorMessage.create(SVNErrorCode.FS_ROOT_DIR, "The root directory cannot be deleted");
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    if ((txnRoot.getTxnFlags() & FSTransactionRoot.SVN_FS_TXN_CHECK_LOCKS) != 0) {
      allowLockedOperation(myFSFS, path, myAuthor, myLockTokens, true, false);
    }

    makePathMutable(parentPath.getParent(), path);
    txnRoot.deleteEntry(parentPath.getParent().getRevNode(), parentPath.getEntryName());
    txnRoot.removeRevNodeFromCache(parentPath.getAbsPath());
    if (myFSFS.supportsMergeInfo()) {
      long mergeInfoCount = parentPath.getRevNode().getMergeInfoCount();
      if (mergeInfoCount > 0) {
        incrementMergeInfoUpTree(parentPath.getParent(), -mergeInfoCount);
      }
    }
    addChange(
        path,
        parentPath.getRevNode().getId(),
        FSPathChangeKind.FS_PATH_CHANGE_DELETE,
        false,
        false,
        SVNRepository.INVALID_REVISION,
        null,
        kind);
  }
  public void makeCopy(
      FSRevisionRoot fromRoot, String fromPath, String toPath, boolean preserveHistory)
      throws SVNException {
    FSTransactionRoot txnRoot = getTxnRoot();
    String txnId = txnRoot.getTxnID();
    FSRevisionNode fromNode = fromRoot.getRevisionNode(fromPath);

    FSParentPath toParentPath = txnRoot.openPath(toPath, false, true);
    if ((txnRoot.getTxnFlags() & FSTransactionRoot.SVN_FS_TXN_CHECK_LOCKS) != 0) {
      FSCommitter.allowLockedOperation(myFSFS, toPath, myAuthor, myLockTokens, true, false);
    }

    if (toParentPath.getRevNode() != null
        && toParentPath.getRevNode().getId().equals(fromNode.getId())) {
      return;
    }

    FSPathChangeKind changeKind;
    long mergeInfoStart = 0;
    if (toParentPath.getRevNode() != null) {
      changeKind = FSPathChangeKind.FS_PATH_CHANGE_REPLACE;
      if (myFSFS.supportsMergeInfo()) {
        mergeInfoStart = toParentPath.getRevNode().getMergeInfoCount();
      }
    } else {
      changeKind = FSPathChangeKind.FS_PATH_CHANGE_ADD;
    }

    makePathMutable(toParentPath.getParent(), toPath);
    String fromCanonPath = SVNPathUtil.canonicalizeAbsolutePath(fromPath);
    copy(
        toParentPath.getParent().getRevNode(),
        toParentPath.getEntryName(),
        fromNode,
        preserveHistory,
        fromRoot.getRevision(),
        fromCanonPath,
        txnId);

    if (changeKind == FSPathChangeKind.FS_PATH_CHANGE_REPLACE) {
      txnRoot.removeRevNodeFromCache(toParentPath.getAbsPath());
    }

    long mergeInfoEnd = 0;
    if (myFSFS.supportsMergeInfo()) {
      mergeInfoEnd = fromNode.getMergeInfoCount();
      if (mergeInfoStart != mergeInfoEnd) {
        incrementMergeInfoUpTree(toParentPath.getParent(), mergeInfoEnd - mergeInfoStart);
      }
    }

    FSRevisionNode newNode = txnRoot.getRevisionNode(toPath);
    addChange(
        toPath,
        newNode.getId(),
        changeKind,
        false,
        false,
        fromRoot.getRevision(),
        fromCanonPath,
        fromNode.getType());
  }