Rebase feature for update project implemented

*pull with update or rebase args executed;
*continue and abort rebase actions added;
*conflicts resolved  until  rebase continue command finished successfully or  cancelled;
*rebase state added to repository updater,reader and updated files;
*update project dialog changed
This commit is contained in:
Nadya Zabrodina
2014-03-07 21:59:49 +04:00
parent fc56bcb578
commit 8084cb06ef
19 changed files with 317 additions and 159 deletions
+3
View File
@@ -77,6 +77,9 @@
<action id="hg4idea.tag" class="org.zmlx.hg4idea.action.HgCreateTagAction"/>
<action id="hg4idea.updateTo" class="org.zmlx.hg4idea.action.HgUpdateToAction"/>
<action id="hg4idea.resolve.mark" class="org.zmlx.hg4idea.action.HgMarkResolved"/>
<separator/>
<action id="hg4idea.Rebase.Abort" class="org.zmlx.hg4idea.action.HgAbortRebaseAction" text="Abort Rebasing"/>
<action id="hg4idea.Rebase.Continue" class="org.zmlx.hg4idea.action.HgContinueRebaseAction" text="Continue Rebasing"/>
<separator/>
<reference id="ChangesView.Browse"/>
@@ -0,0 +1,50 @@
/*
* Copyright 2000-2014 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.zmlx.hg4idea.action;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.command.HgRebaseCommand;
import org.zmlx.hg4idea.execution.HgCommandResult;
import org.zmlx.hg4idea.repo.HgRepository;
import org.zmlx.hg4idea.util.HgErrorUtil;
import java.util.Collection;
public class HgAbortRebaseAction extends HgProcessRebaseAction {
@Override
protected void execute(@NotNull final Project project,
@NotNull Collection<HgRepository> repositories,
@Nullable final HgRepository selectedRepo) {
new Task.Backgroundable(project, "Abort Rebasing...") {
@Override
public void run(@NotNull ProgressIndicator indicator) {
if (selectedRepo != null) {
HgRebaseCommand rebaseCommand = new HgRebaseCommand(project, selectedRepo.getRoot());
HgCommandResult result = rebaseCommand.abortRebase();
if (HgErrorUtil.isAbort(result)) {
new HgCommandResultNotifier(project).notifyError(result, "Hg Error", "Couldn't abort rebasing");
}
}
}
}.queue();
}
}
@@ -89,7 +89,7 @@ abstract class HgAbstractGlobalAction extends AnAction {
}
}
public static boolean isEnabled(AnActionEvent e) {
public boolean isEnabled(AnActionEvent e) {
Project project = e.getData(CommonDataKeys.PROJECT);
if (project == null) {
return false;
@@ -101,4 +101,17 @@ abstract class HgAbstractGlobalAction extends AnAction {
}
return true;
}
@Nullable
public static HgRepository getSelectedRepositoryFromEvent(AnActionEvent e) {
final DataContext dataContext = e.getDataContext();
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project == null) {
return null;
}
VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE);
HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
return file != null ? repositoryManager.getRepositoryForFile(file) : HgUtil.getCurrentRepository(project);
}
}
@@ -221,7 +221,7 @@ public class HgBranchPopupActions {
e.getPresentation().setEnabled(false);
e.getPresentation().setDescription("Checkout of a new branch is not possible before the first commit.");
}
else if (Repository.State.MERGING.equals(myRepository.getState())) {
else if (!Repository.State.NORMAL.equals(myRepository.getState())) {
e.getPresentation().setEnabled(false);
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2000-2014 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.zmlx.hg4idea.action;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.command.HgRebaseCommand;
import org.zmlx.hg4idea.execution.HgCommandResult;
import org.zmlx.hg4idea.repo.HgRepository;
import org.zmlx.hg4idea.util.HgErrorUtil;
import java.util.Collection;
public class HgContinueRebaseAction extends HgProcessRebaseAction {
@Override
protected void execute(@NotNull final Project project,
@NotNull Collection<HgRepository> repositories,
@Nullable final HgRepository selectedRepo) {
new Task.Backgroundable(project, "Continue Rebasing...") {
@Override
public void run(@NotNull ProgressIndicator indicator) {
if (selectedRepo != null) {
HgRebaseCommand rebaseCommand = new HgRebaseCommand(project, selectedRepo.getRoot());
HgCommandResult result = rebaseCommand.continueRebase();
if (HgErrorUtil.isAbort(result)) {
new HgCommandResultNotifier(project).notifyError(result, "Hg Error", "Couldn't continue rebasing");
}
}
}
}.queue();
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2000-2014 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.zmlx.hg4idea.action;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.zmlx.hg4idea.repo.HgRepository;
public abstract class HgProcessRebaseAction extends HgAbstractGlobalAction {
protected static boolean isRebasing(AnActionEvent e) {
HgRepository repository = HgAbstractGlobalAction.getSelectedRepositoryFromEvent(e);
return repository != null && repository.getState() == HgRepository.State.REBASING;
}
@Override
public boolean isEnabled(AnActionEvent e) {
return super.isEnabled(e) && isRebasing(e);
}
}
@@ -51,8 +51,6 @@ public class HgPullAction extends HgAbstractGlobalAction {
project, dialog.getRepository()
);
command.setSource(dialog.getSource());
command.setRebase(false);
command.setUpdate(false);
command.execute();
}
@@ -12,7 +12,6 @@
// limitations under the License.
package org.zmlx.hg4idea.command;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -27,15 +26,17 @@ import java.util.LinkedList;
import java.util.List;
public class HgPullCommand {
public static int ERROR = -1;
public static int UNRESOLVED = 1;
public static int SUCCESS = 0;
private final Project project;
private final VirtualFile repo;
private String source;
private String revision;
private boolean update = true;
private boolean rebase = !update;
private static final Logger LOG = Logger.getInstance(HgPullCommand.class);
private boolean update;
private boolean rebase;
public HgPullCommand(Project project, @NotNull VirtualFile repo) {
this.project = project;
@@ -58,7 +59,7 @@ public class HgPullCommand {
this.source = source;
}
public boolean execute() {
public int execute() {
List<String> arguments = new LinkedList<String>();
if (update) {
arguments.add("--update");
@@ -79,13 +80,19 @@ public class HgPullCommand {
if (HgErrorUtil.isAuthorizationError(result)) {
new HgCommandResultNotifier(project)
.notifyError(result, "Authorization required", "http authorization required for <code>" + source + "</code>");
return false;
} else if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
return ERROR;
}
else if (HgErrorUtil.isAbort(result) || result.getExitValue() > 1) { //if result == null - > isAbort returns true
new HgCommandResultNotifier(project).notifyError(result, "", "Pull failed");
return false;
} else {
return ERROR;
}
else if (result.getExitValue() == 1) {
return UNRESOLVED;
}
else {
project.getMessageBus().syncPublisher(HgVcs.REMOTE_TOPIC).update(project, null);
return true;
return SUCCESS;
}
}
}
@@ -17,6 +17,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.zmlx.hg4idea.HgVcs;
import org.zmlx.hg4idea.execution.HgCommandExecutor;
import org.zmlx.hg4idea.execution.HgCommandResult;
import java.util.Arrays;
@@ -30,9 +31,15 @@ public class HgRebaseCommand {
this.repo = repo;
}
public void continueRebase() {
new HgCommandExecutor(project).execute(repo, "rebase", Arrays.asList("--continue"), null);
public HgCommandResult continueRebase() {
HgCommandResult result = new HgCommandExecutor(project).executeInCurrentThread(repo, "rebase", Arrays.asList("--continue"), null);
project.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(project, null);
return result;
}
public HgCommandResult abortRebase() {
HgCommandResult result = new HgCommandExecutor(project).executeInCurrentThread(repo, "rebase", Arrays.asList("--abort"), null);
project.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(project, null);
return result;
}
}
@@ -46,7 +46,25 @@ public final class HgConflictResolver {
}
public void resolve(final VirtualFile repo) {
Map<HgFile, HgResolveStatusEnum> resolves = new HgResolveCommand(myProject).getListSynchronously(repo);
final List<VirtualFile> conflicts = findConflicts(myProject, updatedFiles, repo);
if (conflicts.isEmpty()) {
return;
}
final HgVcs vcs = HgVcs.getInstance(myProject);
if (vcs == null) {
return;
}
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
public void run() {
AbstractVcsHelper.getInstance(myProject).showMergeDialog(conflicts, vcs.getMergeProvider());
}
}, ModalityState.defaultModalityState());
}
public static List<VirtualFile> findConflicts(final Project project, final UpdatedFiles updatedFiles, VirtualFile repo) {
Map<HgFile, HgResolveStatusEnum> resolves = new HgResolveCommand(project).getListSynchronously(repo);
final List<VirtualFile> conflicts = new ArrayList<VirtualFile>();
for (Map.Entry<HgFile, HgResolveStatusEnum> entry : resolves.entrySet()) {
File file = entry.getKey().getFile();
@@ -65,21 +83,9 @@ public final class HgConflictResolver {
updatedFiles.getGroupById(FileGroup.UPDATED_ID).remove(file.getAbsolutePath());
//TODO get the correct revision to pass to the UpdatedFiles
updatedFiles.getGroupById(fileGroupId)
.add(file.getPath(), HgVcs.VCS_NAME, null);
.add(file.getPath(), HgVcs.VCS_NAME, null);
}
}
if (conflicts.isEmpty()) {
return;
}
final HgVcs vcs = HgVcs.getInstance(myProject);
if (vcs == null) { return; }
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
public void run() {
AbstractVcsHelper.getInstance(myProject).showMergeDialog(conflicts, vcs.getMergeProvider());
}
}, ModalityState.defaultModalityState());
return conflicts;
}
}
@@ -23,9 +23,11 @@ import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.*;
import org.zmlx.hg4idea.action.HgCommandResultNotifier;
import org.zmlx.hg4idea.command.*;
import org.zmlx.hg4idea.execution.HgCommandException;
import org.zmlx.hg4idea.execution.HgCommandResult;
import org.zmlx.hg4idea.util.HgErrorUtil;
import org.zmlx.hg4idea.util.HgUtil;
import java.util.ArrayList;
@@ -47,12 +49,8 @@ public class HgRegularUpdater implements HgUpdater {
this.updateConfiguration = configuration;
}
private boolean shouldPull() {
return updateConfiguration.shouldPull();
}
private boolean shouldUpdate() {
return updateConfiguration.shouldUpdate();
private boolean shouldRebase() {
return updateConfiguration.shouldRebase();
}
private boolean shouldMerge() {
@@ -88,27 +86,29 @@ public class HgRegularUpdater implements HgUpdater {
// throw new VcsException("working dir not at branch tip (use \"Update to...\" to check out branch tip)");
// }
if (shouldPull()) {
boolean pullResult = pull(repoRoot, indicator);
if (!pullResult) {
return false;
}
HgRevisionNumber parentBeforeUpdate = new HgWorkingCopyRevisionsCommand(project).firstParent(repoRoot);
int pullResult = pull(repoRoot, indicator, shouldRebase());
if (pullResult == HgPullCommand.ERROR) {
return false;
}
if (shouldUpdate()) {
HgRevisionNumber paretnAfterUpdate = new HgWorkingCopyRevisionsCommand(project).firstParent(repoRoot);
List<HgRevisionNumber> parentsBeforeUpdate = new HgWorkingCopyRevisionsCommand(project).parents(repoRoot);
if (parentsBeforeUpdate.size() > 1) {
throw new VcsException(HgVcsMessages.message("hg4idea.update.error.uncommittedMerge", repoRoot.getPath()));
}
if (pullResult == HgPullCommand.SUCCESS) {
addUpdatedFiles(repoRoot, updatedFiles, parentBeforeUpdate, paretnAfterUpdate);
return true;
}
if (shouldMerge()) {
indicator.setText2(HgVcsMessages.message("hg4idea.progress.countingHeads"));
List<HgRevisionNumber> branchHeadsAfterPull = new HgHeadsCommand(project, repoRoot).execute();
List<HgRevisionNumber> pulledBranchHeads = determinePulledBranchHeads(branchHeadsBeforePull, branchHeadsAfterPull);
List<HgRevisionNumber> remainingOriginalBranchHeads = determingRemainingOriginalBranchHeads(branchHeadsBeforePull, branchHeadsAfterPull);
List<HgRevisionNumber> remainingOriginalBranchHeads =
determingRemainingOriginalBranchHeads(branchHeadsBeforePull, branchHeadsAfterPull);
if (branchHeadsAfterPull.size() > 1 && shouldMerge()) {
if (branchHeadsAfterPull.size() > 1) {
abortOnLocalChanges();
abortOnMultiplePulledHeads(pulledBranchHeads);
abortOnMultipleLocalHeads(remainingOriginalBranchHeads);
@@ -118,14 +118,14 @@ public class HgRegularUpdater implements HgUpdater {
if (shouldCommitAfterMerge()) {
commitOrWarnAboutConflicts(warnings, mergeResult);
}
} else {
//in case of multiple heads the update will report the appropriate error
update(repoRoot, indicator, updatedFiles, warnings);
}
//any kind of update could have resulted in merges and merge conflicts, so run the resolver
resolvePossibleConflicts(updatedFiles);
}
else {
processRebase(updatedFiles);
}
return true;
}
@@ -207,6 +207,24 @@ public class HgRegularUpdater implements HgUpdater {
return new HgHeadMerger(project, mergeCommand).merge(repoRoot);
}
private void processRebase(final UpdatedFiles updatedFiles) throws VcsException {
HgCommandResult result;
do {
resolvePossibleConflicts(updatedFiles);
if (!HgConflictResolver.findConflicts(project, updatedFiles, repoRoot).isEmpty()) {
return;
}
HgRebaseCommand rebaseCommand = new HgRebaseCommand(project, repoRoot);
result = rebaseCommand.continueRebase();
if (HgErrorUtil.isAbort(result)) {
new HgCommandResultNotifier(project).notifyError(result, "Hg Error", "Couldn't continue rebasing");
return;
}
}
while (result.getExitValue() == 1);
}
private void abortOnLocalChanges() throws VcsException {
if (getLocalChanges().size() != 0) {
throw new VcsException(HgVcsMessages.message("hg4idea.update.error.localchanges", repoRoot.getPath()));
@@ -222,14 +240,18 @@ public class HgRegularUpdater implements HgUpdater {
return statusCommand.execute(repoRoot);
}
private boolean pull(VirtualFile repo, ProgressIndicator indicator)
private int pull(VirtualFile repo, ProgressIndicator indicator, boolean isRebase)
throws VcsException {
indicator.setText2(HgVcsMessages.message("hg4idea.progress.pull.with.update"));
HgPullCommand hgPullCommand = new HgPullCommand(project, repo);
final String defaultPath = HgUtil.getRepositoryDefaultPath(project, repo);
hgPullCommand.setSource(defaultPath);
hgPullCommand.setUpdate(false);
hgPullCommand.setRebase(false);
if (isRebase) {
hgPullCommand.setRebase(true);
}
else {
hgPullCommand.setUpdate(true);
}
return hgPullCommand.execute();
}
@@ -23,19 +23,11 @@ public interface HgUpdater {
boolean update(UpdatedFiles updatedFiles, ProgressIndicator indicator, List<VcsException> exceptions)
throws VcsException;
static class UpdateConfiguration{
private boolean shouldPull = true;
private boolean shouldUpdate = true;
class UpdateConfiguration{
private boolean shouldMerge = true;
private boolean shouldCommitAfterMerge = true;
private boolean shouldRebase = true;
public void setShouldPull(boolean shouldPull) {
this.shouldPull = shouldPull;
}
public void setShouldUpdate(boolean shouldUpdate) {
this.shouldUpdate = shouldUpdate;
}
public void setShouldMerge(boolean shouldMerge) {
this.shouldMerge = shouldMerge;
@@ -45,16 +37,16 @@ public interface HgUpdater {
this.shouldCommitAfterMerge = shouldCommitAfterMerge;
}
public boolean shouldPull() {
return shouldPull;
}
public boolean shouldUpdate() {
return shouldUpdate;
public void setShouldRebase(boolean shouldRebase) {
this.shouldRebase = shouldRebase;
}
public boolean shouldRebase() {
return shouldRebase;
}
public boolean shouldMerge() {
return shouldUpdate() && shouldMerge;
return shouldMerge;
}
public boolean shouldCommitAfterMerge() {
@@ -34,6 +34,7 @@ public class HgRepositoryFiles {
// so check for starting branch
public static final String BRANCHEADSDIR = "cache";
public static final String MERGE = "merge";
public static final String REBASE = "rebase"; //rebasestate
public static final String BRANCH = "branch";
public static final String BOOKMARKS = "bookmarks";
public static final String LOCAL_TAGS = "localtags";
@@ -45,6 +46,7 @@ public class HgRepositoryFiles {
@NotNull private final String myBranchHeadsPath;
@NotNull private final String myBranchHeadsDirPath;
@NotNull private final String myMergePath;
@NotNull private final String myRebasePath;
@NotNull private final String myBranchPath;
@NotNull private final String myBookmarksPath;
@NotNull private final String myTagsPath;
@@ -62,6 +64,7 @@ public class HgRepositoryFiles {
myBranchHeadsDirPath = hgDir.getPath() + slash(BRANCHEADSDIR);
myBranchPath = hgDir.getPath() + slash(BRANCH);
myMergePath = hgDir.getPath() + slash(MERGE);
myRebasePath = hgDir.getPath() + slash(REBASE);
myBookmarksPath = hgDir.getPath() + slash(BOOKMARKS);
myTagsPath = hgDir.getParent().getPath() + slash(TAGS);
myLocalTagsPath = hgDir.getPath() + slash(LOCAL_TAGS);
@@ -99,6 +102,10 @@ public class HgRepositoryFiles {
return filePath.startsWith(myMergePath);
}
public boolean isRebaseFile(String filePath) {
return filePath.startsWith(myRebasePath);
}
public boolean isBookmarksFile(String filePath) {
return filePath.equals(myBookmarksPath);
}
@@ -142,8 +142,15 @@ public class HgRepositoryReader {
return new File(myHgDir, "merge").exists();
}
public boolean isRebaseInProgress() {
return new File(myHgDir, "rebasestate").exists();
}
@NotNull
public Repository.State readState() {
if (isRebaseInProgress()) {
return Repository.State.REBASING;
}
return isMergeInProgress() ? Repository.State.MERGING : Repository.State.NORMAL;
}
@@ -91,6 +91,7 @@ final class HgRepositoryUpdater implements Disposable, BulkFileListener {
boolean branchHeadsChanged = false;
boolean branchFileChanged = false;
boolean mergeFileChanged = false;
boolean rebaseFileChanged = false;
boolean bookmarksFileChanged = false;
boolean tagsFileChanged = false;
boolean localTagsFileChanged = false;
@@ -111,6 +112,9 @@ final class HgRepositoryUpdater implements Disposable, BulkFileListener {
else if (myRepositoryFiles.isMergeFile(filePath)) {
mergeFileChanged = true;
}
else if (myRepositoryFiles.isRebaseFile(filePath)) {
rebaseFileChanged = true;
}
else if (myRepositoryFiles.isBookmarksFile(filePath)) {
bookmarksFileChanged = true;
}
@@ -132,6 +136,7 @@ final class HgRepositoryUpdater implements Disposable, BulkFileListener {
if (branchHeadsChanged ||
branchFileChanged ||
mergeFileChanged ||
rebaseFileChanged ||
bookmarksFileChanged ||
currentBookmarkFileChanged ||
tagsFileChanged ||
@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.zmlx.hg4idea.ui.HgUpdateDialog">
<grid id="27dc6" binding="contentPane" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="6a810" class="javax.swing.JCheckBox" binding="pullCheckBox" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;pull"/>
<toolTipText value="pull from the default remote repository"/>
</properties>
</component>
<hspacer id="732d8">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="2555e" class="javax.swing.JCheckBox" binding="updateCheckBox" default-binding="true">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;update"/>
<toolTipText value="update to the head of the current branch"/>
</properties>
</component>
<component id="3a607" class="javax.swing.JCheckBox" binding="mergeCheckBox" default-binding="true">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;merge"/>
<toolTipText value="merge if pulling resulted in extra heads"/>
</properties>
</component>
<component id="6499c" class="javax.swing.JCheckBox" binding="commitAfterMergeCheckBox" default-binding="true">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;commit after merge without conflicts"/>
<toolTipText value="commit automatically after the merge"/>
</properties>
</component>
<vspacer id="26be6">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</form>
@@ -12,6 +12,8 @@
// limitations under the License.
package org.zmlx.hg4idea.ui;
import com.intellij.ui.IdeBorderFactory;
import net.miginfocom.swing.MigLayout;
import org.zmlx.hg4idea.provider.update.HgUpdater;
import javax.swing.*;
@@ -22,45 +24,62 @@ import java.awt.event.ItemListener;
* Configuration dialog for the update process.
*/
public class HgUpdateDialog {
private JPanel contentPane;
private JCheckBox pullCheckBox;
private JCheckBox updateCheckBox;
private JCheckBox mergeCheckBox;
private JCheckBox commitAfterMergeCheckBox;
private JCheckBox myCommitAfterMergeCheckBox;
private JRadioButton myMergeRadioButton;
private JRadioButton myRebaseRadioButton;
public HgUpdateDialog() {
ItemListener enabledListener = new ItemListener() {
public void itemStateChanged(ItemEvent e) {
updateEnabledStates();
}
};
updateCheckBox.addItemListener(enabledListener);
mergeCheckBox.addItemListener(enabledListener);
updateEnabledStates();
createCenterPanel();
}
private void updateEnabledStates() {
//TODO this information is actually duplicated in the HgRegularUpdater (as a series of nested ifs)
mergeCheckBox.setEnabled(updateCheckBox.isSelected());
commitAfterMergeCheckBox.setEnabled(mergeCheckBox.isEnabled() && mergeCheckBox.isSelected());
myCommitAfterMergeCheckBox.setEnabled(myMergeRadioButton.isSelected());
}
public void applyTo(HgUpdater.UpdateConfiguration updateConfiguration) {
updateConfiguration.setShouldPull(pullCheckBox.isSelected());
updateConfiguration.setShouldUpdate(updateCheckBox.isSelected());
updateConfiguration.setShouldMerge(mergeCheckBox.isSelected());
updateConfiguration.setShouldCommitAfterMerge(commitAfterMergeCheckBox.isSelected());
updateConfiguration.setShouldMerge(myMergeRadioButton.isSelected());
updateConfiguration.setShouldCommitAfterMerge(myCommitAfterMergeCheckBox.isSelected());
updateConfiguration.setShouldRebase(myRebaseRadioButton.isSelected());
}
public JComponent createCenterPanel() {
MigLayout migLayout = new MigLayout("flowy,ins 0, fill");
JPanel contentPane = new JPanel(migLayout);
contentPane.setBorder(IdeBorderFactory.createTitledBorder("Update Type"));
myMergeRadioButton = new JRadioButton("Merge", true);
myMergeRadioButton.setMnemonic('m');
myMergeRadioButton.setToolTipText("Merge if pulling resulted in extra heads");
myCommitAfterMergeCheckBox = new JCheckBox("Commit after merge without conflicts", false);
myCommitAfterMergeCheckBox.setMnemonic('c');
myCommitAfterMergeCheckBox.setToolTipText("Commit automatically after the merge");
myRebaseRadioButton = new JRadioButton("Rebase", false);
myRebaseRadioButton.setToolTipText("Rebase changesets to a branch tip as destination");
myRebaseRadioButton.setMnemonic('r');
final ButtonGroup radioButtonGroup = new ButtonGroup();
radioButtonGroup.add(myMergeRadioButton);
radioButtonGroup.add(myRebaseRadioButton);
contentPane.add(myMergeRadioButton, "left");
contentPane.add(myCommitAfterMergeCheckBox, "gapx 5%");
contentPane.add(myRebaseRadioButton, "left");
myMergeRadioButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
updateEnabledStates();
}
});
updateEnabledStates();
return contentPane;
}
public void updateFrom(HgUpdater.UpdateConfiguration updateConfiguration) {
pullCheckBox.setSelected(updateConfiguration.shouldPull());
updateCheckBox.setSelected(updateConfiguration.shouldUpdate());
mergeCheckBox.setSelected(updateConfiguration.shouldMerge());
commitAfterMergeCheckBox.setSelected(updateConfiguration.shouldCommitAfterMerge());
myMergeRadioButton.setSelected(updateConfiguration.shouldMerge());
myCommitAfterMergeCheckBox.setSelected(updateConfiguration.shouldCommitAfterMerge());
myRebaseRadioButton.setSelected(updateConfiguration.shouldRebase());
}
}
@@ -571,7 +571,7 @@ public abstract class HgUtil {
public static String getDisplayableBranchOrBookmarkText(@NotNull HgRepository repository) {
HgRepository.State state = repository.getState();
String branchText = "";
if (state == HgRepository.State.MERGING) {
if (state != HgRepository.State.NORMAL) {
branchText += state.toString() + " ";
}
String branchOrBookMarkName = repository.getCurrentBookmark();
@@ -60,7 +60,6 @@ public class HgUpdateTest extends HgCollaborativeTest {
//do a simple pull without an update
HgPullCommand pull = new HgPullCommand(myProject, projectRepoVirtualFile);
pull.setSource(HgUtil.getRepositoryDefaultPath(myProject, projectRepoVirtualFile));
pull.setUpdate(false);
pull.execute();
assertEquals( determineNumberOfIncomingChanges( projectRepo ), 0,