Package org.tmatesoft.svn.core.internal.io.fs

Source Code of org.tmatesoft.svn.core.internal.io.fs.FSLog$PathInfo

/*
* ====================================================================
* Copyright (c) 2004-2009 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.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.tmatesoft.svn.core.ISVNLogEntryHandler;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNMergeInfo;
import org.tmatesoft.svn.core.SVNMergeInfoInheritance;
import org.tmatesoft.svn.core.SVNMergeRange;
import org.tmatesoft.svn.core.SVNMergeRangeList;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNProperty;
import org.tmatesoft.svn.core.SVNPropertyValue;
import org.tmatesoft.svn.core.SVNRevisionProperty;
import org.tmatesoft.svn.core.internal.util.SVNDate;
import org.tmatesoft.svn.core.internal.util.SVNHashMap;
import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNMergeInfoManager;
import org.tmatesoft.svn.core.io.SVNLocationEntry;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNRevision;


/**
* @version 1.3
* @author  TMate Software Ltd.
*/
public class FSLog {
    private static final int MAX_OPEN_HISTORIES = 128
   
    private FSFS myFSFS;
    private String[] myPaths;
    private boolean myIsDescending;
    private boolean myIsDiscoverChangedPaths;
    private boolean myIsStrictNode;
    private boolean myIsIncludeMergedRevisions;
    private long myStartRevision;
    private long myEndRevision;
    private long myLimit;
    private ISVNLogEntryHandler myHandler;
    private SVNMergeInfoManager myMergeInfoManager;
    private String[] myRevPropNames;
   
    public FSLog(FSFS owner, String[] paths, long limit, long start, long end, boolean descending,
            boolean discoverChangedPaths, boolean strictNode, boolean includeMergedRevisions,
            String[] revPropNames, ISVNLogEntryHandler handler) {
        myFSFS = owner;
        myPaths = paths;
        myStartRevision = start;
        myEndRevision = end;
        myIsDescending = descending;
        myIsDiscoverChangedPaths = discoverChangedPaths;
        myIsStrictNode = strictNode;
        myIsIncludeMergedRevisions = includeMergedRevisions;
        myRevPropNames = revPropNames;
        myLimit = limit;
        myHandler = handler;
    }
   
    public void reset(FSFS owner, String[] paths, long limit, long start, long end, boolean descending,
            boolean discoverChangedPaths, boolean strictNode, boolean includeMergedRevisions,
            String[] revPropNames, ISVNLogEntryHandler handler) {
        myFSFS = owner;
        myPaths = paths;
        myStartRevision = start;
        myEndRevision = end;
        myIsDescending = descending;
        myIsDiscoverChangedPaths = discoverChangedPaths;
        myIsStrictNode = strictNode;
        myIsIncludeMergedRevisions = includeMergedRevisions;
        myRevPropNames = revPropNames;
        myLimit = limit;
        myHandler = handler;
    }
   
    public long runLog() throws SVNException {
        long count = 0;
        if (!myIsIncludeMergedRevisions && myPaths.length == 1 && "/".equals(myPaths[0])) {
            count = myEndRevision - myStartRevision + 1;
            if (myLimit > 0 && count > myLimit) {
                count = myLimit;
            }
       
            for (int i = 0; i < count; i++) {
                long rev = myStartRevision + i;
                if (myIsDescending) {
                    rev = myEndRevision - i;
                }
                sendLog(rev, false);
            }
           
            return count;
        }

        return doLogs(myPaths, myStartRevision, myEndRevision, myIsIncludeMergedRevisions, myIsDescending,
                myLimit);
    }
   
    private long doLogs(String[] paths, long startRevision, long endRevision, boolean includeMergedRevisions,
            boolean isDescendingOrder, long limit) throws SVNException {
        long sendCount = 0;
        PathInfo[] histories = getPathHistories(paths, startRevision, endRevision, myIsStrictNode);
       
        LinkedList revisions = null;
        Map revMergeInfo = null;
        boolean anyHistoriesLeft = true;
        for (long currentRev = endRevision; anyHistoriesLeft; currentRev = getNextHistoryRevision(histories)) {
           
            boolean changed = false;
            anyHistoriesLeft = false;
           
            for (int i = 0; i < histories.length; i++) {
                PathInfo info = histories[i];
                changed = info.checkHistory(currentRev, myIsStrictNode, startRevision, changed);
               
                if (!info.myIsDone) {
                    anyHistoriesLeft = true;
                }
            }

            if (changed) {
                boolean hasChildren = false;
                Map mergeInfo = null;
                if (includeMergedRevisions) {
                    LinkedList currentPaths = new LinkedList();
                    for (int i = 0; i < histories.length; i++) {
                        PathInfo info = histories[i];
                        currentPaths.add(info.myPath);
                    }
                    mergeInfo = getCombinedMergeInfoChanges((String[]) currentPaths.toArray(new String[currentPaths.size()]), currentRev);
                    hasChildren = !mergeInfo.isEmpty();
                }
               
                if (isDescendingOrder) {
                    sendLog(currentRev, hasChildren);
                    sendCount++;
                    if (hasChildren) {
                        handleMergedRevisions(mergeInfo);
                    }
                    if (limit > 0 && sendCount >= limit) {
                        break;
                    }
                } else {
                    if (revisions == null) {
                        revisions = new LinkedList();
                    }
                    revisions.addLast(new Long(currentRev));
                   
                    if (mergeInfo != null) {
                        if (revMergeInfo == null) {
                            revMergeInfo = new TreeMap();
                        }
                        revMergeInfo.put(new Long(currentRev), mergeInfo);
                    }
                }
            }
        }

        if (revisions != null) {
            for (int i = 0; i < revisions.size(); i++) {
                boolean hasChildren = false;
                Map mergeInfo = null;
                long rev = ((Long) revisions.get(revisions.size() - i - 1)).longValue();
               
                if (revMergeInfo != null) {
                    mergeInfo = (Map) revMergeInfo.get(new Long(rev));
                    hasChildren = mergeInfo != null && !mergeInfo.isEmpty();
                }
                sendLog(rev, hasChildren);
                if (hasChildren) {
                    handleMergedRevisions(mergeInfo);
                }
                sendCount++;
                if (limit > 0 && sendCount >= limit) {
                    break;
                }
            }
        }
        return sendCount;
    }
   
    private long getNextHistoryRevision(PathInfo[] histories) {
        long nextRevision = SVNRepository.INVALID_REVISION;
        for (int i = 0; i < histories.length; i++) {
            PathInfo info = histories[i];
            if (info.myIsDone) {
                continue;
            }
            if (info.myHistoryRevision > nextRevision) {
                nextRevision = info.myHistoryRevision;
            }
        }
        return nextRevision;
    }

    private void sendLog(long revision, boolean hasChildren) throws SVNException {
        SVNLogEntry logEntry = fillLogEntry(revision);
        logEntry.setHasChildren(hasChildren);
        if (myHandler != null) {
            myHandler.handleLogEntry(logEntry);
        }
    }

    private SVNLogEntry fillLogEntry(long revision) throws SVNException {
        Map changedPaths = null;
        SVNProperties entryRevProps = null;
        boolean getRevProps = true;
        boolean censorRevProps = false;
        if (revision > 0 && myIsDiscoverChangedPaths) {
            FSRevisionRoot root = myFSFS.createRevisionRoot(revision);
            changedPaths = root.detectChanged();
        }

        //TODO: add autz check code later
        if (getRevProps) {
            SVNProperties revisionProps = myFSFS.getRevisionProperties(revision);

            if (revisionProps != null) {
                String author = revisionProps.getStringValue(SVNRevisionProperty.AUTHOR);
                String datestamp = revisionProps.getStringValue(SVNRevisionProperty.DATE);
                Date date = datestamp != null ? SVNDate.parseDateString(datestamp) : null;

                if (myRevPropNames == null || myRevPropNames.length == 0) {
                    if (censorRevProps) {
                        entryRevProps = new SVNProperties();
                        if (author != null) {
                            entryRevProps.put(SVNRevisionProperty.AUTHOR, author);
                        }
                        if (date != null) {
                            entryRevProps.put(SVNRevisionProperty.DATE, SVNDate.formatDate(date));
                        }
                    } else {
                        entryRevProps = revisionProps;
                        if (date != null) {
                            entryRevProps.put(SVNRevisionProperty.DATE, SVNDate.formatDate(date));
                        }
                    }
                } else {
                    for (int i = 0; i < myRevPropNames.length; i++) {
                        String propName = myRevPropNames[i];
                        SVNPropertyValue propVal = revisionProps.getSVNPropertyValue(propName);
                        if (censorRevProps && !SVNRevisionProperty.AUTHOR.equals(propName) &&
                                !SVNRevisionProperty.DATE.equals(propName)) {
                            continue;
                        }
                        if (entryRevProps == null) {
                            entryRevProps = new SVNProperties();
                        }
                        if (SVNRevisionProperty.DATE.equals(propName) && date != null) {
                            entryRevProps.put(propName, SVNDate.formatDate(date));
                        } else if (propVal != null) {
                            entryRevProps.put(propName, propVal);
                        }
                    }
                }
            }
        }
       
        if (changedPaths == null) {
            changedPaths = new SVNHashMap();
        }
        if (entryRevProps == null) {
            entryRevProps = new SVNProperties();
        }
        SVNLogEntry entry = new SVNLogEntry(changedPaths, revision, entryRevProps, false);
        return entry;
    }
   
    private void handleMergedRevisions(Map mergeInfo) throws SVNException {
        if (mergeInfo == null || mergeInfo.isEmpty()) {
            return;
        }
       
        LinkedList combinedList = combineMergeInfoPathLists(mergeInfo);
        for (int i = combinedList.size() - 1; i >= 0; i--) {
            PathListRange pathListRange = (PathListRange) combinedList.get(i);
            try {
                doLogs(pathListRange.myPaths, pathListRange.myRange.getStartRevision(),
                        pathListRange.myRange.getEndRevision(), true, true, 0);
            } catch (SVNException svne) {
                SVNErrorCode errCode = svne.getErrorMessage().getErrorCode();
                if (errCode == SVNErrorCode.FS_NOT_FOUND || errCode == SVNErrorCode.FS_NO_SUCH_REVISION) {
                    continue;
                }
                throw svne;
            }
        }
        if (myHandler != null) {
            myHandler.handleLogEntry(SVNLogEntry.EMPTY_ENTRY);
        }
    }

    private PathInfo[] getPathHistories(String[] paths, long start, long end, boolean strictNodeHistory) throws SVNException {
        PathInfo[] histories = new PathInfo[paths.length];
        FSRevisionRoot root = myFSFS.createRevisionRoot(end);
        for (int i = 0; i < paths.length; i++) {
            String path = paths[i];
           
            PathInfo pathHistory = new PathInfo();
            pathHistory.myPath = path;
            pathHistory.myHistoryRevision = end;
            pathHistory.myIsDone = false;
            pathHistory.myIsFirstTime = true;
           
            if (i < MAX_OPEN_HISTORIES) {
                pathHistory.myHistory = root.getNodeHistory(path);
            }
           
            histories[i] = pathHistory.getHistory(strictNodeHistory, start);
        }
        return histories;
    }
   
    private Map getCombinedMergeInfoChanges(String[] paths, long revision) throws SVNException {
        if (revision == 0) {
            return new TreeMap();
        }
        if (paths == null || paths.length == 0) {
            return new TreeMap();
        }
        Map result = new SVNHashMap();
        Map addedMergeInfoCatalog = new SVNHashMap();
        Map deletedMergeInfoCatalog = new SVNHashMap();
        FSRevisionRoot root = myFSFS.createRevisionRoot(revision);
       
        collectChangedMergeInfo(addedMergeInfoCatalog, deletedMergeInfoCatalog, revision);
       
        for (int i = 0; i < paths.length; i++) {
            String path = paths[i];
            if (deletedMergeInfoCatalog.containsKey(path)) {
                continue;
            }
            long[] appearedRevision = new long[] {-1};
            SVNLocationEntry prevLocation = null;
            try {
                prevLocation = myFSFS.getPreviousLocation(path, revision, appearedRevision);               
            } catch (SVNException e) {
                if (e.getErrorMessage().getErrorCode() == SVNErrorCode.FS_NOT_FOUND) {
                    continue;
                }
                throw e;
            }
            String prevPath = null;
            long prevRevision = -1;
            if (!(prevLocation != null && prevLocation.getPath() != null && prevLocation.getRevision() >=0 && appearedRevision[0] == revision)) {
                prevPath = path;
                prevRevision = revision - 1;
            } else if (prevLocation != null) {
                prevPath = prevLocation.getPath();
                prevRevision = prevLocation.getRevision();
            }
           
            FSRevisionRoot prevRoot = myFSFS.createRevisionRoot(prevRevision);
            String[] queryPaths = new String[] {prevPath};
            Map catalog = null;
            try {
                catalog = getMergeInfoManager().getMergeInfo(queryPaths, prevRoot, SVNMergeInfoInheritance.INHERITED, false);
            } catch (SVNException e) {
                if (e.getErrorMessage().getErrorCode() == SVNErrorCode.FS_NOT_FOUND) {
                    continue;
                }
                throw e;
            }
            SVNMergeInfo prevMergeinfo = (SVNMergeInfo) catalog.get(prevPath);
            queryPaths = new String[] {path};
            catalog = getMergeInfoManager().getMergeInfo(queryPaths, root, SVNMergeInfoInheritance.INHERITED, false);
            SVNMergeInfo mergeInfo = (SVNMergeInfo) catalog.get(path);
           
            Map deleted = new SVNHashMap();
            Map added = new SVNHashMap();
           
            SVNMergeInfoUtil.diffMergeInfo(deleted, added,
                    prevMergeinfo != null ? prevMergeinfo.getMergeSourcesToMergeLists() : null, mergeInfo != null ? mergeInfo.getMergeSourcesToMergeLists() : null, false);
           
            result = SVNMergeInfoUtil.mergeMergeInfos(result, SVNMergeInfoUtil.mergeMergeInfos(deleted, added));           
        }
        for(Iterator ps = addedMergeInfoCatalog.keySet().iterator(); ps.hasNext();) {
            String changedPath = (String) ps.next();
            Map addedMergeInfo = (Map) addedMergeInfoCatalog.get(changedPath);
            for (int i = 0; i < paths.length; i++) {
                String path = paths[i];
                if (!SVNPathUtil.isAncestor(path, changedPath)) {
                    continue;
                }
                Map deletedMergeInfo = (Map) deletedMergeInfoCatalog.get(changedPath);
                result = SVNMergeInfoUtil.mergeMergeInfos(result, deletedMergeInfo);
                result = SVNMergeInfoUtil.mergeMergeInfos(result, addedMergeInfo);
                break;
            }
        }
        return result;
    }
   
    private void collectChangedMergeInfo(Map addedMergeInfo, Map deletedMergeInfo, long revision) throws SVNException {
        if (revision == 0) {
            return;
        }
        FSRevisionRoot root = myFSFS.createRevisionRoot(revision);
        Map changedPaths = root.getChangedPaths();
        if (changedPaths == null || changedPaths.isEmpty()) {
            return;
        }
        for (Iterator paths = changedPaths.keySet().iterator(); paths.hasNext();) {
            String changedPath = (String) paths.next();
            FSPathChange change = (FSPathChange) changedPaths.get(changedPath);
            if (!change.arePropertiesModified()) {
                continue;
            }
            FSPathChangeKind changeKind = change.getChangeKind();
           
            String basePath = null;
            long baseRevision = -1;
            String mergeInfoValue = null;
            String previousMergeInfoValue = null;
           
            if (changeKind == FSPathChangeKind.FS_PATH_CHANGE_ADD ||
                    changeKind == FSPathChangeKind.FS_PATH_CHANGE_REPLACE) {
                String copyFromPath = change.getCopyPath();
                long copyFromRev = change.getCopyRevision();
                if (copyFromPath != null && copyFromRev >= 0) {
                    basePath = copyFromPath;
                    baseRevision = copyFromRev;
                }
            } else if (changeKind == FSPathChangeKind.FS_PATH_CHANGE_MODIFY) {
                long[] appearedRevision = new long[] {-1};
                SVNLocationEntry prevLocation = myFSFS.getPreviousLocation(changedPath, revision, appearedRevision);
                if (!(prevLocation != null &&
                        prevLocation.getPath() != null && prevLocation.getRevision() >= 0 && appearedRevision[0] == prevLocation.getRevision())) {
                    basePath = changedPath;
                    baseRevision = revision - 1;
                } else {
                    basePath = prevLocation.getPath();
                    baseRevision = prevLocation.getRevision();
                }
            } else {
                continue;
            }
           
            FSRevisionRoot baseRoot = null;
            if (basePath != null && baseRevision >= 0) {
                baseRoot = myFSFS.createRevisionRoot(baseRevision);
                SVNProperties props = myFSFS.getProperties(baseRoot.getRevisionNode(basePath));
                previousMergeInfoValue = props.getStringValue(SVNProperty.MERGE_INFO);
            }

            SVNProperties props = myFSFS.getProperties(root.getRevisionNode(changedPath));
            if (props != null) {
                mergeInfoValue = props.getStringValue(SVNProperty.MERGE_INFO);
            }
 
            if (mergeInfoValue == null && previousMergeInfoValue == null) {
                continue;
            }
           
            if (previousMergeInfoValue != null && mergeInfoValue == null) {
              String[] queryPaths = new String[] { changedPath };
              Map tmpCatalog = getMergeInfoManager().getMergeInfo(queryPaths, root, SVNMergeInfoInheritance.INHERITED, false);
              SVNMergeInfo tmpMergeInfo = (SVNMergeInfo) tmpCatalog.get(changedPath);
              if (tmpMergeInfo != null) {
                  mergeInfoValue = SVNMergeInfoUtil.formatMergeInfoToString(tmpMergeInfo.getMergeSourcesToMergeLists(), null);
              }
            } else if (mergeInfoValue != null && previousMergeInfoValue == null && basePath != null &&
                    SVNRevision.isValidRevisionNumber(baseRevision)) {
                String[] queryPaths = new String[] { basePath };
                Map tmpCatalog = getMergeInfoManager().getMergeInfo(queryPaths, baseRoot, SVNMergeInfoInheritance.INHERITED, false);
                SVNMergeInfo tmpMergeInfo = (SVNMergeInfo) tmpCatalog.get(basePath);
                if (tmpMergeInfo != null) {
                    previousMergeInfoValue = SVNMergeInfoUtil.formatMergeInfoToString(tmpMergeInfo.getMergeSourcesToMergeLists(), null);
                }
            }
       
            if ((previousMergeInfoValue != null && mergeInfoValue == null) ||
                    (previousMergeInfoValue == null && mergeInfoValue != null) ||
                    (previousMergeInfoValue != null && mergeInfoValue != null &&
                            !previousMergeInfoValue.equals(mergeInfoValue))) {
                Map mergeInfo = null;
                Map previousMergeInfo = null;
                if (mergeInfoValue != null) {
                    mergeInfo = SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(mergeInfoValue), null);
                }
                if (previousMergeInfoValue != null) {
                    previousMergeInfo = SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(previousMergeInfoValue), null);
                }
                Map added = new SVNHashMap();
                Map deleted = new SVNHashMap();
                SVNMergeInfoUtil.diffMergeInfo(deleted, added, previousMergeInfo, mergeInfo, false);
               
                addedMergeInfo.put(changedPath, added);
                deletedMergeInfo.put(changedPath, deleted);
            }
        }
       
    }

    private LinkedList combineMergeInfoPathLists(Map mergeInfo) {
        List rangeListPaths = new LinkedList();
        for (Iterator pathsIter = mergeInfo.keySet().iterator(); pathsIter.hasNext();) {
            String path = (String) pathsIter.next();
            SVNMergeRangeList changes = (SVNMergeRangeList) mergeInfo.get(path);
            RangeListPath rangeListPath = new RangeListPath();
            rangeListPath.myPath = path;
            rangeListPath.myRangeList = changes.dup();
            SVNMergeRange[] rangesArray = rangeListPath.myRangeList.getRanges();
            for (int i = 0; i < rangesArray.length; i++) {
                SVNMergeRange range = rangesArray[i];
                range.setStartRevision(range.getStartRevision() + 1);
            }
            rangeListPaths.add(rangeListPath);
        }
       
        LinkedList combinedList = new LinkedList();
        Comparator rangeListPathsComparator = new Comparator() {
            public int compare(Object arg1, Object arg2) {
                RangeListPath rangeListPath1 = (RangeListPath) arg1;
                RangeListPath rangeListPath2 = (RangeListPath) arg2;
                SVNMergeRange[] ranges1 = rangeListPath1.myRangeList.getRanges();
                SVNMergeRange[] ranges2 = rangeListPath2.myRangeList.getRanges();
                SVNMergeRange range1 = ranges1[0];
                SVNMergeRange range2 = ranges2[0];
                if (range1.getStartRevision() < range2.getStartRevision()) {
                    return -1;
                }
                if (range1.getStartRevision() > range2.getStartRevision()) {
                    return 1;
                }
                if (range1.getEndRevision() < range2.getEndRevision()) {
                    return -1;
                }
                if (range1.getEndRevision() > range2.getEndRevision()) {
                    return 1;
                }
                return 0;
            }
        };
       
        while (rangeListPaths.size() > 1) {
            Collections.sort(rangeListPaths, rangeListPathsComparator);
            RangeListPath rangeListPath = (RangeListPath) rangeListPaths.get(0);
            RangeListPath firstRLP = rangeListPath;
            long youngest = rangeListPath.myRangeList.getRanges()[0].getStartRevision();
            long nextYoungest = youngest;
            int numRevs = 1;
            for (; nextYoungest == youngest; numRevs++) {
                if (numRevs == rangeListPaths.size()) {
                    numRevs++;
                    break;
                }
                rangeListPath = (RangeListPath) rangeListPaths.get(numRevs);
                nextYoungest = rangeListPath.myRangeList.getRanges()[0].getStartRevision();
            }
            numRevs--;
            long youngestEnd = firstRLP.myRangeList.getRanges()[0].getEndRevision();
            long tail = nextYoungest - 1;
            if (nextYoungest == youngest || youngestEnd < nextYoungest) {
                tail = youngestEnd;
            }

            PathListRange pathListRange = new PathListRange();
            pathListRange.myRange = new SVNMergeRange(youngest, tail, false);
            List paths = new LinkedList();
            for (int i = 0; i < numRevs; i++) {
                RangeListPath rp = (RangeListPath) rangeListPaths.get(i);
                paths.add(rp.myPath);
            }
            pathListRange.myPaths = (String[]) paths.toArray(new String[paths.size()]);
       
            combinedList.add(pathListRange);
           
            for (int i = 0; i < numRevs; i++) {
                RangeListPath rp = (RangeListPath) rangeListPaths.get(i);
                SVNMergeRange range = rp.myRangeList.getRanges()[0];
                range.setStartRevision(tail + 1);
                if (range.getStartRevision() > range.getEndRevision()) {
                    if (rp.myRangeList.getSize() == 1) {
                        rangeListPaths.remove(0);
                        i--;
                        numRevs--;
                    } else {
                        SVNMergeRange[] ranges = new SVNMergeRange[rp.myRangeList.getSize() - 1];
                        System.arraycopy(rp.myRangeList.getRanges(), 1, ranges, 0, ranges.length);
                        rp.myRangeList = new SVNMergeRangeList(ranges);
                    }
                }
            }
        }
       
        if (!rangeListPaths.isEmpty()) {
            RangeListPath firstRangeListPath = (RangeListPath) rangeListPaths.get(0);
            while (!firstRangeListPath.myRangeList.isEmpty()) {
                PathListRange pathListRange = new PathListRange();
                pathListRange.myPaths = new String[] { firstRangeListPath.myPath };
                pathListRange.myRange = firstRangeListPath.myRangeList.getRanges()[0];
                SVNMergeRange[] ranges = new SVNMergeRange[firstRangeListPath.myRangeList.getSize() - 1];
                System.arraycopy(firstRangeListPath.myRangeList.getRanges(), 1, ranges, 0, ranges.length);
                firstRangeListPath.myRangeList = new SVNMergeRangeList(ranges);
                combinedList.add(pathListRange);
            }
        }
       
        return combinedList;
    }

    private SVNMergeInfoManager getMergeInfoManager() {
        if (myMergeInfoManager == null) {
            myMergeInfoManager = new SVNMergeInfoManager();
        }
        return myMergeInfoManager;
    }
   
    private class RangeListPath {
        String myPath;
        SVNMergeRangeList myRangeList;
    }
   
    private class PathListRange {
        String myPaths[];
        SVNMergeRange myRange;
    }
   
    private class PathInfo {
        FSNodeHistory myHistory;
        boolean myIsDone;
        boolean myIsFirstTime;
        long myHistoryRevision;
        String myPath;
       
        public PathInfo getHistory(boolean strictNodeHistory, long start) throws SVNException {
            FSNodeHistory history = null;
            if (myHistory != null) {
                history = myHistory.getPreviousHistory(strictNodeHistory ? false : true);
                myHistory = history;
            } else {
                FSRevisionRoot historyRoot = myFSFS.createRevisionRoot(myHistoryRevision);
                history = historyRoot.getNodeHistory(myPath);
                history = history.getPreviousHistory(strictNodeHistory ? false : true);
                if (myIsFirstTime) {
                    myIsFirstTime = false;
                } else if (history != null) {
                    history = history.getPreviousHistory(strictNodeHistory ? false : true);
                }
            }

            if (history == null) {
                myIsDone = true;
                return this;
            }

            myPath = history.getHistoryEntry().getPath();
            myHistoryRevision = history.getHistoryEntry().getRevision();
           
            if (myHistoryRevision < start) {
                myIsDone = true;
            }
            return this;
        }

        public boolean checkHistory(long currentRevision, boolean strictNodeHistory,
                                    long start, boolean changed) throws SVNException {
            if (myIsDone) {
                return changed;
            }
           
            if (myHistoryRevision < currentRevision) {
                return changed;
            }
           
            changed = true;
            getHistory(strictNodeHistory, start);
            return changed;
        }
    }
   
}
TOP

Related Classes of org.tmatesoft.svn.core.internal.io.fs.FSLog$PathInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
ody>