Esempio n. 1
0
  public void makeDir(String path) throws SVNException {
    SVNPathUtil.checkPathIsValid(path);
    FSTransactionRoot txnRoot = getTxnRoot();
    String txnId = txnRoot.getTxnID();
    FSParentPath parentPath = txnRoot.openPath(path, false, true);

    if (parentPath.getRevNode() != null) {
      SVNErrorManager.error(FSErrors.errorAlreadyExists(txnRoot, path, myFSFS), SVNLogType.FSFS);
    }

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

    makePathMutable(parentPath.getParent(), path);
    FSRevisionNode subDirNode =
        makeEntry(
            parentPath.getParent().getRevNode(),
            parentPath.getParent().getAbsPath(),
            parentPath.getEntryName(),
            true,
            txnId);

    txnRoot.putRevNodeToCache(parentPath.getAbsPath(), subDirNode);
    addChange(
        path,
        subDirNode.getId(),
        FSPathChangeKind.FS_PATH_CHANGE_ADD,
        false,
        false,
        SVNRepository.INVALID_REVISION,
        null,
        SVNNodeKind.DIR);
  }
Esempio n. 2
0
 private FSID createNode(FSRevisionNode revNode, String copyId, String txnId) throws SVNException {
   FSTransactionRoot txnRoot = getTxnRoot();
   String nodeId = txnRoot.getNewTxnNodeId();
   FSID id = FSID.createTxnId(nodeId, copyId, txnId);
   revNode.setId(id);
   revNode.setIsFreshTxnRoot(false);
   myFSFS.putTxnRevisionNode(id, revNode);
   return id;
 }
 private static boolean areRepresentationsEqual(
     FSRevisionNode revNode1, FSRevisionNode revNode2, boolean forProperties) {
   if (revNode1 == revNode2) {
     return true;
   } else if (revNode1 == null || revNode2 == null) {
     return false;
   }
   return FSRepresentation.compareRepresentations(
       forProperties ? revNode1.getPropsRepresentation() : revNode1.getTextRepresentation(),
       forProperties ? revNode2.getPropsRepresentation() : revNode2.getTextRepresentation());
 }
Esempio n. 4
0
  public static void mergeChanges(
      FSFS owner, FSTransactionRoot txnRoot, FSRevisionNode sourceNode, StringBuffer conflictPath)
      throws SVNException {
    FSRevisionNode txnRootNode = txnRoot.getRootRevisionNode();
    FSRevisionNode ancestorNode = txnRoot.getTxnBaseRootNode();

    if (txnRootNode.getId().equals(ancestorNode.getId())) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.UNKNOWN, "FATAL error: no changes in transaction to commit");
      SVNErrorManager.error(err, SVNLogType.FSFS);
    } else {
      merge(owner, "/", txnRootNode, sourceNode, ancestorNode, txnRoot, conflictPath);
    }
  }
Esempio n. 5
0
 public static InputStream createDeltaStream(
     SVNDeltaCombiner combiner, FSRevisionNode fileNode, FSFS owner) throws SVNException {
   if (fileNode == null) {
     return SVNFileUtil.DUMMY_IN;
   } else if (fileNode.getType() != SVNNodeKind.FILE) {
     SVNErrorMessage err =
         SVNErrorMessage.create(
             SVNErrorCode.FS_NOT_FILE, "Attempted to get textual contents of a *non*-file node");
     SVNErrorManager.error(err, SVNLogType.FSFS);
   }
   FSRepresentation representation = fileNode.getTextRepresentation();
   if (representation == null) {
     return SVNFileUtil.DUMMY_IN;
   }
   return new FSInputStream(combiner, representation, owner);
 }
Esempio n. 6
0
 private static void updateAncestry(
     FSFS owner, FSID sourceId, FSID targetId, String targetPath, long sourcePredecessorCount)
     throws SVNException {
   if (!targetId.isTxn()) {
     SVNErrorMessage err =
         SVNErrorMessage.create(
             SVNErrorCode.FS_NOT_MUTABLE, "Unexpected immutable node at ''{0}''", targetPath);
     SVNErrorManager.error(err, SVNLogType.FSFS);
   }
   FSRevisionNode revNode = owner.getRevisionNode(targetId);
   revNode.setPredecessorId(sourceId);
   revNode.setCount(
       sourcePredecessorCount != -1 ? sourcePredecessorCount + 1 : sourcePredecessorCount);
   revNode.setIsFreshTxnRoot(false);
   owner.putTxnRevisionNode(targetId, revNode);
 }
Esempio n. 7
0
  private static long merge(
      FSFS owner,
      String targetPath,
      FSRevisionNode target,
      FSRevisionNode source,
      FSRevisionNode ancestor,
      FSTransactionRoot txnRoot,
      StringBuffer conflictPath)
      throws SVNException {
    FSID sourceId = source.getId();
    FSID targetId = target.getId();
    FSID ancestorId = ancestor.getId();
    long mergeInfoIncrement = 0;

    if (ancestorId.equals(targetId)) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.FS_GENERAL,
              "Bad merge; target ''{0}'' has id ''{1}'', same as ancestor",
              new Object[] {targetPath, targetId});
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    if (ancestorId.equals(sourceId) || sourceId.equals(targetId)) {
      return mergeInfoIncrement;
    }

    if (source.getType() != SVNNodeKind.DIR
        || target.getType() != SVNNodeKind.DIR
        || ancestor.getType() != SVNNodeKind.DIR) {
      SVNErrorManager.error(FSErrors.errorConflict(targetPath, conflictPath), SVNLogType.FSFS);
    }

    if (!FSRepresentation.compareRepresentations(
        target.getPropsRepresentation(), ancestor.getPropsRepresentation())) {
      SVNErrorManager.error(FSErrors.errorConflict(targetPath, conflictPath), SVNLogType.FSFS);
    }

    Map sourceEntries = source.getDirEntries(owner);
    Map targetEntries = target.getDirEntries(owner);
    Map ancestorEntries = ancestor.getDirEntries(owner);
    Set removedEntries = new SVNHashSet();
    for (Iterator ancestorEntryNames = ancestorEntries.keySet().iterator();
        ancestorEntryNames.hasNext(); ) {
      String ancestorEntryName = (String) ancestorEntryNames.next();
      FSEntry ancestorEntry = (FSEntry) ancestorEntries.get(ancestorEntryName);
      FSEntry sourceEntry =
          removedEntries.contains(ancestorEntryName)
              ? null
              : (FSEntry) sourceEntries.get(ancestorEntryName);
      FSEntry targetEntry = (FSEntry) targetEntries.get(ancestorEntryName);
      if (sourceEntry != null && ancestorEntry.getId().equals(sourceEntry.getId())) {
        /*
         * No changes were made to this entry while the transaction was
         * in progress, so do nothing to the target.
         */
      } else if (targetEntry != null && ancestorEntry.getId().equals(targetEntry.getId())) {
        if (owner.supportsMergeInfo()) {
          FSRevisionNode targetEntryNode = owner.getRevisionNode(targetEntry.getId());
          long mergeInfoStart = targetEntryNode.getMergeInfoCount();
          mergeInfoIncrement -= mergeInfoStart;
        }
        if (sourceEntry != null) {
          if (owner.supportsMergeInfo()) {
            FSRevisionNode sourceEntryNode = owner.getRevisionNode(sourceEntry.getId());
            long mergeInfoEnd = sourceEntryNode.getMergeInfoCount();
            mergeInfoIncrement += mergeInfoEnd;
          }
          txnRoot.setEntry(target, ancestorEntryName, sourceEntry.getId(), sourceEntry.getType());
        } else {
          txnRoot.deleteEntry(target, ancestorEntryName);
        }
      } else {

        if (sourceEntry == null || targetEntry == null) {
          SVNErrorManager.error(
              FSErrors.errorConflict(
                  SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, ancestorEntryName)),
                  conflictPath),
              SVNLogType.FSFS);
        }

        if (sourceEntry.getType() == SVNNodeKind.FILE
            || targetEntry.getType() == SVNNodeKind.FILE
            || ancestorEntry.getType() == SVNNodeKind.FILE) {
          SVNErrorManager.error(
              FSErrors.errorConflict(
                  SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, ancestorEntryName)),
                  conflictPath),
              SVNLogType.FSFS);
        }

        if (!sourceEntry.getId().getNodeID().equals(ancestorEntry.getId().getNodeID())
            || !sourceEntry.getId().getCopyID().equals(ancestorEntry.getId().getCopyID())
            || !targetEntry.getId().getNodeID().equals(ancestorEntry.getId().getNodeID())
            || !targetEntry.getId().getCopyID().equals(ancestorEntry.getId().getCopyID())) {
          SVNErrorManager.error(
              FSErrors.errorConflict(
                  SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, ancestorEntryName)),
                  conflictPath),
              SVNLogType.FSFS);
        }

        FSRevisionNode sourceEntryNode = owner.getRevisionNode(sourceEntry.getId());
        FSRevisionNode targetEntryNode = owner.getRevisionNode(targetEntry.getId());
        FSRevisionNode ancestorEntryNode = owner.getRevisionNode(ancestorEntry.getId());
        String childTargetPath =
            SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, targetEntry.getName()));
        long subMergeInfoIncrement =
            merge(
                owner,
                childTargetPath,
                targetEntryNode,
                sourceEntryNode,
                ancestorEntryNode,
                txnRoot,
                conflictPath);
        if (owner.supportsMergeInfo()) {
          mergeInfoIncrement += subMergeInfoIncrement;
        }
      }

      removedEntries.add(ancestorEntryName);
    }

    for (Iterator sourceEntryNames = sourceEntries.keySet().iterator();
        sourceEntryNames.hasNext(); ) {
      String sourceEntryName = (String) sourceEntryNames.next();
      if (removedEntries.contains(sourceEntryName)) {
        continue;
      }
      FSEntry sourceEntry = (FSEntry) sourceEntries.get(sourceEntryName);
      FSEntry targetEntry = (FSEntry) targetEntries.get(sourceEntryName);
      if (targetEntry != null) {
        SVNErrorManager.error(
            FSErrors.errorConflict(
                SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, targetEntry.getName())),
                conflictPath),
            SVNLogType.FSFS);
      }
      if (owner.supportsMergeInfo()) {
        FSRevisionNode sourceEntryNode = owner.getRevisionNode(sourceEntry.getId());
        long mergeInfoCount = sourceEntryNode.getMergeInfoCount();
        mergeInfoIncrement += mergeInfoCount;
      }
      txnRoot.setEntry(target, sourceEntry.getName(), sourceEntry.getId(), sourceEntry.getType());
    }
    long sourceCount = source.getCount();
    updateAncestry(owner, sourceId, targetId, targetPath, sourceCount);
    if (owner.supportsMergeInfo()) {
      txnRoot.incrementMergeInfoCount(target, mergeInfoIncrement);
    }
    return mergeInfoIncrement;
  }
Esempio n. 8
0
  private void copy(
      FSRevisionNode toNode,
      String entryName,
      FSRevisionNode fromNode,
      boolean preserveHistory,
      long fromRevision,
      String fromPath,
      String txnId)
      throws SVNException {
    FSID id = null;
    FSTransactionRoot txnRoot = getTxnRoot();
    if (preserveHistory) {
      FSID srcId = fromNode.getId();
      FSRevisionNode toRevNode = FSRevisionNode.dumpRevisionNode(fromNode);
      String copyId = reserveCopyId(txnId);

      toRevNode.setPredecessorId(srcId);
      if (toRevNode.getCount() != -1) {
        toRevNode.setCount(toRevNode.getCount() + 1);
      }
      String createdPath =
          SVNPathUtil.getAbsolutePath(SVNPathUtil.append(toNode.getCreatedPath(), entryName));
      toRevNode.setCreatedPath(createdPath);
      toRevNode.setCopyFromPath(fromPath);
      toRevNode.setCopyFromRevision(fromRevision);

      toRevNode.setCopyRootPath(null);
      id = txnRoot.createSuccessor(srcId, toRevNode, copyId);
    } else {
      id = fromNode.getId();
    }

    txnRoot.setEntry(toNode, entryName, id, fromNode.getType());
  }
Esempio n. 9
0
  public void makePathMutable(FSParentPath parentPath, String errorPath) throws SVNException {
    FSTransactionRoot txnRoot = getTxnRoot();
    String txnId = txnRoot.getTxnID();

    if (parentPath.getRevNode().getId().isTxn()) {
      return;
    }
    FSRevisionNode clone = null;

    if (parentPath.getParent() != null) {
      makePathMutable(parentPath.getParent(), errorPath);
      FSID parentId = null;
      String copyId = null;

      switch (parentPath.getCopyStyle()) {
        case FSCopyInheritance.COPY_ID_INHERIT_PARENT:
          parentId = parentPath.getParent().getRevNode().getId();
          copyId = parentId.getCopyID();
          break;
        case FSCopyInheritance.COPY_ID_INHERIT_NEW:
          copyId = reserveCopyId(txnId);
          break;
        case FSCopyInheritance.COPY_ID_INHERIT_SELF:
          copyId = null;
          break;
        case FSCopyInheritance.COPY_ID_INHERIT_UNKNOWN:
        default:
          SVNErrorMessage err =
              SVNErrorMessage.create(
                  SVNErrorCode.UNKNOWN,
                  "FATAL error: can not make path ''{0}'' mutable",
                  errorPath);
          SVNErrorManager.error(err, SVNLogType.FSFS);
      }

      String copyRootPath = parentPath.getRevNode().getCopyRootPath();
      long copyRootRevision = parentPath.getRevNode().getCopyRootRevision();

      FSRoot copyrootRoot = myFSFS.createRevisionRoot(copyRootRevision);
      FSRevisionNode copyRootNode = copyrootRoot.getRevisionNode(copyRootPath);
      FSID childId = parentPath.getRevNode().getId();
      FSID copyRootId = copyRootNode.getId();
      boolean isParentCopyRoot = false;
      if (!childId.getNodeID().equals(copyRootId.getNodeID())) {
        isParentCopyRoot = true;
      }

      String clonePath = parentPath.getParent().getAbsPath();
      clone =
          txnRoot.cloneChild(
              parentPath.getParent().getRevNode(),
              clonePath,
              parentPath.getEntryName(),
              copyId,
              isParentCopyRoot);

      txnRoot.putRevNodeToCache(parentPath.getAbsPath(), clone);
    } else {
      FSTransactionInfo txn = txnRoot.getTxn();

      if (txn.getRootID().equals(txn.getBaseID())) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.UNKNOWN,
                "FATAL error: txn ''{0}'' root id ''{1}'' matches base id ''{2}''",
                new Object[] {txnId, txn.getRootID(), txn.getBaseID()});
        SVNErrorManager.error(err, SVNLogType.FSFS);
      }
      clone = myFSFS.getRevisionNode(txn.getRootID());
    }

    parentPath.setRevNode(clone);
  }
Esempio n. 10
0
  public FSRevisionNode makeEntry(
      FSRevisionNode parent, String parentPath, String entryName, boolean isDir, String txnId)
      throws SVNException {
    if (!SVNPathUtil.isSinglePathComponent(entryName)) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.FS_NOT_SINGLE_PATH_COMPONENT,
              "Attempted to create a node with an illegal name ''{0}''",
              entryName);
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    if (parent.getType() != SVNNodeKind.DIR) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.FS_NOT_DIRECTORY, "Attempted to create entry in non-directory parent");
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    if (!parent.getId().isTxn()) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.FS_NOT_MUTABLE, "Attempted to clone child of non-mutable node");
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    FSRevisionNode newRevNode = new FSRevisionNode();
    newRevNode.setType(isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE);
    String createdPath = SVNPathUtil.getAbsolutePath(SVNPathUtil.append(parentPath, entryName));
    newRevNode.setCreatedPath(createdPath);
    newRevNode.setCopyRootPath(parent.getCopyRootPath());
    newRevNode.setCopyRootRevision(parent.getCopyRootRevision());
    newRevNode.setCopyFromRevision(SVNRepository.INVALID_REVISION);
    newRevNode.setCopyFromPath(null);
    FSID newNodeId = createNode(newRevNode, parent.getId().getCopyID(), txnId);

    FSRevisionNode childNode = myFSFS.getRevisionNode(newNodeId);

    FSTransactionRoot txnRoot = getTxnRoot();
    txnRoot.setEntry(parent, entryName, childNode.getId(), newRevNode.getType());
    return childNode;
  }
Esempio n. 11
0
  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());
  }
Esempio n. 12
0
  public void close() throws IOException {
    if (myIsClosed) {
      return;
    }
    myIsClosed = true;
    final long truncateToSize[] = new long[] {-1};
    try {
      ByteArrayInputStream target = new ByteArrayInputStream(myTextBuffer.toByteArray());
      myDeltaGenerator.sendDelta(null, mySourceStream, mySourceOffset, target, this, false);

      final FSRepresentation rep = new FSRepresentation();
      rep.setOffset(myRepOffset);

      long offset = myTargetFileOS.getPosition();

      rep.setSize(offset - myDeltaStart);
      rep.setExpandedSize(myRepSize);
      rep.setTxnId(myRevNode.getId().getTxnID());
      String uniqueSuffix = myTxnRoot.getNewTxnNodeId();
      String uniquifier = rep.getTxnId() + '/' + uniqueSuffix;
      rep.setUniquifier(uniquifier);
      rep.setRevision(SVNRepository.INVALID_REVISION);

      rep.setMD5HexDigest(SVNFileUtil.toHexDigest(myMD5Digest));
      rep.setSHA1HexDigest(SVNFileUtil.toHexDigest(mySHA1Digest));

      FSFS fsfs = myTxnRoot.getOwner();
      final IFSRepresentationCacheManager reposCacheManager = fsfs.getRepositoryCacheManager();
      if (reposCacheManager != null) {
        try {
          reposCacheManager.runReadTransaction(
              new IFSSqlJetTransaction() {
                public void run() throws SVNException {
                  final FSRepresentation oldRep =
                      reposCacheManager.getRepresentationByHash(rep.getSHA1HexDigest());
                  if (oldRep != null) {
                    oldRep.setUniquifier(rep.getUniquifier());
                    oldRep.setMD5HexDigest(rep.getMD5HexDigest());
                    truncateToSize[0] = myRepOffset;
                    myRevNode.setTextRepresentation(oldRep);
                  }
                }
              });
        } catch (SVNException e) {
          // explicitly ignore.
          SVNDebugLog.getDefaultLog().logError(SVNLogType.FSFS, e);
        }
      }
      if (truncateToSize[0] < 0) {
        myTargetFileOS.write("ENDREP\n".getBytes("UTF-8"));
        myRevNode.setTextRepresentation(rep);
      }
      myRevNode.setIsFreshTxnRoot(false);
      fsfs.putTxnRevisionNode(myRevNode.getId(), myRevNode);
    } catch (SVNException svne) {
      throw new IOException(svne.getMessage());
    } finally {
      closeStreams(truncateToSize[0]);
      try {
        myTxnLock.unlock();
      } catch (SVNException e) {
        //
      }
      FSWriteLock.release(myTxnLock);
    }
  }
Esempio n. 13
0
  public static OutputStream createStream(
      FSRevisionNode revNode, FSTransactionRoot txnRoot, OutputStream dstStream, boolean compress)
      throws SVNException {
    if (revNode.getType() != SVNNodeKind.FILE) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.FS_NOT_FILE, "Attempted to set textual contents of a *non*-file node");
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    if (!revNode.getId().isTxn()) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.FS_NOT_MUTABLE,
              "Attempted to set textual contents of an immutable node");
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    OutputStream targetOS = null;
    InputStream sourceStream = null;
    long offset = -1;
    long deltaStart = -1;
    FSWriteLock txnLock = null;
    try {
      txnLock = FSWriteLock.getWriteLockForTxn(txnRoot.getTxnID(), txnRoot.getOwner());
      txnLock.lock();

      File targetFile = txnRoot.getTransactionProtoRevFile();
      offset = targetFile.length();
      targetOS = SVNFileUtil.openFileForWriting(targetFile, true);
      CountingOutputStream revWriter = new CountingOutputStream(targetOS, offset);

      FSRepresentation baseRep = revNode.chooseDeltaBase(txnRoot.getOwner());
      sourceStream =
          FSInputStream.createDeltaStream(new SVNDeltaCombiner(), baseRep, txnRoot.getOwner());
      String header;

      if (baseRep != null) {
        header =
            FSRepresentation.REP_DELTA
                + " "
                + baseRep.getRevision()
                + " "
                + baseRep.getOffset()
                + " "
                + baseRep.getSize()
                + "\n";
      } else {
        header = FSRepresentation.REP_DELTA + "\n";
      }

      revWriter.write(header.getBytes("UTF-8"));
      deltaStart = revWriter.getPosition();

      if (dstStream instanceof FSOutputStream) {
        FSOutputStream fsOS = (FSOutputStream) dstStream;
        fsOS.reset(
            revNode, revWriter, targetFile, sourceStream, deltaStart, 0, offset, txnRoot, txnLock);
        return dstStream;
      }

      return new FSOutputStream(
          revNode,
          revWriter,
          targetFile,
          sourceStream,
          deltaStart,
          0,
          offset,
          txnRoot,
          compress,
          txnLock);

    } catch (IOException ioe) {
      SVNFileUtil.closeFile(targetOS);
      SVNFileUtil.closeFile(sourceStream);
      txnLock.unlock();
      FSWriteLock.release(txnLock);
      SVNErrorMessage err =
          SVNErrorMessage.create(SVNErrorCode.IO_ERROR, ioe.getLocalizedMessage());
      SVNErrorManager.error(err, ioe, SVNLogType.FSFS);
    } catch (SVNException svne) {
      if (txnLock != null) {
        txnLock.unlock();
        FSWriteLock.release(txnLock);
      }
      SVNFileUtil.closeFile(targetOS);
      SVNFileUtil.closeFile(sourceStream);
      throw svne;
    }
    return null;
  }