From e9968ac59f426ee83fadf2aafdd22626eb4c9267 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 29 Jan 2015 20:44:21 +0300 Subject: [PATCH] svn: Refactoring - removed OneRecursiveShotMergeInfoWorker, corresponding logic moved to OneShotMergeInfoHelper --- .../idea/svn/integrate/MergeContext.java | 9 + .../OneRecursiveShotMergeInfoWorker.java | 184 ------------------ .../svn/mergeinfo/OneShotMergeInfoHelper.java | 152 ++++++++++++++- 3 files changed, 157 insertions(+), 188 deletions(-) delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeContext.java index c4729c7a2d0f..11dfb1aeb9c8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeContext.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeContext.java @@ -18,8 +18,10 @@ package org.jetbrains.idea.svn.integrate; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.dialogs.WCInfo; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; /** * @author Konstantin Kolosovsky. @@ -33,6 +35,7 @@ public class MergeContext { @NotNull private final String mySourceUrl; @NotNull private final SvnVcs myVcs; @NotNull private final String myTitle; + @NotNull private final String myRepositoryRelativeSourcePath; public MergeContext(@NotNull SvnVcs vcs, @NotNull String sourceUrl, @@ -46,6 +49,7 @@ public class MergeContext { mySourceUrl = sourceUrl; myWcInfo = wcInfo; myTitle = "Merge from " + myBranchName; + myRepositoryRelativeSourcePath = SvnUtil.ensureStartSlash(SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), mySourceUrl)); } @NotNull @@ -73,6 +77,11 @@ public class MergeContext { return mySourceUrl; } + @NotNull + public String getRepositoryRelativeSourcePath() { + return myRepositoryRelativeSourcePath; + } + @NotNull public SvnVcs getVcs() { return myVcs; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java deleted file mode 100644 index c88f34204ab8..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn.mergeinfo; - -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vcs.AreaMap; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.util.ObjectUtils; -import com.intellij.util.PairProcessor; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.svn.SvnPropertyKeys; -import org.jetbrains.idea.svn.SvnUtil; -import org.jetbrains.idea.svn.api.Depth; -import org.jetbrains.idea.svn.commandLine.SvnBindException; -import org.jetbrains.idea.svn.integrate.MergeContext; -import org.jetbrains.idea.svn.properties.PropertyConsumer; -import org.jetbrains.idea.svn.properties.PropertyData; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.wc.SVNRevision; -import org.tmatesoft.svn.core.wc2.SvnTarget; - -import java.io.File; -import java.util.Map; - -public class OneRecursiveShotMergeInfoWorker { - - @NotNull private final MergeContext myMergeContext; - - // subpath [file] (local) to (subpathURL - merged FROM - to ranges list) - @NotNull private final AreaMap> myMergeInfoMap; - @NotNull private final Object myLock; - @NotNull private final String myRepositoryRelativeSourcePath; - - public OneRecursiveShotMergeInfoWorker(@NotNull MergeContext mergeContext) { - myMergeContext = mergeContext; - myLock = new Object(); - // TODO: Rewrite without AreaMap usage - myMergeInfoMap = AreaMap.create(new PairProcessor() { - public boolean process(String parentUrl, String childUrl) { - if (".".equals(parentUrl)) return true; - return SVNPathUtil.isAncestor(SvnUtil.ensureStartSlash(parentUrl), SvnUtil.ensureStartSlash(childUrl)); - } - }); - myRepositoryRelativeSourcePath = - SvnUtil.ensureStartSlash(SVNPathUtil.getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl())); - } - - public void prepare() throws VcsException { - Depth depth = Depth.allOrEmpty(myMergeContext.getVcs().getSvnConfiguration().isCheckNestedForQuickMerge()); - File file = myMergeContext.getWcInfo().getRootInfo().getIoFile(); - - myMergeContext.getVcs().getFactory(file).createPropertyClient() - .getProperty(SvnTarget.fromFile(file), SvnPropertyKeys.MERGE_INFO, SVNRevision.WORKING, depth, createPropertyHandler()); - } - - @NotNull - private PropertyConsumer createPropertyHandler() { - return new PropertyConsumer() { - public void handleProperty(@NotNull File path, @NotNull PropertyData property) throws SVNException { - String workingCopyRelativePath = getWorkingCopyRelativePath(path); - Map mergeInfo; - - try { - mergeInfo = BranchInfo.parseMergeInfo(ObjectUtils.assertNotNull(property.getValue())); - } - catch (SvnBindException e) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.MERGE_INFO_PARSE_ERROR, e), e); - } - - synchronized (myLock) { - myMergeInfoMap.put(toKey(workingCopyRelativePath), mergeInfo); - } - } - - public void handleProperty(SVNURL url, PropertyData property) throws SVNException { - } - - public void handleProperty(long revision, PropertyData property) throws SVNException { - } - }; - } - - @NotNull - public SvnMergeInfoCache.MergeCheckResult isMerged(@NotNull String repositoryRelativePath, long revisionNumber) { - String sourceRelativePath = - SVNPathUtil.getRelativePath(myRepositoryRelativeSourcePath, SvnUtil.ensureStartSlash(repositoryRelativePath)); - SvnMergeInfoCache.MergeCheckResult result; - - if (sourceRelativePath == null) { - // TODO: SVNPathUtil.getRelativePath() is @NotNull - probably we need to check also isEmpty() here? - result = SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS; - } - else { - InfoProcessor processor = new InfoProcessor(sourceRelativePath, myRepositoryRelativeSourcePath, revisionNumber); - - synchronized (myLock) { - myMergeInfoMap.getSimiliar(toKey(sourceRelativePath), processor); - } - - result = SvnMergeInfoCache.MergeCheckResult.getInstance(processor.isMerged()); - } - - return result; - } - - private static class InfoProcessor implements PairProcessor> { - - @NotNull private final String myRepositoryRelativeSourcePath; - private boolean myIsMerged; - @NotNull private final String mySourceRelativePath; - private final long myRevisionNumber; - - public InfoProcessor(@NotNull String sourceRelativePath, @NotNull String repositoryRelativeSourcePath, long revisionNumber) { - mySourceRelativePath = sourceRelativePath; - myRevisionNumber = revisionNumber; - myRepositoryRelativeSourcePath = SvnUtil.ensureStartSlash(repositoryRelativeSourcePath); - } - - public boolean isMerged() { - return myIsMerged; - } - - // TODO: Try to unify with BranchInfo.processMergeinfoProperty() - public boolean process(@NotNull String workingCopyRelativePath, @NotNull Map mergedPathsMap) { - boolean processed = false; - final boolean isCurrentPath = workingCopyRelativePath.equals(mySourceRelativePath); - - if (mergedPathsMap.isEmpty()) { - myIsMerged = false; - processed = true; - } - else { - String mergedPathAffectingSourcePath = ContainerUtil.find(mergedPathsMap.keySet(), new Condition() { - @Override - public boolean value(String path) { - return SVNPathUtil.isAncestor(myRepositoryRelativeSourcePath, SvnUtil.ensureStartSlash(path)); - } - }); - - if (mergedPathAffectingSourcePath != null) { - SVNMergeRangeList mergeRangeList = mergedPathsMap.get(mergedPathAffectingSourcePath); - - processed = true; - myIsMerged = ContainerUtil.or(mergeRangeList.getRanges(), new Condition() { - @Override - public boolean value(@NotNull SVNMergeRange range) { - return BranchInfo.isInRange(range, myRevisionNumber) && (range.isInheritable() || isCurrentPath); - } - }); - } - } - - return processed; - } - } - - @NotNull - private String getWorkingCopyRelativePath(@NotNull File file) { - return FileUtil.toSystemIndependentName( - ObjectUtils.assertNotNull(FileUtil.getRelativePath(myMergeContext.getWcInfo().getRootInfo().getIoFile(), file))); - } - - @NotNull - private static String toKey(@NotNull String path) { - return SystemInfo.isFileSystemCaseSensitive ? path : path.toUpperCase(); - } -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java index 2d0a1d2fcb24..bdd13c820acb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java @@ -15,29 +15,61 @@ */ package org.jetbrains.idea.svn.mergeinfo; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vcs.AreaMap; import com.intellij.openapi.vcs.VcsException; +import com.intellij.util.ObjectUtils; +import com.intellij.util.PairProcessor; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnPropertyKeys; +import org.jetbrains.idea.svn.SvnUtil; +import org.jetbrains.idea.svn.api.Depth; +import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.integrate.MergeContext; +import org.jetbrains.idea.svn.properties.PropertyConsumer; +import org.jetbrains.idea.svn.properties.PropertyData; +import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; +import java.io.File; import java.util.Collection; import java.util.Map; import java.util.Set; public class OneShotMergeInfoHelper implements MergeChecker { - @NotNull private final OneRecursiveShotMergeInfoWorker myWorker; + @NotNull private final MergeContext myMergeContext; @NotNull private final Map> myPartiallyMerged; + // subpath [file] (local) to (subpathURL - merged FROM - to ranges list) + @NotNull private final AreaMap> myMergeInfoMap; + @NotNull private final Object myMergeInfoLock; public OneShotMergeInfoHelper(@NotNull MergeContext mergeContext) { - myWorker = new OneRecursiveShotMergeInfoWorker(mergeContext); + myMergeContext = mergeContext; myPartiallyMerged = ContainerUtil.newHashMap(); + myMergeInfoLock = new Object(); + // TODO: Rewrite without AreaMap usage + myMergeInfoMap = AreaMap.create(new PairProcessor() { + public boolean process(String parentUrl, String childUrl) { + if (".".equals(parentUrl)) return true; + return SVNPathUtil.isAncestor(SvnUtil.ensureStartSlash(parentUrl), SvnUtil.ensureStartSlash(childUrl)); + } + }); } public void prepare() throws VcsException { - myWorker.prepare(); + Depth depth = Depth.allOrEmpty(myMergeContext.getVcs().getSvnConfiguration().isCheckNestedForQuickMerge()); + File file = myMergeContext.getWcInfo().getRootInfo().getIoFile(); + + myMergeContext.getVcs().getFactory(file).createPropertyClient() + .getProperty(SvnTarget.fromFile(file), SvnPropertyKeys.MERGE_INFO, SVNRevision.WORKING, depth, createPropertyHandler()); } @Nullable @@ -52,7 +84,7 @@ public class OneShotMergeInfoHelper implements MergeChecker { for (String path : changeList.getAffectedPaths()) { //noinspection EnumSwitchStatementWhichMissesCases - switch (myWorker.isMerged(path, changeList.getNumber())) { + switch (checkPath(path, changeList.getNumber())) { case MERGED: hasMergedPaths = true; break; @@ -70,4 +102,116 @@ public class OneShotMergeInfoHelper implements MergeChecker { ? hasMergedPaths ? SvnMergeInfoCache.MergeCheckResult.MERGED : SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS : SvnMergeInfoCache.MergeCheckResult.NOT_MERGED; } + + @NotNull + public SvnMergeInfoCache.MergeCheckResult checkPath(@NotNull String repositoryRelativePath, long revisionNumber) { + String sourceRelativePath = + SVNPathUtil.getRelativePath(myMergeContext.getRepositoryRelativeSourcePath(), SvnUtil.ensureStartSlash(repositoryRelativePath)); + SvnMergeInfoCache.MergeCheckResult result; + + if (sourceRelativePath == null) { + // TODO: SVNPathUtil.getRelativePath() is @NotNull - probably we need to check also isEmpty() here? + result = SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS; + } + else { + InfoProcessor processor = new InfoProcessor(sourceRelativePath, myMergeContext.getRepositoryRelativeSourcePath(), revisionNumber); + + synchronized (myMergeInfoLock) { + myMergeInfoMap.getSimiliar(toKey(sourceRelativePath), processor); + } + + result = SvnMergeInfoCache.MergeCheckResult.getInstance(processor.isMerged()); + } + + return result; + } + + private static class InfoProcessor implements PairProcessor> { + + @NotNull private final String myRepositoryRelativeSourcePath; + private boolean myIsMerged; + @NotNull private final String mySourceRelativePath; + private final long myRevisionNumber; + + public InfoProcessor(@NotNull String sourceRelativePath, @NotNull String repositoryRelativeSourcePath, long revisionNumber) { + mySourceRelativePath = sourceRelativePath; + myRevisionNumber = revisionNumber; + myRepositoryRelativeSourcePath = SvnUtil.ensureStartSlash(repositoryRelativeSourcePath); + } + + public boolean isMerged() { + return myIsMerged; + } + + // TODO: Try to unify with BranchInfo.processMergeinfoProperty() + public boolean process(@NotNull String workingCopyRelativePath, @NotNull Map mergedPathsMap) { + boolean processed = false; + final boolean isCurrentPath = workingCopyRelativePath.equals(mySourceRelativePath); + + if (mergedPathsMap.isEmpty()) { + myIsMerged = false; + processed = true; + } + else { + String mergedPathAffectingSourcePath = ContainerUtil.find(mergedPathsMap.keySet(), new Condition() { + @Override + public boolean value(String path) { + return SVNPathUtil.isAncestor(myRepositoryRelativeSourcePath, SvnUtil.ensureStartSlash(path)); + } + }); + + if (mergedPathAffectingSourcePath != null) { + SVNMergeRangeList mergeRangeList = mergedPathsMap.get(mergedPathAffectingSourcePath); + + processed = true; + myIsMerged = ContainerUtil.or(mergeRangeList.getRanges(), new Condition() { + @Override + public boolean value(@NotNull SVNMergeRange range) { + return BranchInfo.isInRange(range, myRevisionNumber) && (range.isInheritable() || isCurrentPath); + } + }); + } + } + + return processed; + } + } + + @NotNull + private PropertyConsumer createPropertyHandler() { + return new PropertyConsumer() { + public void handleProperty(@NotNull File path, @NotNull PropertyData property) throws SVNException { + String workingCopyRelativePath = getWorkingCopyRelativePath(path); + Map mergeInfo; + + try { + mergeInfo = BranchInfo.parseMergeInfo(ObjectUtils.assertNotNull(property.getValue())); + } + catch (SvnBindException e) { + throw new SVNException(SVNErrorMessage.create(SVNErrorCode.MERGE_INFO_PARSE_ERROR, e), e); + } + + synchronized (myMergeInfoLock) { + myMergeInfoMap.put(toKey(workingCopyRelativePath), mergeInfo); + } + } + + public void handleProperty(SVNURL url, PropertyData property) throws SVNException { + } + + public void handleProperty(long revision, PropertyData property) throws SVNException { + } + }; + } + + @NotNull + private String getWorkingCopyRelativePath(@NotNull File file) { + return FileUtil.toSystemIndependentName( + ObjectUtils.assertNotNull(FileUtil.getRelativePath(myMergeContext.getWcInfo().getRootInfo().getIoFile(), file))); + } + + @NotNull + private static String toKey(@NotNull String path) { + return SystemInfo.isFileSystemCaseSensitive ? path : path.toUpperCase(); + } }