public Object[] calculateRemainingRangeList(File targetFile, SVNEntry entry, SVNURL sourceRoot, boolean[] indirect, SVNURL url1, long revision1, SVNURL url2, long revision2, SVNMergeRange range) throws SVNException { SVNMergeRangeList remainingRangeList = null; Map targetMergeInfo = null; Map implicitMergeInfo = null; boolean honorMergeInfo = isHonorMergeInfo(); if (honorMergeInfo) { MergePath mergeTarget = new MergePath(targetFile); myRepository1.setLocation(entry.getSVNURL(), false); Map[] fullMergeInfo = getFullMergeInfo(entry, true, true, indirect, SVNMergeInfoInheritance.INHERITED, myRepository1, targetFile, Math.max(revision1, revision2), Math.min(revision1, revision2)); targetMergeInfo = fullMergeInfo[0]; implicitMergeInfo = fullMergeInfo[1]; myRepository1.setLocation(url1, false); if (!myIsRecordOnly) { calculateRemainingRanges(null, mergeTarget, sourceRoot, url1, revision1, url2, revision2, targetMergeInfo, myImplicitSrcGap, false, false, entry, myRepository1); remainingRangeList = mergeTarget.myRemainingRanges; } } if (!honorMergeInfo || myIsRecordOnly) { remainingRangeList = new SVNMergeRangeList(range); } return new Object[]{remainingRangeList, targetMergeInfo, implicitMergeInfo}; }
myWCAccess = createWCAccess(); targetWCPath = targetWCPath.getAbsoluteFile(); try { SVNAdminArea adminArea = myWCAccess.probeOpen(targetWCPath, !dryRun, SVNWCAccess.INFINITE_DEPTH); SVNEntry targetEntry = myWCAccess.getVersionedEntry(targetWCPath, false); SVNURL url = srcURL == null ? getURL(srcPath) : srcURL; if (url == null) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, SVNURL wcReposRoot = getReposRoot(targetWCPath, null, SVNRevision.WORKING, adminArea, myWCAccess); List mergeSources = null; SVNRepository repository = null; SVNURL sourceReposRoot = null; try { repository = createRepository(url, null, null, true); sourceReposRoot = repository.getRepositoryRoot(true); mergeSources = normalizeMergeSources(srcPath, url, sourceReposRoot, pegRevision, rangesToMerge, repository); } finally { doMerge(null, mergeSources, targetWCPath, targetEntry, adminArea, true, true, wcReposRoot.equals(sourceReposRoot), ignoreAncestry, force, dryRun, recordOnly, false, depth);
protected SVNRepository ensureRepository(SVNRepository repository, SVNURL url) throws SVNException { if (repository != null) { try { ensureSessionURL(repository, url); return repository; } catch (SVNException e) { // } repository = null; } if (repository == null) { repository = createRepository(url, null, null, false); } return repository; }
protected Map getMergeInfo(SVNURL url, SVNRevision pegRevision, SVNURL repositoryRoot[]) throws SVNException { SVNRepository repository = null; try { repository = createRepository(url, null, null, true); long revisionNum = getRevisionNumber(pegRevision, repository, null); SVNURL reposRoot = repository.getRepositoryRoot(true); if (repositoryRoot != null && repositoryRoot.length > 0) { repositoryRoot[0] = reposRoot; } String relPath = getPathRelativeToRoot(null, url, reposRoot, null, null); return getReposMergeInfo(repository, relPath, revisionNum, SVNMergeInfoInheritance.INHERITED, false); } finally { if (repository != null) { repository.closeSession(); } } }
protected Map getMergeInfo(SVNURL url, SVNRevision pegRevision, SVNURL repositoryRoot[]) throws SVNException { SVNRepository repository = null; try { repository = createRepository(url, null, null, true); long revisionNum = getRevisionNumber(pegRevision, repository, null); SVNURL reposRoot = repository.getRepositoryRoot(true); if (repositoryRoot != null && repositoryRoot.length > 0) { repositoryRoot[0] = reposRoot; } String relPath = getPathRelativeToSession(url, null, repository); if (relPath == null) { repository.setLocation(url, false); relPath = ""; } return getReposMergeInfo(repository, relPath, revisionNum, SVNMergeInfoInheritance.INHERITED, false); } finally { if (repository != null) { repository.closeSession(); } } }
boolean isRollBack = revision1 > revision2; SVNURL primaryURL = isRollBack ? url1 : url2; boolean honorMergeInfo = isHonorMergeInfo(); boolean recordMergeInfo = isRecordMergeInfo(); myIsSingleFileMerge = true; boolean[] indirect = { false }; mergeInfoPath = getPathRelativeToRoot(null, primaryURL, sourceRootURL, null, null); Object[] mergeInfoBundle = calculateRemainingRangeList(targetWCPath, entry, sourceRootURL, indirect, url1, revision1, url2, revision2, range); SVNMergeRangeList remainingRangeList = (SVNMergeRangeList) mergeInfoBundle[0]; AbstractDiffCallback callback = getMergeCallback(adminArea); SVNMergeRangeList rangeListToMerge = remainingRangeList; if (myAreSourcesAncestral && remainingRangeList.getSize() > 1) { SVNURL oldSessionURL = ensureSessionURL(myRepository1, primaryURL); rangeListToMerge = removeNoOpMergeRanges(myRepository1, remainingRangeList); if (oldSessionURL != null) { myRepository1.setLocation(oldSessionURL, false); f1 = loadFile(repos1, nextRange.getStartRevision(), props1, adminArea); f2 = loadFile(repos2, nextRange.getEndRevision(), props2, adminArea); props1 = filterProperties(props1, true, false, false); props2 = filterProperties(props2, true, false, false); SVNProperties propsDiff = computePropsDiff(props1, props2);
protected void runMergeReintegrate(SVNURL srcURL, File srcPath, SVNRevision pegRevision, File targetWCPath, boolean dryRun) throws SVNException { myWCAccess = createWCAccess(); targetWCPath = targetWCPath.getAbsoluteFile(); try { SVNAdminArea adminArea = myWCAccess.probeOpen(targetWCPath, !dryRun, SVNWCAccess.INFINITE_DEPTH); SVNEntry targetEntry = myWCAccess.getVersionedEntry(targetWCPath, false); SVNURL url2 = srcURL == null ? getURL(srcPath) : srcURL; if (url2 == null) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, SVNURL wcReposRoot = getReposRoot(targetWCPath, null, SVNRevision.WORKING, adminArea, myWCAccess); SVNRepository repository = null; SVNURL sourceReposRoot = null; try { repository = createRepository(wcReposRoot, null, null, true); sourceReposRoot = repository.getRepositoryRoot(true); if (!wcReposRoot.equals(sourceReposRoot)) { ensureWCReflectsRepositorySubTree(targetWCPath); long[] rev1 = { targetEntry.getRevision() }; String sourceReposRelPath = getPathRelativeToRoot(null, url2, null, null, repository); String targetReposRelPath = getPathRelativeToRoot(targetWCPath, null, wcReposRoot, null, repository); long rev2 = getRevisionNumber(pegRevision, repository, srcPath); SVNURL[] url1 = { null }; Map unmergedToSourceMergeInfoCatalog = calculateLeftHandSide(url1, rev1, targetReposRelPath, handler.getSubTreesWithMergeInfoPaths(), rev1[0], sourceReposRelPath, sourceReposRoot, rev2, repository);
myWCAccess = createWCAccess(); targetWCPath = targetWCPath.getAbsoluteFile(); try { SVNURL wcReposRoot = getReposRoot(targetWCPath, null, SVNRevision.WORKING, adminArea, myWCAccess); repository1 = createRepository(url1, null, null, false); SVNURL sourceReposRoot = repository1.getRepositoryRoot(true); long rev1 = getRevisionNumber(revision1, latestRev, repository1, null); repository2 = createRepository(url2, null, null, false); long rev2 = getRevisionNumber(revision2, latestRev, repository2, null); long youngestCommonRevision = SVNRepository.INVALID_REVISION; if (!ignoreAncestry) { SVNLocationEntry youngestLocation = getYoungestCommonAncestor(null, url1, rev1, null, url2, rev2); youngestCommonPath = youngestLocation.getPath(); range = new SVNRevisionRange(sRev, eRev); ranges.add(range); mergeSources = normalizeMergeSources(null, url1, sourceReposRoot, sRev, ranges, repository1); } else if (youngestCommonURL.equals(url1) && youngestCommonRevision == rev1) { range = new SVNRevisionRange(sRev, eRev); ranges.add(range); mergeSources = normalizeMergeSources(null, url2, sourceReposRoot, eRev, ranges, repository2);
MergeSource mergeSource = myMergeDriver.getCurrentMergeSource(); if (mergeSource.getRevision1() < mergeSource.getRevision2() || !myMergeDriver.myAreSourcesAncestral) { SVNProperties filteredProps = myMergeDriver.filterSelfReferentialMergeInfo(regularProps, file); if (filteredProps != null) { regularProps = filteredProps; SVNPropertyValue mergeInfoProp = originalProperties.getSVNPropertyValue(SVNProperty.MERGE_INFO); if (mergeInfoProp == null && propValue != null) { myMergeDriver.addPathWithNewMergeInfo(file); } else if (mergeInfoProp != null && propValue == null) { myMergeDriver.addPathWithDeletedMergeInfo(file);
protected Map getMergeInfo(File path, SVNRevision pegRevision, SVNURL repositoryRoot[]) throws SVNException { SVNWCAccess wcAccess = createWCAccess(); try { SVNAdminArea adminArea = wcAccess.probeOpen(path, false, 0); SVNEntry entry = wcAccess.getVersionedEntry(path, false); long revNum[] = { SVNRepository.INVALID_REVISION }; SVNURL url = getEntryLocation(path, entry, revNum, SVNRevision.WORKING); SVNRepository repository = null; try { repository = createRepository(url, null, null, false); repository.assertServerIsMergeInfoCapable(path.toString()); } finally { repository.closeSession(); } SVNURL reposRoot = getReposRoot(path, null, pegRevision, adminArea, wcAccess); if (repositoryRoot != null && repositoryRoot.length > 0) { repositoryRoot[0] = reposRoot; } boolean[] indirect = { false }; return getWCOrRepositoryMergeInfo(path, entry, SVNMergeInfoInheritance.INHERITED, indirect, false, null); } finally { wcAccess.close(); } }
result[0] = getWCOrRepositoryMergeInfo(target, entry, inherit, indirect, false, repos); long[] targetRev = new long[1]; targetRev[0] = SVNRepository.INVALID_REVISION; SVNURL url = deriveLocation(target, null, targetRev, SVNRevision.WORKING, repos, myWCAccess); if (targetRev[0] <= end) { result[1] = new TreeMap();//implicit merge info try { if (repos != null) { sessionURL = ensureSessionURL(repos, url); } else { repos = createRepository(url, null, null, false); closeSession = true; getLocations(url, null, repos, SVNRevision.create(targetRev[0]), SVNRevision.create(start), SVNRevision.UNDEFINED); targetRev[0] = start; result[1] = getHistoryAsMergeInfo(url, null, SVNRevision.create(targetRev[0]), start, end, repos, null); if (sessionURL != null) {
private List normalizeMergeSources(File source, SVNURL sourceURL, SVNURL sourceRootURL, SVNRevision pegRevision, Collection rangesToMerge, SVNRepository repository) throws SVNException { long youngestRevision[] = { SVNRepository.INVALID_REVISION }; long pegRevNum = getRevisionNumber(pegRevision, youngestRevision, repository, source); if (!SVNRevision.isValidRevisionNumber(pegRevNum)) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CLIENT_BAD_REVISION); long rangeStartRev = getRevisionNumber(rangeStart, youngestRevision, repository, source); long rangeEndRev = getRevisionNumber(rangeEnd, youngestRevision, repository, source); if (rangeStartRev != rangeEndRev) { SVNMergeRange range = new SVNMergeRange(rangeStartRev, rangeEndRev, true); getLocations(sourceURL, null, repository, SVNRevision.create(pegRevNum), SVNRevision.create(youngestRequestedRev), SVNRevision.UNDEFINED); pegRevNum = youngestRequestedRev; SVNLocationSegment segment2 = (SVNLocationSegment) segments.get(1); SVNURL segmentURL = sourceRootURL.appendPath(segment2.getPath(), false); SVNLocationEntry copyFromLocation = getCopySource(null, segmentURL, SVNRevision.create(segment2.getStartRevision())); String copyFromPath = copyFromLocation.getPath(); List mergeSources = combineRangeWithSegments(range, segmentsArray, sourceRootURL); resultMergeSources.addAll(mergeSources);
public Map calculateImplicitMergeInfo(SVNRepository repos, SVNURL url, long[] targetRev, long start, long end) throws SVNException { Map implicitMergeInfo = null; boolean closeSession = false; SVNURL sessionURL = null; try { if (repos != null) { sessionURL = ensureSessionURL(repos, url); } else { repos = createRepository(url, null, null, false); closeSession = true; } if (targetRev[0] < start) { getLocations(url, null, repos, SVNRevision.create(targetRev[0]), SVNRevision.create(start), SVNRevision.UNDEFINED); targetRev[0] = start; } implicitMergeInfo = getHistoryAsMergeInfo(url, null, SVNRevision.create(targetRev[0]), start, end, repos, null); if (sessionURL != null) { repos.setLocation(sessionURL, false); } } finally { if (closeSession) { repos.closeSession(); } } return implicitMergeInfo; }
Map adjustedTargetMergeInfo = null; String mergeInfoPath = getPathRelativeToRoot(null, primaryURL, sourceRootURL, null, repository); if (implicitSrcGap != null && child.myPreMergeMergeInfo != null) { SVNMergeRangeList explicitMergeInfoGapRanges = (SVNMergeRangeList) child.myPreMergeMergeInfo.get(mergeInfoPath); adjustedTargetMergeInfo = targetMergeInfo; filterMergedRevisions(child, mergeInfoPath, adjustedTargetMergeInfo, implicitMergeInfo, revision1, revision2); SVNMergeRangeList addedRangeList = rangeListDiff[1]; if (!deletedRangeList.isEmpty() || !addedRangeList.isEmpty()) { adjustDeletedSubTreeRanges(child, parent, revision1, revision2, primaryURL, repository); SVNRepositoryLocation[] locations = null; try { locations = getLocations(url1, null, repository, SVNRevision.create(revision1), SVNRevision.create(entry.getRevision()), SVNRevision.UNDEFINED); SVNURL startURL = locations[0].getURL();
if (index == 0) { boolean indirect[] = { false }; Map[] mergeInfo = getFullMergeInfo(childEntry, false, true, indirect, SVNMergeInfoInheritance.INHERITED, repository, child.myPath, Math.max(revision1, revision2), Math.min(revision1, revision2)); child.myImplicitMergeInfo = mergeInfo[1]; } else { int parentIndex = findNearestAncestor(myChildrenWithMergeInfo.toArray(), false, child.myPath); MergePath parent = (MergePath) myChildrenWithMergeInfo.get(parentIndex); boolean childInheritsImplicit = parent != null && !child.myIsSwitched; ensureImplicitMergeinfo(parent, child, childInheritsImplicit, childEntry, revision1, revision2, repository); findGapsInMergeSourceHistory(gap, parentMergeSrcCanonPath, url1, revision1, url2, revision2, repository); if (gap[0] >= 0 && gap[1] >= 0) { myImplicitSrcGap = new SVNMergeRangeList(gap[0], gap[1], true); Map mergeInfo[] = getFullMergeInfo(childEntry, true, index == 0, indirect, SVNMergeInfoInheritance.INHERITED, repository, child.myPath, Math.max(revision1, revision2), Math.min(revision1, revision2)); int parentIndex = findNearestAncestor(childrenWithMergeInfoArray, false, child.myPath); if (parentIndex >= 0 && parentIndex < childrenWithMergeInfoArray.length) { parent = (MergePath) childrenWithMergeInfoArray[parentIndex]; calculateRemainingRanges(parent, child, sourceRootURL, childURL1, revision1, childURL2, revision2, child.myPreMergeMergeInfo, myImplicitSrcGap, index > 0, childInheritsImplicit, childEntry, repository);
public Map getHistoryAsMergeInfo(SVNURL url, File path, SVNRevision pegRevision, long rangeYoungest, long rangeOldest, SVNRepository repos, SVNWCAccess access) throws SVNException { long[] pegRevNum = new long[1]; pegRevNum[0] = SVNRepository.INVALID_REVISION; url = deriveLocation(path, url, pegRevNum, pegRevision, repos, access); boolean closeSession = false; try { if (repos == null) { repos = createRepository(url, null, null, false); closeSession = true; } if (!SVNRevision.isValidRevisionNumber(rangeYoungest)) { rangeYoungest = pegRevNum[0]; } if (!SVNRevision.isValidRevisionNumber(rangeOldest)) { rangeOldest = 0; } Collection segments = repos.getLocationSegments("", pegRevNum[0], rangeYoungest, rangeOldest); return getMergeInfoFromSegments(segments); } finally { if (closeSession) { repos.closeSession(); } } }
protected void getLogsForMergeInfoRangeList(SVNURL reposRootURL, String[] paths, SVNMergeRangeList rangeList, boolean discoverChangedPaths, String[] revProps, ISVNLogEntryHandler handler) throws SVNException { if (rangeList.isEmpty()) { return; } SVNMergeRange[] listRanges = rangeList.getRanges(); Arrays.sort(listRanges); SVNMergeRange youngestRange = listRanges[listRanges.length - 1]; SVNRevision youngestRev = SVNRevision.create(youngestRange.getEndRevision()); SVNMergeRange oldestRange = listRanges[0]; SVNRevision oldestRev = SVNRevision.create(oldestRange.getStartRevision()); LogHandlerFilter filterHandler = new LogHandlerFilter(handler, rangeList); SVNLogClient logClient = getLogClient(); logClient.doLog(reposRootURL, paths, youngestRev, oldestRev, youngestRev, false, discoverChangedPaths, false, 0, revProps, filterHandler); checkCancelled(); }
protected SVNLocationEntry getCopySource(File path, SVNURL url, SVNRevision revision) throws SVNException { long[] pegRev = { SVNRepository.INVALID_REVISION }; SVNRepository repos = createRepository(url, path, null, revision, revision, pegRev); SVNLocationEntry copyFromEntry = null; String targetPath = getPathRelativeToRoot(path, url, null, null, repos); CopyFromReceiver receiver = new CopyFromReceiver(targetPath); try { repos.log(new String[] { "" }, pegRev[0], 1, true, true, 0, false, new String[0], receiver); copyFromEntry = receiver.getCopyFromLocation(); } catch (SVNException e) { SVNErrorCode errCode = e.getErrorMessage().getErrorCode(); if (errCode == SVNErrorCode.FS_NOT_FOUND || errCode == SVNErrorCode.RA_DAV_REQUEST_FAILED) { return new SVNLocationEntry(SVNRepository.INVALID_REVISION, null); } throw e; } return copyFromEntry == null ? new SVNLocationEntry(SVNRepository.INVALID_REVISION, null) : copyFromEntry; }
Map mergeInfo[] = getFullMergeInfo(childEntry, indirect, SVNMergeInfoInheritance.INHERITED, repository, child.myPath, Math.max(revision1, revision2), Math.min(revision1, revision2)); child.myPreMergeMergeInfo = mergeInfo[0]; int parentIndex = findNearestAncestor(childrenWithMergeInfoArray, false, child.myPath); if (parentIndex >= 0 && parentIndex < childrenWithMergeInfoArray.length) { parent = (MergePath) childrenWithMergeInfoArray[parentIndex]; calculateRemainingRanges(parent, child, sourceRootURL, childURL1, revision1, childURL2, revision2, child.myPreMergeMergeInfo, child.myImplicitMergeInfo, index > 0, childEntry, repository);
private void fixDeletedSubtreeRanges(SVNURL url1, long revision1, SVNURL url2, long revision2, SVNRepository repository) throws SVNException { boolean isRollback = revision2 < revision1; SVNURL sourceRootUrl = repository.getRepositoryRoot(true); Object[] array= myChildrenWithMergeInfo.toArray(); for (Iterator iterator = myChildrenWithMergeInfo.iterator(); iterator.hasNext(); ) { MergePath child = (MergePath) iterator.next(); if (child.myIsAbsent) { continue; } int parentIndex = findNearestAncestor(array, false, child.myPath); MergePath parent = (MergePath) array[parentIndex]; if (isRollback) { child.myRemainingRanges = child.myRemainingRanges.reverse(); parent.myRemainingRanges = parent.myRemainingRanges.reverse(); } SVNMergeRangeList added = child.myRemainingRanges.diff(parent.myRemainingRanges, true); SVNMergeRangeList deleted = parent.myRemainingRanges.diff(child.myRemainingRanges, true); if (isRollback) { child.myRemainingRanges = child.myRemainingRanges.reverse(); parent.myRemainingRanges = parent.myRemainingRanges.reverse(); } if (!added.isEmpty() || !deleted.isEmpty()) { String childReposSrcPath = SVNWCUtils.getPathAsChild(myTarget, child.myPath); SVNURL childPrimarySrcUrl = revision1 < revision2 ? url2 : url1; childPrimarySrcUrl = childPrimarySrcUrl.appendPath(childReposSrcPath, false); adjustDeletedSubTreeRanges(child, parent, revision1, revision2, childPrimarySrcUrl, repository); } } }