public static long[] getRangeEndPoints(Map mergeInfo) { // long[] { youngestRange, oldestRange } long[] rangePoints = {SVNRepository.INVALID_REVISION, SVNRepository.INVALID_REVISION}; if (mergeInfo != null) { for (Iterator mergeInfoIter = mergeInfo.keySet().iterator(); mergeInfoIter.hasNext(); ) { String path = (String) mergeInfoIter.next(); SVNMergeRangeList rangeList = (SVNMergeRangeList) mergeInfo.get(path); if (!rangeList.isEmpty()) { SVNMergeRange[] ranges = rangeList.getRanges(); SVNMergeRange range = ranges[ranges.length - 1]; if (!SVNRevision.isValidRevisionNumber(rangePoints[0]) || range.getEndRevision() > rangePoints[0]) { rangePoints[0] = range.getEndRevision(); } range = ranges[0]; if (!SVNRevision.isValidRevisionNumber(rangePoints[1]) || rangePoints[1] > range.getStartRevision()) { rangePoints[1] = range.getStartRevision(); } } } } return rangePoints; }
public static SVNMergeRange[] parseRevisionList(StringBuffer mergeInfo, String path) throws SVNException { Collection ranges = new LinkedList(); while (mergeInfo.length() > 0 && mergeInfo.charAt(0) != '\n' && Character.isWhitespace(mergeInfo.charAt(0))) { mergeInfo = mergeInfo.deleteCharAt(0); } if (mergeInfo.length() == 0 || mergeInfo.charAt(0) == '\n') { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Mergeinfo for ''{0}'' maps to an empty revision range", path); SVNErrorManager.error(err, SVNLogType.DEFAULT); } while (mergeInfo.length() > 0 && mergeInfo.charAt(0) != '\n') { long startRev = parseRevision(mergeInfo); if (mergeInfo.length() > 0 && mergeInfo.charAt(0) != '\n' && mergeInfo.charAt(0) != '-' && mergeInfo.charAt(0) != ',' && mergeInfo.charAt(0) != '*') { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Invalid character ''{0}'' found in revision list", new Character(mergeInfo.charAt(0))); SVNErrorManager.error(err, SVNLogType.DEFAULT); } SVNMergeRange range = new SVNMergeRange(startRev - 1, startRev, true); if (mergeInfo.length() > 0 && mergeInfo.charAt(0) == '-') { mergeInfo = mergeInfo.deleteCharAt(0); long endRev = parseRevision(mergeInfo); if (startRev > endRev) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Unable to parse reversed revision range ''{0}-{1}''", new Object[] {new Long(startRev), new Long(endRev)}); SVNErrorManager.error(err, SVNLogType.DEFAULT); } else if (startRev == endRev) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Unable to parse revision range ''{0}-{1}'' with same start and end revisions", new Object[] {new Long(startRev), new Long(endRev)}); SVNErrorManager.error(err, SVNLogType.DEFAULT); } range.setEndRevision(endRev); } if (mergeInfo.length() == 0 || mergeInfo.charAt(0) == '\n') { ranges.add(range); return (SVNMergeRange[]) ranges.toArray(new SVNMergeRange[ranges.size()]); } else if (mergeInfo.length() > 0 && mergeInfo.charAt(0) == ',') { ranges.add(range); mergeInfo = mergeInfo.deleteCharAt(0); } else if (mergeInfo.length() > 0 && mergeInfo.charAt(0) == '*') { range.setInheritable(false); mergeInfo = mergeInfo.deleteCharAt(0); if (mergeInfo.length() == 0 || mergeInfo.charAt(0) == ',' || mergeInfo.charAt(0) == '\n') { ranges.add(range); if (mergeInfo.length() > 0 && mergeInfo.charAt(0) == ',') { mergeInfo = mergeInfo.deleteCharAt(0); } else { return (SVNMergeRange[]) ranges.toArray(new SVNMergeRange[ranges.size()]); } } else { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Invalid character ''{0}'' found in range list", mergeInfo.length() > 0 ? mergeInfo.charAt(0) + "" : ""); SVNErrorManager.error(err, SVNLogType.DEFAULT); } } else { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Invalid character ''{0}'' found in range list", mergeInfo.length() > 0 ? mergeInfo.charAt(0) + "" : ""); SVNErrorManager.error(err, SVNLogType.DEFAULT); } } if (mergeInfo.length() == 0 || mergeInfo.charAt(0) != '\n') { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Range list parsing ended before hitting newline"); SVNErrorManager.error(err, SVNLogType.DEFAULT); } return (SVNMergeRange[]) ranges.toArray(new SVNMergeRange[ranges.size()]); }
public static Map parseMergeInfo(StringBuffer mergeInfo, Map srcPathsToRangeLists) throws SVNException { srcPathsToRangeLists = srcPathsToRangeLists == null ? new TreeMap() : srcPathsToRangeLists; if (mergeInfo.length() == 0) { return srcPathsToRangeLists; } try { while (mergeInfo.length() > 0) { int eolInd = mergeInfo.indexOf("\n"); eolInd = eolInd < 0 ? mergeInfo.length() - 1 : eolInd; int ind = mergeInfo.lastIndexOf(":", eolInd); if (ind == -1) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Pathname not terminated by ':'"); SVNErrorManager.error(err, SVNLogType.DEFAULT); } if (ind == 0) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "No pathname preceding ':'"); SVNErrorManager.error(err, SVNLogType.DEFAULT); } String path = null; if (mergeInfo.charAt(0) == '/') { path = mergeInfo.substring(0, ind); } else { String relativePath = mergeInfo.substring(0, ind); path = "/" + relativePath; } mergeInfo = mergeInfo.delete(0, ind + 1); SVNMergeRange[] ranges = parseRevisionList(mergeInfo, path); if (mergeInfo.length() != 0 && mergeInfo.charAt(0) != '\n') { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Could not find end of line in range list line in ''{0}''", mergeInfo); SVNErrorManager.error(err, SVNLogType.DEFAULT); } if (mergeInfo.length() > 0) { mergeInfo = mergeInfo.deleteCharAt(0); } if (ranges.length > 1) { Arrays.sort(ranges); SVNMergeRange lastRange = ranges[0]; Collection newRanges = new ArrayList(); newRanges.add(lastRange); for (int i = 1; i < ranges.length; i++) { SVNMergeRange range = ranges[i]; if (lastRange.getStartRevision() <= range.getEndRevision() && range.getStartRevision() <= lastRange.getEndRevision()) { if (range.getStartRevision() < lastRange.getEndRevision() && range.isInheritable() != lastRange.isInheritable()) { // error. String r1 = lastRange.toString(); String r2 = range.toString(); SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Unable to parse overlapping revision ranges ''{0}'' and ''{1}'' with different inheritance types", new Object[] {r1, r2}); SVNErrorManager.error(err, SVNLogType.WC); } if (lastRange.isInheritable() == range.isInheritable()) { lastRange.setEndRevision( Math.max(range.getEndRevision(), lastRange.getEndRevision())); continue; } } newRanges.add(ranges[i]); lastRange = ranges[i]; } ranges = (SVNMergeRange[]) newRanges.toArray(new SVNMergeRange[newRanges.size()]); } SVNMergeRangeList existingRange = (SVNMergeRangeList) srcPathsToRangeLists.get(path); if (existingRange != null) { ranges = existingRange.merge(new SVNMergeRangeList(ranges)).getRanges(); } srcPathsToRangeLists.put(path, new SVNMergeRangeList(ranges)); } } catch (SVNException svne) { if (svne.getErrorMessage().getErrorCode() != SVNErrorCode.MERGE_INFO_PARSE_ERROR) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.MERGE_INFO_PARSE_ERROR, "Could not parse mergeinfo string ''{0}''", mergeInfo.toString()); SVNErrorManager.error(err, svne, SVNLogType.DEFAULT); } throw svne; } return srcPathsToRangeLists; }