Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * ====================================================================
   * Copyright (c) 2004-2006 TMate Software Ltd.  All rights reserved.
   *
   * This software is licensed as described in the file COPYING, which
   * you should have received as part of this distribution.  The terms
   * are also available at http://svnkit.com/license.html
   * If newer versions of this license are posted there, you may use a
   * newer version instead, at your option.
  * ====================================================================
  */
 package org.tmatesoft.svn.core.internal.io.fs;
 
 import java.io.File;
 import java.util.Date;
 import java.util.Map;
 

Author(s):
TMate Software Ltd.
Version:
1.1.0
 
 public class FSCommitter {
 
     private FSFS myFSFS;
     private FSTransactionRoot myTxnRoot;
     private FSTransactionInfo myTxn;
     private Collection myLockTokens;
     private String myAuthor;
 
     public FSCommitter(FSFS fsfsFSTransactionRoot txnRootFSTransactionInfo txnCollection lockTokensString author) {
          = fsfs;
          = txnRoot;
          = txn;
          = lockTokens != null ? lockTokens : .;
          = author;
     }
 
     public void deleteNode(String paththrows SVNException {
         FSParentPath parentPath = .openPath(pathtruetrue);
 
         if (parentPath.getParent() == null) {
             SVNErrorMessage err = SVNErrorMessage.create(."The root directory cannot be deleted");
             SVNErrorManager.error(err);
         }
 
         if ((.getTxnFlags() & .) != 0) {
             allowLockedOperation(pathtruefalse);
         }
 
         makePathMutable(parentPath.getParent(), path);
         .deleteEntry(parentPath.getParent().getRevNode(), parentPath.getNameEntry());
         .removeRevNodeFromCache(parentPath.getAbsPath());
         addChange(pathparentPath.getRevNode().getId(), .falsefalse.null);
     }
 
     public void makeCopy(FSRevisionRoot fromRootString fromPathString toPathboolean preserveHistorythrows SVNException {
         String txnId = .getTxnID();
         FSRevisionNode fromNode = fromRoot.getRevisionNode(fromPath);
 
         FSParentPath toParentPath = .openPath(toPathfalsetrue);
         if ((.getTxnFlags() & .) != 0) {
             FSCommitter.allowLockedOperation(toPathtruefalse);
         }
 
         if (toParentPath.getRevNode() != null && toParentPath.getRevNode().getId().equals(fromNode.getId())) {
             return;
         }
 
         FSPathChangeKind changeKind;
         if (toParentPath.getRevNode() != null) {
             changeKind = .;
         } else {
             changeKind = .;
         }
 
         makePathMutable(toParentPath.getParent(), toPath);
         String fromCanonPath = fromPath;
         copy(toParentPath.getParent().getRevNode(), toParentPath.getNameEntry(), fromNodepreserveHistoryfromRoot.getRevision(), fromCanonPathtxnId);
 
        if (changeKind == .) {
            .removeRevNodeFromCache(toParentPath.getAbsPath());
        }
        FSRevisionNode newNode = .getRevisionNode(toPath);
        addChange(toPathnewNode.getId(), changeKindfalsefalsefromRoot.getRevision(), fromCanonPath);
    }
    public void makeFile(String paththrows SVNException {
        SVNPathUtil.checkPathIsValid(path);
        String txnId = .getTxnID();
        FSParentPath parentPath = .openPath(pathfalsetrue);
        if (parentPath.getRevNode() != null) {
            SVNErrorManager.error(FSErrors.errorAlreadyExists(path));
        }
        if ((.getTxnFlags() & .) != 0) {
            FSCommitter.allowLockedOperation(pathfalsefalse);
        }
        makePathMutable(parentPath.getParent(), path);
        FSRevisionNode childNode = makeEntry(parentPath.getParent().getRevNode(), parentPath.getParent().getAbsPath(), parentPath.getNameEntry(), falsetxnId);
        .putRevNodeToCache(parentPath.getAbsPath(), childNode);
        addChange(pathchildNode.getId(), .falsefalse.null);
    }
    public void makeDir(String paththrows SVNException {
        SVNPathUtil.checkPathIsValid(path);
        String txnId = .getTxnID();
        FSParentPath parentPath = .openPath(pathfalsetrue);
        if (parentPath.getRevNode() != null) {
            SVNErrorManager.error(FSErrors.errorAlreadyExists(path));
        }
        if ((.getTxnFlags() & .) != 0) {
            FSCommitter.allowLockedOperation(pathtruefalse);
        }
        makePathMutable(parentPath.getParent(), path);
        FSRevisionNode subDirNode = makeEntry(parentPath.getParent().getRevNode(), parentPath.getParent().getAbsPath(), parentPath.getNameEntry(), truetxnId);
        .putRevNodeToCache(parentPath.getAbsPath(), subDirNode);
        addChange(pathsubDirNode.getId(), .falsefalse.null);
    }
    public FSRevisionNode makeEntry(FSRevisionNode parentString parentPathString entryNameboolean isDirString txnIdthrows SVNException {
        if (!SVNPathUtil.isSinglePathComponent(entryName)) {
            SVNErrorMessage err = SVNErrorMessage.create(."Attempted to create a node with an illegal name ''{0}''"entryName);
            SVNErrorManager.error(err);
        }
        if (parent.getType() != .) {
            SVNErrorMessage err = SVNErrorMessage.create(."Attempted to create entry in non-directory parent");
            SVNErrorManager.error(err);
        }
        if (!parent.getId().isTxn()) {
            SVNErrorMessage err = SVNErrorMessage.create(."Attempted to clone child of non-mutable node");
            SVNErrorManager.error(err);
        }
        FSRevisionNode newRevNode = new FSRevisionNode();
        newRevNode.setType(isDir ? . : .);
        newRevNode.setCreatedPath(SVNPathUtil.concatToAbs(parentPathentryName));
        newRevNode.setCopyRootPath(parent.getCopyRootPath());
        newRevNode.setCopyRootRevision(parent.getCopyRootRevision());
        newRevNode.setCopyFromPath(null);
        FSID newNodeId = createNode(newRevNodeparent.getId().getCopyID(), txnId);
        FSRevisionNode childNode = .getRevisionNode(newNodeId);
        .setEntry(parententryNamechildNode.getId(), newRevNode.getType());
        return childNode;
    }
    public void addChange(String pathFSID idFSPathChangeKind changeKindboolean textModifiedboolean propsModifiedlong copyFromRevisionString copyFromPaththrows SVNException {
        OutputStream changesFile = null;
        try {
            changesFile = SVNFileUtil.openFileForWriting(.getTransactionChangesFile(), true);
            FSPathChange pathChange = new FSPathChange(pathidchangeKindtextModifiedpropsModifiedcopyFromPathcopyFromRevision);
            .writeChangeEntry(changesFilepathChange);
        } catch (IOException ioe) {
            SVNErrorMessage err = SVNErrorMessage.create(.ioe.getLocalizedMessage());
            SVNErrorManager.error(errioe);
        } finally {
            SVNFileUtil.closeFile(changesFile);
        }
    }
    public long commitTxn() throws SVNException {
        long newRevision = .;
        while (true) {
            long youngishRev = .getYoungestRevision();
            FSRevisionRoot youngishRoot = .createRevisionRoot(youngishRev);
            FSRevisionNode youngishRootNode = youngishRoot.getRevisionNode("/");
            mergeChanges(nullyoungishRootNode);
            .setBaseRevision(youngishRev);
            FSWriteLock writeLock = FSWriteLock.getWriteLock();
            synchronized (writeLock) {
                try {
                    writeLock.lock();
                    newRevision = commit();
                } catch (SVNException svne) {
                    if (svne.getErrorMessage().getErrorCode() == .) {
                        long youngestRev = .getYoungestRevision();
                        if (youngishRev == youngestRev) {
                            throw svne;
                        }
                        continue;
                    }
                    throw svne;
                } finally {
                    writeLock.unlock();
                    FSWriteLock.realease(writeLock);
                }
            }
            return newRevision;
        }
    }
    public void makePathMutable(FSParentPath parentPathString errorPaththrows SVNException {
        String txnId = .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 .:
                    parentId = parentPath.getParent().getRevNode().getId();
                    copyId = parentId.getCopyID();
                    break;
                case .:
                    copyId = reserveCopyId(txnId);
                    break;
                case .:
                    copyId = null;
                    break;
                case .:
                default:
                    SVNErrorMessage err = SVNErrorMessage.create(."FATAL error: can not make path ''{0}'' mutable"errorPath);
                    SVNErrorManager.error(err);
            }
            String copyRootPath = parentPath.getRevNode().getCopyRootPath();
            long copyRootRevision = parentPath.getRevNode().getCopyRootRevision();
            FSRoot copyrootRoot = .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 = .cloneChild(parentPath.getParent().getRevNode(), clonePathparentPath.getNameEntry(), copyIdisParentCopyRoot);
            .putRevNodeToCache(parentPath.getAbsPath(), clone);
        } else {
            FSTransactionInfo txn = .getTxn();
            if (txn.getRootID().equals(txn.getBaseID())) {
                SVNErrorMessage err = SVNErrorMessage.create(."FATAL error: txn ''{0}'' root id ''{1}'' matches base id ''{2}''"new Object[] {
                        txnIdtxn.getRootID(), txn.getBaseID()
                });
                SVNErrorManager.error(err);
            }
            clone = .getRevisionNode(txn.getRootID());
        }
        parentPath.setRevNode(clone);
    }
    public String reserveCopyId(String txnIdthrows SVNException {
        String[] nextIds = .readNextIDs();
        String copyId = FSTransactionRoot.generateNextKey(nextIds[1]);
        .writeNextIDs(txnIdnextIds[0], copyId);
        return "_" + nextIds[1];
    }
    private void copy(FSRevisionNode toNodeString entryNameFSRevisionNode fromNodeboolean preserveHistorylong fromRevisionString fromPathString txnIdthrows SVNException {
        FSID id = null;
        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);
            }
            toRevNode.setCreatedPath(SVNPathUtil.concatToAbs(toNode.getCreatedPath(), entryName));
            toRevNode.setCopyFromPath(fromPath);
            toRevNode.setCopyFromRevision(fromRevision);
            toRevNode.setCopyRootPath(null);
            id = .createSuccessor(srcIdtoRevNodecopyId);
        } else {
            id = fromNode.getId();
        }
        .setEntry(toNodeentryNameidfromNode.getType());
    }
    private FSID createNode(FSRevisionNode revNodeString copyIdString txnIdthrows SVNException {
        String nodeId = getNewTxnNodeId();
        FSID id = FSID.createTxnId(nodeIdcopyIdtxnId);
        revNode.setId(id);
        .putTxnRevisionNode(idrevNode);
        return id;
    }
    private String getNewTxnNodeId() throws SVNException {
        String[] curIds = .readNextIDs();
        String curNodeId = curIds[0];
        String curCopyId = curIds[1];
        String nextNodeId = FSTransactionRoot.generateNextKey(curNodeId);
        .writeNextIDs(.getTxnID(), nextNodeIdcurCopyId);
        return "_" + nextNodeId;
    }
    private long commit() throws SVNException {
        long oldRev = .getYoungestRevision();
        if (.getBaseRevision() != oldRev) {
            SVNErrorMessage err = SVNErrorMessage.create(."Transaction out of date");
            SVNErrorManager.error(err);
        }
        verifyLocks();
        String[] ids = .getNextRevisionIDs();
        String startNodeId = ids[0];
        String startCopyId = ids[1];
        long newRevision = oldRev + 1;
        OutputStream protoFileOS = null;
        FSID newRootId = null;
        File revisionPrototypeFile = .getTransactionRevFile();
        long offset = revisionPrototypeFile.length();
        try {
            protoFileOS = SVNFileUtil.openFileForWriting(revisionPrototypeFiletrue);
            FSID rootId = FSID.createTxnId("0""0".getTxnId());
            CountingStream revWriter = new CountingStream(protoFileOSoffset);
            newRootId = .writeFinalRevision(newRootIdrevWriternewRevisionrootIdstartNodeIdstartCopyId);
            long changedPathOffset = .writeFinalChangedPathInfo(revWriter);
            String offsetsLine = "\n" + newRootId.getOffset() + " " + changedPathOffset + "\n";
            protoFileOS.write(offsetsLine.getBytes("UTF-8"));
        } catch (IOException ioe) {
            SVNErrorMessage err = SVNErrorMessage.create(.ioe.getLocalizedMessage());
            SVNErrorManager.error(errioe);
        } finally {
            SVNFileUtil.closeFile(protoFileOS);
        }
        Map txnProps = .getTransactionProperties(.getTxnId());
        if (txnProps != null && !txnProps.isEmpty()) {
            if (txnProps.get(.) != null) {
            }
            if (txnProps.get(.) != null) {
                .setTransactionProperty(.getTxnId(), .null);
            }
        }
        File dstRevFile = .getNewRevisionFile(newRevision);
        SVNFileUtil.rename(revisionPrototypeFiledstRevFile);
        String commitTime = SVNTimeUtil.formatDate(new Date(System.currentTimeMillis()));
        
        File txnPropsFile = .getTransactionPropertiesFile(.getTxnId());
        File dstRevPropsFile = .getNewRevisionPropertiesFile(newRevision);
        SVNFileUtil.rename(txnPropsFiledstRevPropsFile);
        try {
            .writeFinalCurrentFile(newRevisionstartNodeIdstartCopyId);
        } catch (IOException ioe) {
            SVNErrorMessage err = SVNErrorMessage.create(.ioe.getLocalizedMessage());
            SVNErrorManager.error(errioe);
        }
        purgeTxn(.getTxnId());
        return newRevision;
    }
    private void mergeChanges(FSRevisionNode ancestorNodeFSRevisionNode sourceNodethrows SVNException {
        String txnId = .getTxnId();
        FSRevisionNode txnRootNode = .getRootRevisionNode();
        if (ancestorNode == null) {
            ancestorNode = .getTxnBaseRootNode();
        }
        if (txnRootNode.getId().equals(ancestorNode.getId())) {
            SVNErrorMessage err = SVNErrorMessage.create(."FATAL error: no changes in transaction to commit");
            SVNErrorManager.error(err);
        } else {
            merge("/"txnRootNodesourceNodeancestorNodetxnId);
        }
    }
    private void merge(String targetPathFSRevisionNode targetFSRevisionNode sourceFSRevisionNode ancestorString txnIdthrows SVNException {
        FSID sourceId = source.getId();
        FSID targetId = target.getId();
        FSID ancestorId = ancestor.getId();
        if (ancestorId.equals(targetId)) {
            SVNErrorMessage err = SVNErrorMessage.create(."Bad merge; target ''{0}'' has id ''{1}'', same as ancestor"new Object[] {
                    targetPathtargetId
            });
            SVNErrorManager.error(err);
        }
        if (ancestorId.equals(sourceId) || sourceId.equals(targetId)) {
            return;
        }
        if (source.getType() != . || target.getType() != . || ancestor.getType() != .) {
            SVNErrorManager.error(FSErrors.errorConflict(targetPath));
        }
        if (!FSRepresentation.compareRepresentations(target.getPropsRepresentation(), ancestor.getPropsRepresentation())) {
            SVNErrorManager.error(FSErrors.errorConflict(targetPath));
        }
        Map sourceEntries = source.getDirEntries();
        Map targetEntries = target.getDirEntries();
        Map ancestorEntries = ancestor.getDirEntries();
        for (Iterator ancestorEntryNames = ancestorEntries.keySet().iterator(); ancestorEntryNames.hasNext();) {
            String ancestorEntryName = (StringancestorEntryNames.next();
            FSEntry ancestorEntry = (FSEntryancestorEntries.get(ancestorEntryName);
            FSEntry sourceEntry = (FSEntrysourceEntries.get(ancestorEntryName);
            FSEntry targetEntry = (FSEntrytargetEntries.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 (sourceEntry != null) {
                    .setEntry(targetancestorEntryNamesourceEntry.getId(), sourceEntry.getType());
                } else {
                    .deleteEntry(targetancestorEntryName);
                }
            } else {
                if (sourceEntry == null || targetEntry == null) {
                    SVNErrorManager.error(FSErrors.errorConflict(SVNPathUtil.concatToAbs(targetPathancestorEntryName)));
                }
                if (sourceEntry.getType() == . || targetEntry.getType() == . || ancestorEntry.getType() == .) {
                    SVNErrorManager.error(FSErrors.errorConflict(SVNPathUtil.concatToAbs(targetPathancestorEntryName)));
                }
                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.concatToAbs(targetPathancestorEntryName)));
                }
                FSRevisionNode sourceEntryNode = .getRevisionNode(sourceEntry.getId());
                FSRevisionNode targetEntryNode = .getRevisionNode(targetEntry.getId());
                FSRevisionNode ancestorEntryNode = .getRevisionNode(ancestorEntry.getId());
                String childTargetPath = SVNPathUtil.concatToAbs(targetPathtargetEntry.getName());
                merge(childTargetPathtargetEntryNodesourceEntryNodeancestorEntryNodetxnId);
            }
            sourceEntries.remove(ancestorEntryName);
        }
        for (Iterator sourceEntryNames = sourceEntries.keySet().iterator(); sourceEntryNames.hasNext();) {
            String sourceEntryName = (StringsourceEntryNames.next();
            FSEntry sourceEntry = (FSEntrysourceEntries.get(sourceEntryName);
            FSEntry targetEntry = (FSEntrytargetEntries.get(sourceEntryName);
            if (targetEntry != null) {
                SVNErrorManager.error(FSErrors.errorConflict(SVNPathUtil.concatToAbs(targetPathtargetEntry.getName())));
            }
            .setEntry(targetsourceEntry.getName(), sourceEntry.getId(), sourceEntry.getType());
        }
        long sourceCount = source.getCount();
        updateAncestry(sourceIdtargetIdtargetPathsourceCount);
    }
    private void updateAncestry(FSID sourceIdFSID targetIdString targetPathlong sourcePredecessorCountthrows SVNException {
        if (!targetId.isTxn()) {
            SVNErrorMessage err = SVNErrorMessage.create(."Unexpected immutable node at ''{0}''"targetPath);
            SVNErrorManager.error(err);
        }
        FSRevisionNode revNode = .getRevisionNode(targetId);
        revNode.setPredecessorId(sourceId);
        revNode.setCount(sourcePredecessorCount != -1 ? sourcePredecessorCount + 1 : sourcePredecessorCount);
        .putTxnRevisionNode(targetIdrevNode);
    }
    private void verifyLocks() throws SVNException {
        Map changes = .getChangedPaths();
        Object[] changedPaths = changes.keySet().toArray();
        Arrays.sort(changedPaths);
        String lastRecursedPath = null;
        for (int i = 0; i < changedPaths.lengthi++) {
            String changedPath = (StringchangedPaths[i];
            boolean recurse = true;
            if (lastRecursedPath != null && SVNPathUtil.pathIsChild(lastRecursedPathchangedPath) != null) {
                continue;
            }
            FSPathChange change = (FSPathChangechanges.get(changedPath);
            if (change.getChangeKind() == .) {
                recurse = false;
            }
            allowLockedOperation(changedPathrecursetrue);
            if (recurse) {
                lastRecursedPath = changedPath;
            }
        }
    }
    public static void allowLockedOperation(FSFS fsfsString pathfinal String usernamefinal Collection lockTokensboolean recursiveboolean haveWriteLockthrows SVNException {
        if (recursive) {
            ISVNLockHandler handler = new ISVNLockHandler() {
                private String myUsername = username;
                private Collection myTokens = lockTokens;
                public void handleLock(String pathSVNLock lockSVNErrorMessage errorthrows SVNException {
                    verifyLock(lock);
                }
                public void handleUnlock(String pathSVNLock lockSVNErrorMessage errorthrows SVNException {
                }
            };
            fsfs.walkDigestFiles(fsfs.getDigestFileFromRepositoryPath(path), handlerhaveWriteLock);
        } else {
            SVNLock lock = fsfs.getLockHelper(pathhaveWriteLock);
            if (lock != null) {
                verifyLock(locklockTokensusername);
            }
        }
    }
    
    private static void verifyLock(SVNLock lockCollection lockTokensString usernamethrows SVNException {
        if (username == null || "".equals(username)) {
            SVNErrorMessage err = SVNErrorMessage.create(."Cannot verify lock on path ''{0}''; no username available"lock.getPath());
            SVNErrorManager.error(err);
        } else if (username.compareTo(lock.getOwner()) != 0) {
            SVNErrorMessage err = SVNErrorMessage.create(."User {0} does not own lock on path ''{1}'' (currently locked by {2})"new Object[] {
                    usernamelock.getPath(), lock.getOwner()
            });
            SVNErrorManager.error(err);
        }
        for (Iterator tokens = lockTokens.iterator(); tokens.hasNext();) {
            String token = (Stringtokens.next();
            if (token.equals(lock.getID())) {
                return;
            }
        }
        SVNErrorMessage err = SVNErrorMessage.create(."Cannot verify lock on path ''{0}''; no matching lock-token available"lock.getPath());
        SVNErrorManager.error(err);
    }
    public static void abortTransaction(FSFS fsfsString txnIdthrows SVNException {
        File txnDir = fsfs.getTransactionDir(txnId);
        SVNFileUtil.deleteAll(txnDirtrue);
        if (txnDir.exists()) {
            SVNErrorMessage err = SVNErrorMessage.create(."Transaction cleanup failed");
            SVNErrorManager.error(err);
        }
    }
    public static void purgeTxn(FSFS fsfsString txnId) {
        SVNFileUtil.deleteAll(fsfs.getTransactionDir(txnId), true);
    }
New to GrepCode? Check out our FAQ X