示例#1
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;
  }
示例#2
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());
  }