svn: Refactored "BaseMergeTask" and inheritors

* Used single "QuickMerge" constructor parameter instead of 2 separate
"MergeContext" and "QuickMergeInteraction" parameters
* Code simplified, warnings fixed, @NotNull
This commit is contained in:
Konstantin Kolosovsky
2016-10-11 04:28:23 +03:00
parent e7ba0f7c78
commit f97ff5f6bc
11 changed files with 119 additions and 194 deletions
@@ -31,31 +31,28 @@ import org.tmatesoft.svn.core.SVNURL;
import java.util.List;
/**
* @author Konstantin Kolosovsky.
*/
public abstract class BaseMergeTask extends TaskDescriptor {
private static final Logger LOG = Logger.getInstance(BaseMergeTask.class);
@NotNull protected final QuickMerge myMergeProcess;
@NotNull protected final MergeContext myMergeContext;
@NotNull protected final QuickMergeInteraction myInteraction;
public BaseMergeTask(@NotNull MergeContext mergeContext,
@NotNull QuickMergeInteraction interaction, String name,
@NotNull Where where) {
public BaseMergeTask(@NotNull QuickMerge mergeProcess, @NotNull String name, @NotNull Where where) {
super(name, where);
myMergeContext = mergeContext;
myInteraction = interaction;
myMergeProcess = mergeProcess;
myMergeContext = mergeProcess.getMergeContext();
myInteraction = mergeProcess.getInteraction();
}
@NotNull
protected List<TaskDescriptor> getMergeAllTasks() {
List<TaskDescriptor> result = ContainerUtil.newArrayList();
result.add(new LocalChangesPromptTask(myMergeContext, myInteraction, true, null, null));
MergeAllWithBranchCopyPointTask mergeAllExecutor = new MergeAllWithBranchCopyPointTask(myMergeContext, myInteraction);
result.add(new LocalChangesPromptTask(myMergeProcess, true, null, null));
MergeAllWithBranchCopyPointTask mergeAllExecutor = new MergeAllWithBranchCopyPointTask(myMergeProcess);
result.add(myMergeContext.getVcs().getSvnBranchPointsCalculator()
.getFirstCopyPointTask(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl(),
myMergeContext.getWcInfo().getRootUrl(), mergeAllExecutor));
@@ -65,11 +62,11 @@ public abstract class BaseMergeTask extends TaskDescriptor {
}
protected void runChangeListsMerge(@NotNull ContinuationContext context,
@NotNull final List<CommittedChangeList> lists,
@NotNull List<CommittedChangeList> lists,
@NotNull SvnBranchPointsCalculator.WrapperInvertor copyPoint,
@NotNull String title) {
context.next(new LocalChangesPromptTask(myMergeContext, myInteraction, false, lists, copyPoint),
new MergeTask(myMergeContext, myInteraction, new ChangeListsMergerFactory(lists, false, false, true), title));
context.next(new LocalChangesPromptTask(myMergeProcess, false, lists, copyPoint),
new MergeTask(myMergeProcess, new ChangeListsMergerFactory(lists, false, false, true), title));
}
@Nullable
@@ -15,22 +15,20 @@
*/
package org.jetbrains.idea.svn.integrate;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.continuation.ContinuationContext;
import com.intellij.util.continuation.TaskDescriptor;
import com.intellij.util.continuation.Where;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnUtil;
import java.util.List;
/**
* @author Konstantin Kolosovsky.
*/
import static com.intellij.util.containers.ContainerUtil.newArrayList;
import static org.jetbrains.idea.svn.SvnUtil.checkRepositoryVersion15;
public class CheckRepositorySupportsMergeInfoTask extends BaseMergeTask {
public CheckRepositorySupportsMergeInfoTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) {
super(mergeContext, interaction, "Checking repository capabilities", Where.POOLED);
public CheckRepositorySupportsMergeInfoTask(@NotNull QuickMerge mergeProcess) {
super(mergeProcess, "Checking repository capabilities", Where.POOLED);
}
@Override
@@ -40,11 +38,11 @@ public class CheckRepositorySupportsMergeInfoTask extends BaseMergeTask {
private boolean supportsMergeInfo() {
return myMergeContext.getWcInfo().getFormat().supportsMergeInfo() &&
SvnUtil.checkRepositoryVersion15(myMergeContext.getVcs(), myMergeContext.getSourceUrl());
checkRepositoryVersion15(myMergeContext.getVcs(), myMergeContext.getSourceUrl());
}
@NotNull
private List<TaskDescriptor> getChooseMergeTypeTasks() {
return ContainerUtil.<TaskDescriptor>newArrayList(new MergeAllOrSelectedChooserTask(myMergeContext, myInteraction));
return newArrayList(new MergeAllOrSelectedChooserTask(myMergeProcess));
}
}
@@ -16,16 +16,13 @@
package org.jetbrains.idea.svn.integrate;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.util.FilePathByPathComparator;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.continuation.ContinuationContext;
import com.intellij.util.continuation.Where;
import com.intellij.vcsUtil.VcsUtil;
@@ -36,25 +33,27 @@ import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* @author Konstantin Kolosovsky.
*/
import static com.intellij.openapi.util.Conditions.alwaysTrue;
import static com.intellij.openapi.vcs.changes.ChangesUtil.*;
import static com.intellij.util.containers.ContainerUtil.isEmpty;
import static com.intellij.util.containers.ContainerUtil.sorted;
import static java.util.stream.Collectors.toSet;
public class LocalChangesPromptTask extends BaseMergeTask {
private final boolean myMergeAll;
@Nullable private final List<CommittedChangeList> myChangeListsToMerge;
private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint;
public LocalChangesPromptTask(@NotNull MergeContext mergeContext,
@NotNull QuickMergeInteraction interaction,
public LocalChangesPromptTask(@NotNull QuickMerge mergeProcess,
boolean mergeAll,
@Nullable List<CommittedChangeList> changeListsToMerge,
@Nullable SvnBranchPointsCalculator.WrapperInvertor copyPoint) {
super(mergeContext, interaction, "local changes intersection check", Where.AWT);
super(mergeProcess, "local changes intersection check", Where.AWT);
myMergeAll = mergeAll;
myChangeListsToMerge = changeListsToMerge;
@@ -64,9 +63,9 @@ public class LocalChangesPromptTask extends BaseMergeTask {
@Nullable
private File getLocalPath(String repositoryRelativePath) {
// from source if not inverted
final String absolutePath = SVNPathUtil.append(myMergeContext.getWcInfo().getRepositoryRoot(), repositoryRelativePath);
final SvnBranchPointsCalculator.BranchCopyData wrapped = myCopyPoint.getWrapped();
final String sourceRelativePath =
String absolutePath = SVNPathUtil.append(myMergeContext.getWcInfo().getRepositoryRoot(), repositoryRelativePath);
SvnBranchPointsCalculator.BranchCopyData wrapped = myCopyPoint.getWrapped();
String sourceRelativePath =
SVNPathUtil.getRelativePath(myCopyPoint.isInvertedSense() ? wrapped.getSource() : wrapped.getTarget(), absolutePath);
return !StringUtil.isEmptyOrSpaces(sourceRelativePath) ? new File(myMergeContext.getWcInfo().getPath(), sourceRelativePath) : null;
@@ -76,9 +75,7 @@ public class LocalChangesPromptTask extends BaseMergeTask {
public void run(ContinuationContext context) {
List<LocalChangeList> localChangeLists = ChangeListManager.getInstance(myMergeContext.getProject()).getChangeListsCopy();
Intersection intersection =
myMergeAll
? getAllChangesIntersection(localChangeLists)
: getChangesIntersection(localChangeLists, myChangeListsToMerge);
myMergeAll ? getAllChangesIntersection(localChangeLists) : getChangesIntersection(localChangeLists, myChangeListsToMerge);
if (intersection != null && !intersection.getChangesSubset().isEmpty()) {
processIntersection(context, intersection);
@@ -89,7 +86,7 @@ public class LocalChangesPromptTask extends BaseMergeTask {
//noinspection EnumSwitchStatementWhichMissesCases
switch (myInteraction.selectLocalChangesAction(myMergeAll)) {
case shelve:
context.next(new ShelveLocalChangesTask(myMergeContext, myInteraction, intersection));
context.next(new ShelveLocalChangesTask(myMergeProcess, intersection));
break;
case cancel:
context.cancelEverything();
@@ -97,8 +94,7 @@ public class LocalChangesPromptTask extends BaseMergeTask {
case inspect:
// here's cast is due to generic's bug
@SuppressWarnings("unchecked") Collection<Change> changes = (Collection<Change>)intersection.getChangesSubset().values();
myInteraction
.showIntersectedLocalPaths(ContainerUtil.sorted(ChangesUtil.getPaths(changes), FilePathByPathComparator.getInstance()));
myInteraction.showIntersectedLocalPaths(sorted(getPaths(changes), FilePathByPathComparator.getInstance()));
context.cancelEverything();
break;
}
@@ -109,16 +105,8 @@ public class LocalChangesPromptTask extends BaseMergeTask {
@Nullable List<CommittedChangeList> changeListsToMerge) {
Intersection result = null;
if (!ContainerUtil.isEmpty(changeListsToMerge)) {
final Set<FilePath> pathsToMerge = collectPaths(changeListsToMerge);
result = getChangesIntersection(localChangeLists, new Condition<Change>() {
@Override
public boolean value(Change change) {
return notNullAndInSet(ChangesUtil.getBeforePath(change), pathsToMerge) ||
notNullAndInSet(ChangesUtil.getAfterPath(change), pathsToMerge);
}
});
if (!isEmpty(changeListsToMerge)) {
result = getChangesIntersection(localChangeLists, change -> hasPathToMerge(change, collectPaths(changeListsToMerge)));
}
return result;
@@ -126,26 +114,18 @@ public class LocalChangesPromptTask extends BaseMergeTask {
@NotNull
private Set<FilePath> collectPaths(@NotNull List<CommittedChangeList> lists) {
Set<FilePath> result = new HashSet<>();
for (CommittedChangeList list : lists) {
SvnChangeList svnList = (SvnChangeList)list;
for (String path : svnList.getAffectedPaths()) {
File localPath = getLocalPath(path);
if (localPath != null) {
result.add(VcsUtil.getFilePath(localPath, false));
}
}
}
return result;
return lists.stream()
.map(SvnChangeList.class::cast)
.flatMap(list -> list.getAffectedPaths().stream())
.map(this::getLocalPath)
.filter(Objects::nonNull)
.map(localPath -> VcsUtil.getFilePath(localPath, false))
.collect(toSet());
}
@NotNull
private static Intersection getAllChangesIntersection(@NotNull List<LocalChangeList> localChangeLists) {
return getChangesIntersection(localChangeLists, Conditions.<Change>alwaysTrue());
return getChangesIntersection(localChangeLists, alwaysTrue());
}
@NotNull
@@ -163,7 +143,10 @@ public class LocalChangesPromptTask extends BaseMergeTask {
return result;
}
private static boolean notNullAndInSet(@Nullable FilePath path, @NotNull Set<FilePath> items) {
return path != null && items.contains(path);
private static boolean hasPathToMerge(@NotNull Change change, @NotNull Set<FilePath> pathsToMerge) {
FilePath beforePath = getBeforePath(change);
FilePath afterPath = getAfterPath(change);
return beforePath != null && pathsToMerge.contains(beforePath) || afterPath != null && pathsToMerge.contains(afterPath);
}
}
@@ -22,13 +22,10 @@ import com.intellij.util.continuation.Where;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Konstantin Kolosovsky.
*/
public class MergeAllOrSelectedChooserTask extends BaseMergeTask {
public MergeAllOrSelectedChooserTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) {
super(mergeContext, interaction, "merge source selector", Where.AWT);
public MergeAllOrSelectedChooserTask(@NotNull QuickMerge mergeProcess) {
super(mergeProcess, "merge source selector", Where.AWT);
}
@Override
@@ -40,7 +37,7 @@ public class MergeAllOrSelectedChooserTask extends BaseMergeTask {
break;
case showLatest:
LoadRecentBranchRevisions loader = new LoadRecentBranchRevisions(myMergeContext, -1);
ShowRecentInDialogTask dialog = new ShowRecentInDialogTask(myMergeContext, myInteraction, loader);
ShowRecentInDialogTask dialog = new ShowRecentInDialogTask(myMergeProcess, loader);
context.next(loader, dialog);
break;
@@ -66,7 +63,7 @@ public class MergeAllOrSelectedChooserTask extends BaseMergeTask {
MergeCalculatorTask result = null;
try {
result = new MergeCalculatorTask(myMergeContext, myInteraction);
result = new MergeCalculatorTask(myMergeProcess);
}
catch (VcsException e) {
finishWithError(context, e.getMessage(), true);
@@ -21,24 +21,17 @@ import com.intellij.util.Consumer;
import com.intellij.util.continuation.ContinuationContext;
import com.intellij.util.continuation.Where;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.update.UpdateEventHandler;
import org.tmatesoft.svn.core.SVNURL;
import java.io.File;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Konstantin Kolosovsky.
*/
public class MergeAllWithBranchCopyPointTask extends BaseMergeTask
implements Consumer<TransparentlyFailedValueI<SvnBranchPointsCalculator.WrapperInvertor, VcsException>> {
@NotNull private final AtomicReference<TransparentlyFailedValueI<SvnBranchPointsCalculator.WrapperInvertor, VcsException>> myData;
public MergeAllWithBranchCopyPointTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) {
super(mergeContext, interaction, "merge all", Where.AWT);
public MergeAllWithBranchCopyPointTask(@NotNull QuickMerge mergeProcess) {
super(mergeProcess, "merge all", Where.AWT);
myData = new AtomicReference<>();
}
@@ -84,23 +77,17 @@ public class MergeAllWithBranchCopyPointTask extends BaseMergeTask
context.cancelEverything();
}
else {
final MergerFactory mergerFactory = createBranchMergerFactory(reintegrate, inverter);
final String title = "Merging all from " + myMergeContext.getBranchName() + (reintegrate ? " (reintegrate)" : "");
MergerFactory mergerFactory = createBranchMergerFactory(reintegrate, inverter);
String title = "Merging all from " + myMergeContext.getBranchName() + (reintegrate ? " (reintegrate)" : "");
context.next(new MergeTask(myMergeContext, myInteraction, mergerFactory, title));
context.next(new MergeTask(myMergeProcess, mergerFactory, title));
}
}
@NotNull
private MergerFactory createBranchMergerFactory(final boolean reintegrate,
@NotNull final SvnBranchPointsCalculator.WrapperInvertor inverter) {
return new MergerFactory() {
@Override
public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) {
return new BranchMerger(vcs, currentBranchUrl, myMergeContext.getWcInfo().getPath(), handler, reintegrate,
myMergeContext.getBranchName(),
reintegrate ? inverter.getWrapped().getTargetRevision() : inverter.getWrapped().getSourceRevision());
}
};
private MergerFactory createBranchMergerFactory(boolean reintegrate, @NotNull SvnBranchPointsCalculator.WrapperInvertor inverter) {
return (vcs, target, handler, currentBranchUrl, branchName) ->
new BranchMerger(vcs, currentBranchUrl, myMergeContext.getWcInfo().getPath(), handler, reintegrate, myMergeContext.getBranchName(),
reintegrate ? inverter.getWrapped().getTargetRevision() : inverter.getWrapped().getSourceRevision());
}
}
@@ -17,35 +17,33 @@ package org.jetbrains.idea.svn.integrate;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.TransparentlyFailedValueI;
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.util.Consumer;
import com.intellij.util.PairConsumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.continuation.ContinuationContext;
import com.intellij.util.continuation.TaskDescriptor;
import com.intellij.util.continuation.Where;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.history.*;
import org.jetbrains.idea.svn.mergeinfo.MergeChecker;
import org.jetbrains.idea.svn.mergeinfo.OneShotMergeInfoHelper;
import org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Konstantin Kolosovsky.
*/
import static com.intellij.util.containers.ContainerUtil.newArrayList;
import static java.util.Collections.singletonList;
import static org.jetbrains.idea.svn.SvnUtil.ensureStartSlash;
import static org.tmatesoft.svn.core.internal.util.SVNPathUtil.getRelativePath;
import static org.tmatesoft.svn.core.internal.util.SVNPathUtil.isAncestor;
public class MergeCalculatorTask extends BaseMergeTask
implements Consumer<TransparentlyFailedValueI<SvnBranchPointsCalculator.WrapperInvertor, VcsException>> {
@@ -59,15 +57,15 @@ public class MergeCalculatorTask extends BaseMergeTask
myCopyData.set(value);
}
public MergeCalculatorTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) throws VcsException {
super(mergeContext, interaction, "Calculating not merged revisions", Where.POOLED);
public MergeCalculatorTask(@NotNull QuickMerge mergeProcess) throws VcsException {
super(mergeProcess, "Calculating not merged revisions", Where.POOLED);
myMergeTitle = "Merge from " + myMergeContext.getBranchName();
// TODO: Previously it was configurable - either to use OneShotMergeInfoHelper or BranchInfo as merge checker, but later that logic
// TODO: was commented (in 80ebdbfea5210f6c998e67ddf28ca9c670fa4efe on 5/28/2010).
// TODO: Still check if we need to preserve such configuration or it is sufficient to always use OneShotMergeInfoHelper.
myMergeChecker = new OneShotMergeInfoHelper(myMergeContext);
((OneShotMergeInfoHelper)myMergeChecker).prepare();
myMergeChecker.prepare();
myCopyData = new AtomicReference<>();
}
@@ -101,36 +99,33 @@ public class MergeCalculatorTask extends BaseMergeTask
}
}
catch (VcsException e) {
finishWithError(context, "Merge start wasn't found", Collections.singletonList(e));
finishWithError(context, "Merge start wasn't found", singletonList(e));
}
return result;
}
@NotNull
private LinkedList<Pair<SvnChangeList, LogHierarchyNode>> getChangeListsAfter(@NotNull ContinuationContext context, final long revision) {
private List<Pair<SvnChangeList, LogHierarchyNode>> getChangeListsAfter(@NotNull ContinuationContext context, final long revision) {
ChangeBrowserSettings settings = new ChangeBrowserSettings();
settings.CHANGE_AFTER = Long.toString(revision);
settings.USE_CHANGE_AFTER_FILTER = true;
final LinkedList<Pair<SvnChangeList, LogHierarchyNode>> result = ContainerUtil.newLinkedList();
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
List<Pair<SvnChangeList, LogHierarchyNode>> result = newArrayList();
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
try {
((SvnCommittedChangesProvider)myMergeContext.getVcs().getCommittedChangesProvider())
.getCommittedChangesWithMergedRevisons(settings, new SvnRepositoryLocation(myMergeContext.getSourceUrl()), 0,
new PairConsumer<SvnChangeList, LogHierarchyNode>() {
public void consume(@NotNull SvnChangeList changeList, LogHierarchyNode tree) {
indicator.checkCanceled();
if (revision < changeList.getNumber()) {
result.add(Pair.create(changeList, tree));
}
(changeList, tree) -> {
indicator.checkCanceled();
if (revision < changeList.getNumber()) {
result.add(Pair.create(changeList, tree));
}
});
}
catch (VcsException e) {
finishWithError(context, "Checking revisions for merge fault", Collections.singletonList(e));
finishWithError(context, "Checking revisions for merge fault", singletonList(e));
}
return result;
@@ -140,10 +135,10 @@ public class MergeCalculatorTask extends BaseMergeTask
private List<CommittedChangeList> getNotMergedChangeLists(@NotNull List<Pair<SvnChangeList, LogHierarchyNode>> changeLists) {
ProgressManager.getInstance().getProgressIndicator().setText("Checking merge information...");
String repositoryRelativeWorkingCopyRoot = SvnUtil.ensureStartSlash(
SVNPathUtil.getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getWcInfo().getRootUrl()));
String repositoryRelativeWorkingCopyRoot =
ensureStartSlash(getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getWcInfo().getRootUrl()));
String repositoryRelativeSourceBranch =
SvnUtil.ensureStartSlash(SVNPathUtil.getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl()));
ensureStartSlash(getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl()));
return getNotMergedChangeLists(changeLists, repositoryRelativeWorkingCopyRoot, repositoryRelativeSourceBranch);
}
@@ -152,7 +147,7 @@ public class MergeCalculatorTask extends BaseMergeTask
private List<CommittedChangeList> getNotMergedChangeLists(@NotNull List<Pair<SvnChangeList, LogHierarchyNode>> changeLists,
@NotNull String workingCopyRoot,
@NotNull String sourceBranch) {
List<CommittedChangeList> result = ContainerUtil.newArrayList();
List<CommittedChangeList> result = newArrayList();
for (Pair<SvnChangeList, LogHierarchyNode> pair : changeLists) {
SvnChangeList changeList = pair.getFirst();
@@ -204,9 +199,7 @@ public class MergeCalculatorTask extends BaseMergeTask
}
// true if errors found
static boolean checkListForPaths(@NotNull final String workingCopyRoot,
@NotNull final String sourceBranch,
@NotNull LogHierarchyNode node) {
static boolean checkListForPaths(@NotNull String workingCopyRoot, @NotNull String sourceBranch, @NotNull LogHierarchyNode node) {
// TODO: Such filtering logic is not clear enough so far (and probably not correct for all cases - for instance when we perform merge
// TODO: from branch1 to branch2 and have revision which contain merge changes from branch3 to branch1.
// TODO: In this case paths of child log entries will not contain neither urls from branch1 nor from branch2 - and checkEntry() method
@@ -214,12 +207,7 @@ public class MergeCalculatorTask extends BaseMergeTask
// TODO: Why do we check entries recursively - we have a revision - set of changes in the "merge from" branch? Why do we need to check
// TODO: where they came from - we want avoid some circular merges or what? Does subversion itself perform such checks or not?
boolean isLocalChange = ContainerUtil.or(node.getChildren(), new Condition<LogHierarchyNode>() {
@Override
public boolean value(@NotNull LogHierarchyNode child) {
return checkForSubtree(child, workingCopyRoot, sourceBranch);
}
});
boolean isLocalChange = ContainerUtil.or(node.getChildren(), child -> checkForSubtree(child, workingCopyRoot, sourceBranch));
return isLocalChange || checkForEntry(node.getMe(), workingCopyRoot, sourceBranch);
}
@@ -231,11 +219,11 @@ public class MergeCalculatorTask extends BaseMergeTask
*/
// true if errors found
private static boolean checkForSubtree(@NotNull LogHierarchyNode tree, @NotNull String relativeBranch, @NotNull String localURL) {
final LinkedList<LogHierarchyNode> queue = new LinkedList<>();
LinkedList<LogHierarchyNode> queue = new LinkedList<>();
queue.addLast(tree);
while (!queue.isEmpty()) {
final LogHierarchyNode element = queue.removeFirst();
LogHierarchyNode element = queue.removeFirst();
ProgressManager.checkCanceled();
if (checkForEntry(element.getMe(), localURL, relativeBranch)) return true;
@@ -253,10 +241,10 @@ public class MergeCalculatorTask extends BaseMergeTask
boolean atLeastOneUnderBranch = false;
for (LogEntryPath path : entry.getChangedPaths().values()) {
if (SVNPathUtil.isAncestor(localURL, path.getPath())) {
if (isAncestor(localURL, path.getPath())) {
return true;
}
if (!atLeastOneUnderBranch && SVNPathUtil.isAncestor(relativeBranch, path.getPath())) {
if (!atLeastOneUnderBranch && isAncestor(relativeBranch, path.getPath())) {
atLeastOneUnderBranch = true;
}
}
@@ -15,26 +15,20 @@
*/
package org.jetbrains.idea.svn.integrate;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.continuation.ContinuationContext;
import com.intellij.util.continuation.Where;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.NestedCopyType;
import org.jetbrains.idea.svn.dialogs.WCInfo;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNURLUtil;
import java.io.File;
/**
* @author Konstantin Kolosovsky.
*/
public class MergeInitChecksTask extends BaseMergeTask {
public MergeInitChecksTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) {
super(mergeContext, interaction, "initial checks", Where.AWT);
public MergeInitChecksTask(@NotNull QuickMerge mergeProcess) {
super(mergeProcess, "initial checks", Where.AWT);
}
@Override
@@ -52,14 +46,11 @@ public class MergeInitChecksTask extends BaseMergeTask {
}
private boolean hasSwitchedRoots() {
final File currentRoot = myMergeContext.getWcInfo().getRootInfo().getIoFile();
File currentRoot = myMergeContext.getWcInfo().getRootInfo().getIoFile();
return ContainerUtil.or(myMergeContext.getVcs().getAllWcInfos(), new Condition<WCInfo>() {
@Override
public boolean value(WCInfo info) {
return NestedCopyType.switched.equals(info.getType()) && FileUtil.isAncestor(currentRoot, info.getRootInfo().getIoFile(), true);
}
});
return myMergeContext.getVcs().getAllWcInfos().stream()
.filter(info -> NestedCopyType.switched.equals(info.getType()))
.anyMatch(info -> FileUtil.isAncestor(currentRoot, info.getRootInfo().getIoFile(), true));
}
private static boolean areInSameHierarchy(@NotNull SVNURL url1, @NotNull SVNURL url2) {
@@ -25,18 +25,12 @@ import com.intellij.util.continuation.Where;
import org.jetbrains.annotations.NotNull;
import org.tmatesoft.svn.core.SVNURL;
/**
* @author Konstantin Kolosovsky.
*/
public class MergeTask extends BaseMergeTask {
@NotNull private final MergerFactory myFactory;
public MergeTask(@NotNull MergeContext mergeContext,
@NotNull QuickMergeInteraction interaction,
@NotNull MergerFactory factory,
final String mergeTitle) {
super(mergeContext, interaction, mergeTitle, Where.AWT);
public MergeTask(@NotNull QuickMerge mergeProcess, @NotNull MergerFactory factory, @NotNull String mergeTitle) {
super(mergeProcess, mergeTitle, Where.AWT);
myFactory = factory;
}
@@ -88,10 +82,10 @@ public class MergeTask extends BaseMergeTask {
return needRefresh;
}
private void refreshChanges(@NotNull final ContinuationContext context) {
private void refreshChanges(@NotNull ContinuationContext context) {
context.suspend();
ChangeListManager.getInstance(myMergeContext.getProject())
.invokeAfterUpdate(() -> context.ping(), InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE, "", ModalityState.NON_MODAL);
.invokeAfterUpdate(context::ping, InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE, "", ModalityState.NON_MODAL);
}
}
@@ -40,6 +40,16 @@ public class QuickMerge {
myInteraction = interaction;
}
@NotNull
public MergeContext getMergeContext() {
return myMergeContext;
}
@NotNull
public QuickMergeInteraction getInteraction() {
return myInteraction;
}
@CalledInAwt
public void execute() {
runMergeTasks(null);
@@ -56,8 +66,8 @@ public class QuickMerge {
FileDocumentManager.getInstance().saveAllDocuments();
TaskDescriptor[] tasks = {
new MergeInitChecksTask(myMergeContext, myInteraction),
new CheckRepositorySupportsMergeInfoTask(myMergeContext, myInteraction),
new MergeInitChecksTask(this),
new CheckRepositorySupportsMergeInfoTask(this),
finalTask
};
@@ -23,7 +23,6 @@ import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.continuation.ContinuationContext;
import com.intellij.util.continuation.Where;
import org.jetbrains.annotations.NotNull;
@@ -34,39 +33,30 @@ import java.util.List;
import java.util.Map;
import static com.intellij.openapi.vcs.changes.ChangesUtil.getAfterRevisionsFiles;
import static com.intellij.util.containers.ContainerUtil.newArrayList;
import static java.util.stream.Collectors.toList;
/**
* @author Konstantin Kolosovsky.
*/
public class ShelveLocalChangesTask extends BaseMergeTask {
@NotNull private final Intersection myIntersection;
public ShelveLocalChangesTask(@NotNull MergeContext mergeContext,
@NotNull QuickMergeInteraction interaction,
@NotNull Intersection intersection) {
super(mergeContext, interaction, "Shelving local changes before merge", Where.POOLED);
public ShelveLocalChangesTask(@NotNull QuickMerge mergeProcess, @NotNull Intersection intersection) {
super(mergeProcess, "Shelving local changes before merge", Where.POOLED);
myIntersection = intersection;
}
@Override
public void run(final ContinuationContext context) {
public void run(ContinuationContext context) {
List<VirtualFile> changedFiles = shelveChanges(context);
context.suspend();
RefreshQueue.getInstance().refresh(true, false, new Runnable() {
@Override
public void run() {
context.ping();
}
}, changedFiles);
RefreshQueue.getInstance().refresh(true, false, context::ping, changedFiles);
}
@NotNull
private List<VirtualFile> shelveChanges(@NotNull ContinuationContext context) {
List<VirtualFile> changedFiles = ContainerUtil.newArrayList();
List<VirtualFile> changedFiles = newArrayList();
ShelveChangesManager shelveManager = ShelveChangesManager.getInstance(myMergeContext.getProject());
for (Map.Entry<String, Collection<Change>> entry : myIntersection.getChangesSubset().entrySet()) {
@@ -92,11 +82,6 @@ public class ShelveLocalChangesTask extends BaseMergeTask {
}
private static void saveAllDocuments() {
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
FileDocumentManager.getInstance().saveAllDocuments();
}
}, ModalityState.NON_MODAL);
ApplicationManager.getApplication().invokeAndWait(() -> FileDocumentManager.getInstance().saveAllDocuments(), ModalityState.NON_MODAL);
}
}
@@ -22,17 +22,12 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author Konstantin Kolosovsky.
*/
public class ShowRecentInDialogTask extends BaseMergeTask {
@NotNull private final LoadRecentBranchRevisions myInitialChangeListsLoader;
public ShowRecentInDialogTask(@NotNull MergeContext mergeContext,
@NotNull QuickMergeInteraction interaction,
@NotNull LoadRecentBranchRevisions initialChangeListsLoader) {
super(mergeContext, interaction, "", Where.AWT);
public ShowRecentInDialogTask(@NotNull QuickMerge mergeProcess, @NotNull LoadRecentBranchRevisions initialChangeListsLoader) {
super(mergeProcess, "", Where.AWT);
myInitialChangeListsLoader = initialChangeListsLoader;
}