svn: Use automatic sync/reintegrate merges if merge info is supported

Do not specify certain revisions for "Merge All" operation if merge info
is supported - svn detects necessary revisions and performs
corresponding merge operation automatically.
This commit is contained in:
Konstantin Kolosovsky
2016-10-11 04:28:23 +03:00
parent be51cac86d
commit 0fbf03256f
9 changed files with 57 additions and 22 deletions
@@ -85,11 +85,13 @@ public abstract class BaseMergeTask extends TaskDescriptor {
}
@NotNull
protected List<TaskDescriptor> getMergeAllTasks() {
protected List<TaskDescriptor> getMergeAllTasks(boolean supportsMergeInfo) {
// merge info is not supported - branch copy point is used to make first sync merge successful (without unnecessary tree conflicts)
// merge info is supported - branch copy point is used to determine if sync or reintegrate merge should be performed
return newArrayList(
new LocalChangesPromptTask(myMergeProcess),
new LookForBranchOriginTask(myMergeProcess, true, copyPoint ->
next(new MergeAllWithBranchCopyPointTask(myMergeProcess, copyPoint)))
next(new MergeAllWithBranchCopyPointTask(myMergeProcess, copyPoint, supportsMergeInfo)))
);
}
@@ -27,6 +27,7 @@ import org.jetbrains.idea.svn.diff.DiffOptions;
import org.jetbrains.idea.svn.update.UpdateEventHandler;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNRevisionRange;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
@@ -44,12 +45,16 @@ public class BranchMerger implements IMerger {
private final long mySourceCopyRevision;
private boolean myAtStart;
private SVNRevision mySourceLatestRevision;
private final boolean mySupportsMergeInfo;
public BranchMerger(final SvnVcs vcs,
final SVNURL sourceUrl,
final String targetPath,
final UpdateEventHandler handler,
final boolean isReintegrate, final String branchName, final long sourceCopyRevision) {
final boolean isReintegrate,
final String branchName,
long sourceCopyRevision,
boolean supportsMergeInfo) {
myVcs = vcs;
myTargetPath = targetPath;
mySourceUrl = sourceUrl;
@@ -58,11 +63,13 @@ public class BranchMerger implements IMerger {
myBranchName = branchName;
mySourceCopyRevision = sourceCopyRevision;
myAtStart = true;
mySourceLatestRevision = resolveSourceLatestRevision();
mySupportsMergeInfo = supportsMergeInfo;
}
public String getComment() {
return "Merge all from " + myBranchName + " at " + mySourceLatestRevision +(myReintegrate ? " (reintegration)" : "");
return "Merge all from " + myBranchName +
(!mySupportsMergeInfo ? " at " + mySourceLatestRevision : "") +
(myReintegrate ? " (reintegration)" : "");
}
public boolean hasNext() {
@@ -74,13 +81,15 @@ public class BranchMerger implements IMerger {
File destination = new File(myTargetPath);
MergeClient client = myVcs.getFactory(destination).createMergeClient();
SvnTarget source = SvnTarget.fromURL(mySourceUrl);
if (myReintegrate) {
client.merge(SvnTarget.fromURL(mySourceUrl), destination, false, createDiffOptions(), myHandler);
if (mySupportsMergeInfo) {
client.merge(source, destination, false, myReintegrate, createDiffOptions(), myHandler);
} else {
client.merge(SvnTarget.fromURL(mySourceUrl, SVNRevision.create(mySourceCopyRevision)),
SvnTarget.fromURL(mySourceUrl, mySourceLatestRevision), destination, Depth.INFINITY, true, false, false, true,
createDiffOptions(), myHandler);
mySourceLatestRevision = resolveSourceLatestRevision();
SVNRevisionRange range = new SVNRevisionRange(SVNRevision.create(mySourceCopyRevision), mySourceLatestRevision);
client.merge(source, range, destination, Depth.UNKNOWN, false, false, true, createDiffOptions(), myHandler);
}
}
@@ -32,7 +32,7 @@ public class CheckRepositorySupportsMergeInfoTask extends BaseMergeTask {
@Override
public void run() {
next(supportsMergeInfo() ? getChooseMergeTypeTasks() : getMergeAllTasks());
next(supportsMergeInfo() ? getChooseMergeTypeTasks() : getMergeAllTasks(false));
}
private boolean supportsMergeInfo() {
@@ -25,13 +25,14 @@ public class CmdMergeClient extends BaseSvnClient implements MergeClient {
public void merge(@NotNull SvnTarget source,
@NotNull File destination,
boolean dryRun,
boolean reintegrate,
@Nullable DiffOptions diffOptions,
@Nullable final ProgressTracker handler) throws VcsException {
@Nullable ProgressTracker handler) throws VcsException {
assertUrl(source);
List<String> parameters = new ArrayList<>();
CommandUtil.put(parameters, source);
fillParameters(parameters, destination, null, dryRun, false, false, true, diffOptions);
fillParameters(parameters, destination, null, dryRun, false, false, reintegrate, diffOptions);
run(destination, handler, parameters);
}
@@ -29,7 +29,7 @@ public class MergeAllOrSelectedChooserTask extends BaseMergeTask {
//noinspection EnumSwitchStatementWhichMissesCases
switch (myInteraction.selectMergeVariant()) {
case all:
next(getMergeAllTasks());
next(getMergeAllTasks(true));
break;
case showLatest:
LoadRecentBranchRevisions loader = new LoadRecentBranchRevisions(myMergeProcess, -1);
@@ -21,10 +21,14 @@ import org.jetbrains.annotations.NotNull;
public class MergeAllWithBranchCopyPointTask extends BaseMergeTask {
@NotNull private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint;
private final boolean mySupportsMergeInfo;
public MergeAllWithBranchCopyPointTask(@NotNull QuickMerge mergeProcess, @NotNull SvnBranchPointsCalculator.WrapperInvertor copyPoint) {
public MergeAllWithBranchCopyPointTask(@NotNull QuickMerge mergeProcess,
@NotNull SvnBranchPointsCalculator.WrapperInvertor copyPoint,
boolean supportsMergeInfo) {
super(mergeProcess, "merge all", Where.AWT);
myCopyPoint = copyPoint;
mySupportsMergeInfo = supportsMergeInfo;
}
@Override
@@ -44,8 +48,11 @@ public class MergeAllWithBranchCopyPointTask extends BaseMergeTask {
@NotNull
private MergerFactory createBranchMergerFactory(boolean reintegrate) {
return (vcs, target, handler, currentBranchUrl, branchName) ->
new BranchMerger(vcs, currentBranchUrl, myMergeContext.getWcInfo().getPath(), handler, reintegrate, myMergeContext.getBranchName(),
reintegrate ? myCopyPoint.getWrapped().getTargetRevision() : myCopyPoint.getWrapped().getSourceRevision());
return (vcs, target, handler, currentBranchUrl, branchName) -> {
long revision = reintegrate ? myCopyPoint.getWrapped().getTargetRevision() : myCopyPoint.getWrapped().getSourceRevision();
return new BranchMerger(vcs, currentBranchUrl, myMergeContext.getWcInfo().getPath(), handler, reintegrate,
myMergeContext.getBranchName(), revision, mySupportsMergeInfo);
};
}
}
@@ -148,7 +148,7 @@ public class MergeCalculatorTask extends BaseMergeTask {
end();
break;
case all:
next(getMergeAllTasks());
next(getMergeAllTasks(true));
break;
default:
List<CommittedChangeList> lists = result.getSelectedLists();
@@ -20,6 +20,7 @@ public interface MergeClient extends SvnClient {
void merge(@NotNull SvnTarget source,
@NotNull File destination,
boolean dryRun,
boolean reintegrate,
@Nullable DiffOptions diffOptions,
@Nullable ProgressTracker handler) throws VcsException;
@@ -7,28 +7,43 @@ import org.jetbrains.idea.svn.api.BaseSvnClient;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.api.ProgressTracker;
import org.jetbrains.idea.svn.diff.DiffOptions;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.SVNDiffClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNRevisionRange;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.singletonList;
/**
* @author Konstantin Kolosovsky.
*/
public class SvnKitMergeClient extends BaseSvnClient implements MergeClient {
private static final List<SVNRevisionRange> ALL_REVISIONS_RANGE =
singletonList(new SVNRevisionRange(SVNRevision.create(1), SVNRevision.HEAD));
public void merge(@NotNull SvnTarget source,
@NotNull File destination,
boolean dryRun,
boolean reintegrate,
@Nullable DiffOptions diffOptions,
@Nullable ProgressTracker handler) throws VcsException {
assertUrl(source);
SVNDiffClient client = createClient(diffOptions, handler);
try {
createClient(diffOptions, handler).doMergeReIntegrate(source.getURL(), source.getPegRevision(), destination, dryRun);
if (reintegrate) {
client.doMergeReIntegrate(source.getURL(), source.getPegRevision(), destination, dryRun);
}
else {
client.doMerge(source.getURL(), source.getPegRevision(), ALL_REVISIONS_RANGE, destination, SVNDepth.UNKNOWN, true, false, dryRun,
false);
}
}
catch (SVNException e) {
throw new VcsException(e);
@@ -48,7 +63,7 @@ public class SvnKitMergeClient extends BaseSvnClient implements MergeClient {
assertUrl(source);
try {
createClient(diffOptions, handler).doMerge(source.getURL(), source.getPegRevision(), Collections.singletonList(range), destination,
createClient(diffOptions, handler).doMerge(source.getURL(), source.getPegRevision(), singletonList(range), destination,
toDepth(depth), true, force, dryRun, recordOnly);
}
catch (SVNException e) {