[Mercurial] IDEA-56109 Push dialog: branch selector, 'force' option.
authorKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Mon, 12 Jul 2010 12:21:36 +0000 (16:21 +0400)
committerKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Mon, 12 Jul 2010 12:21:36 +0000 (16:21 +0400)
plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java
plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.form
plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java

index 558b4078d9df850e068bc4e520eaa8d139be3767..46fcc80e8e06d77dfe5080dffba2d815f57ae37d 100644 (file)
@@ -20,20 +20,10 @@ hg4idea.error=Error
 hg4idea.revert=Revert
 hg4idea.commit=Commit
 
-hg4idea.init.dialog.title=Create Mercurial repository
-hg4idea.init.dialog.incorrect.path=The specified path is incorrect
-hg4idea.init.dialog.option.create.repository.for.whole.project=&Create repository for the whole project
-hg4idea.init.dialog.option.select.folder=&Select where to create repository
-hg4idea.init.destination.directory.description=Select directory where the new Mercurial repository will be created.
-hg4idea.init.destination.directory.title=Select directory for hg init
-hg4idea.init.this.is.hg.root=The selected folder {0} is already a Mercurial root
-hg4idea.init.already.under.hg.description=<html>The selected directory <b><code>{0}</code></b> is already under Mercurial: <b><code>{1}</code></b><br/>Would you like to create new repository in the selected folder or use the parent one?</html>
-hg4idea.init.already.under.hg.title=This directory is already under hg
-hg4idea.init.already.under.hg.dialog.title=Directory is under hg
-hg4idea.init.already.under.hg.option.use.parent=Use parent repository, but keep working in this project.
-hg4idea.init.already.under.hg.option.create.repo.here=Create new repository here.
-hg4idea.init.created.notification.title=Mercurial repository created
-hg4idea.init.created.notification.description=Repository was created in {0}
+hg4idea.add.title=Add files to Mercurial
+hg4idea.add.single.title=Add file to Mercurial
+hg4idea.add.body=Do you want to add the following file to Mercurial?\n{0}\n\nIf you say NO, you can still add it later manually.
+hg4idea.add.progress=Adding files to Mercurial
 
 hg4idea.clone.title=Clone Mercurial Repository
 hg4idea.clone.button.clone=Clone
@@ -60,20 +50,37 @@ hg4idea.configuration.executable.error=\"{0}\" doesn''t appear to be a valid hg
 
 hg4idea.command.executable.error=Error executing \"{0}\". Make sure you have setup the right executable in Mercurial configuration
 
+hg4idea.commit.success=Repository \"{0}\" committed
+hg4idea.commit.partial.merge.message=<html>Partial commits are not allowed during merge, and following files are not included:<ul>{0}</ul>Perform commit with all files included ?</html>
+hg4idea.commit.partial.merge.title=Partial Merge Commit
 hg4idea.commit.error.messageEmpty=Please provide a commit message
 
-hg4idea.add.title=Add files to Mercurial
-hg4idea.add.single.title=Add file to Mercurial
-hg4idea.add.body=Do you want to add the following file to Mercurial?\n{0}\n\nIf you say NO, you can still add it later manually.
-hg4idea.add.progress=Adding files to Mercurial
+hg4idea.init.dialog.title=Create Mercurial repository
+hg4idea.init.dialog.incorrect.path=The specified path is incorrect
+hg4idea.init.dialog.option.create.repository.for.whole.project=&Create repository for the whole project
+hg4idea.init.dialog.option.select.folder=&Select where to create repository
+hg4idea.init.destination.directory.description=Select directory where the new Mercurial repository will be created.
+hg4idea.init.destination.directory.title=Select directory for hg init
+hg4idea.init.this.is.hg.root=The selected folder {0} is already a Mercurial root
+hg4idea.init.already.under.hg.description=<html>The selected directory <b><code>{0}</code></b> is already under Mercurial: <b><code>{1}</code></b><br/>Would you like to create new repository in the selected folder or use the parent one?</html>
+hg4idea.init.already.under.hg.title=This directory is already under hg
+hg4idea.init.already.under.hg.dialog.title=Directory is under hg
+hg4idea.init.already.under.hg.option.use.parent=Use parent repository, but keep working in this project.
+hg4idea.init.already.under.hg.option.create.repo.here=Create new repository here.
+hg4idea.init.created.notification.title=Mercurial repository created
+hg4idea.init.created.notification.description=Repository was created in {0}
+
+hg4idea.move.progress=Moving files in the VCS...
+
+hg4idea.push.dialog.title=Push
+hg4idea.push.branch=&Branch
+hg4idea.push.force=&Force push
 
 hg4idea.remove.single.title=Remove file from Mercurial
 hg4idea.remove.single.body=Do you want to remove the following file from Mercurial?\n{0}\n\nIf you say NO, you can still remove it later manually.
 hg4idea.remove.multiple.title=Remove files from Mercurial
 hg4idea.remove.progress=Removing files from the VCS...
 
-hg4idea.move.progress=Moving files in the VCS...
-
 hg4idea.update.error.uncommittedMerge=outstanding uncommitted merge in repository {0}, not updating or merging
 hg4idea.update.error.localchanges=outstanding uncommitted changes in repository {0}, not merging with pulled head
 hg4idea.update.error.merge.multipleLocalHeads=More than one local head in repository {0}, not merging
@@ -84,16 +91,13 @@ hg4idea.update.progress.updating.to.pulled.head=Updating to pulled head
 hg4idea.update.progress.merging=Merging with pulled head
 
 hg4idea.progress.updatingworkingdir=Updating local working directory
-
 hg4idea.progress.integrating=Integrating {0} ...
 hg4idea.progress.merging=Performing merge...
 hg4idea.progress.updating=Updating {0} ...
 hg4idea.progress.countingHeads=Checking number of heads...
 hg4idea.progress.pull.with.rebase=Rebasing patches
 hg4idea.progress.pull.with.update=Updating repository
-hg4idea.commit.success=Repository \"{0}\" committed
-hg4idea.commit.partial.merge.message=<html>Partial commits are not allowed during merge, and following files are not included:<ul>{0}</ul>Perform commit with all files included ?</html>
-hg4idea.commit.partial.merge.title=Partial Merge Commit
+
 hg4idea.error.invalidTarget=Invalid integration target
 hg4idea.status.currentSituationtext=<html><b>{0}</b><em>({1})</em></html>
 hg4idea.status.currentSituation.description=<html>Current mercurial branch and parents of the working directory</html>
@@ -103,5 +107,4 @@ hg4idea.error.invalidExecutable=\"{0}\" is not a valid mercurial executable
 hg4idea.integrate.other.head=Other head: {0}
 
 hgidea.dialog.login.password.required=Login and password required
-
-hg4idea.exception.file.not.under.hg=The file {0} is not under Mercurial.
+hg4idea.exception.file.not.under.hg=The file {0} is not under Mercurial.
\ No newline at end of file
index cdebfe23480c61a6e94ed292021ac2de8083b1b5..9a22f9b69302c1f717b3d0d8641e8d949005c389 100644 (file)
@@ -43,14 +43,11 @@ public class HgPushAction extends HgAbstractGlobalAction {
       }
 
       public void execute() {
-        HgPushCommand command = new HgPushCommand(
-          project, dialog.getRepository(), dialog.getTarget()
-        );
-        if (dialog.isRevisionSelected()) {
-          command.setRevision(dialog.getRevision());
-        }
-        HgCommandResult result = command.execute();
-        new HgCommandResultNotifier(project).process(result);
+        HgPushCommand command = new HgPushCommand(project, dialog.getRepository(), dialog.getTarget());
+        command.setRevision(dialog.getRevision());
+        command.setForce(dialog.isForce());
+        command.setBranch(dialog.getBranch());
+        new HgCommandResultNotifier(project).process(command.execute());
       }
     };
   }
index d92ded120133a5c940318058d16358833ccb9ad8..09fbd76a24a1a7149a6dab56bbfc47c395911013 100644 (file)
@@ -23,35 +23,51 @@ import java.util.List;
 
 public class HgPushCommand {
 
-  private final Project project;
-  private final VirtualFile repo;
-  private final String destination;
+  private final Project myProject;
+  private final VirtualFile myRepo;
+  private final String myDestination;
   private final HgCommandAuthenticator authenticator = new HgCommandAuthenticator();
 
-  private String revision;
+  private String myRevision;
+  private boolean myForce;
+  private HgTagBranch myBranch;
 
   public HgPushCommand(Project project, @NotNull VirtualFile repo, String destination) {
-    this.project = project;
-    this.repo = repo;
-    this.destination = destination;
+    myProject = project;
+    myRepo = repo;
+    myDestination = destination;
   }
 
   public void setRevision(String revision) {
-    this.revision = revision;
+    myRevision = revision;
+  }
+
+  public void setForce(boolean force) {
+    myForce = force;
+  }
+
+  public void setBranch(HgTagBranch branch) {
+    myBranch = branch;
   }
 
   public HgCommandResult execute() {
-    List<String> arguments = new LinkedList<String>();
-    if (StringUtils.isNotBlank(revision)) {
+    final List<String> arguments = new LinkedList<String>();
+    if (StringUtils.isNotBlank(myRevision)) {
       arguments.add("-r");
-      arguments.add(revision);
+      arguments.add(myRevision);
     }
-    arguments.add(destination);
-
-    HgCommandResult result = authenticator.executeCommandAndAuthenticateIfNecessary(project, repo, destination, "push", arguments);
-
-    project.getMessageBus().syncPublisher(HgVcs.OUTGOING_TOPIC).update(project);
+    if (myBranch != null) {
+      arguments.add("-b");
+      arguments.add(myBranch.getName());
+    }
+    if (myForce) {
+      arguments.add("-f");
+    }
+    arguments.add(myDestination);
 
+    final HgCommandResult result = authenticator.executeCommandAndAuthenticateIfNecessary(myProject, myRepo, myDestination, "push", arguments);
+    myProject.getMessageBus().syncPublisher(HgVcs.OUTGOING_TOPIC).update(myProject);
     return result;
   }
+
 }
index 3441dc1bdf881ed67af8bd833048228fbc4f2b9d..a77faefa5901c6fe0bb8dcb165adcdab4b389f78 100644 (file)
@@ -3,12 +3,12 @@
   <grid id="27dc6" binding="contentPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" 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="529" height="243"/>
+      <xy x="20" y="20" width="529" height="307"/>
     </constraints>
     <properties/>
     <border type="none"/>
     <children>
-      <grid id="16351" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+      <grid id="16351" layout-manager="GridLayoutManager" row-count="6" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
         <margin top="0" left="0" bottom="0" right="0"/>
         <constraints>
           <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -18,7 +18,7 @@
         <children>
           <vspacer id="f51de">
             <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"/>
+              <grid row="5" 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>
           <component id="59224" class="javax.swing.JLabel">
@@ -36,7 +36,7 @@
             </constraints>
             <properties/>
           </component>
-          <grid id="3b42" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+          <grid id="3b42" layout-manager="GridLayoutManager" row-count="3" 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>
               <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
                   <text value="tip"/>
                 </properties>
               </component>
-              <vspacer id="d2af5">
-                <constraints>
-                  <grid row="1" 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>
               <hspacer id="27a66">
                 <constraints>
-                  <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                  <grid row="2" 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="5fcc4" class="javax.swing.JCheckBox" binding="forceCheckBox" 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 resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.push.force"/>
+                </properties>
+              </component>
+              <component id="e6341" class="javax.swing.JCheckBox" binding="branchCheckBox" 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 resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.push.branch"/>
+                </properties>
+              </component>
+              <component id="1adc4" class="javax.swing.JComboBox" binding="branchComboBox">
+                <constraints>
+                  <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+              </component>
             </children>
           </grid>
           <nested-form id="9e17d" form-file="org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.form" binding="hgRepositorySelectorComponent">
index 8048638ef2705f1ff4d101faf0d2797711c079d3..f08cda41c8e4067bd3837f5a432a20dbeb10c634 100644 (file)
@@ -16,7 +16,11 @@ import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.apache.commons.lang.StringUtils;
+import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.HgVcsMessages;
 import org.zmlx.hg4idea.command.HgShowConfigCommand;
+import org.zmlx.hg4idea.command.HgTagBranch;
+import org.zmlx.hg4idea.command.HgTagBranchCommand;
 
 import javax.swing.*;
 import javax.swing.event.ChangeEvent;
@@ -26,20 +30,25 @@ import javax.swing.event.DocumentListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.Collection;
+import java.util.List;
 
 public class HgPushDialog extends DialogWrapper {
 
-  private final Project project;
+  private final Project myProject;
 
   private JPanel contentPanel;
   private JTextField repositoryTxt;
   private JCheckBox revisionCbx;
   private JTextField revisionTxt;
   private HgRepositorySelectorComponent hgRepositorySelectorComponent;
+  private JCheckBox forceCheckBox;
+  private JCheckBox branchCheckBox;
+  private JComboBox branchComboBox;
 
   public HgPushDialog(Project project) {
     super(project, false);
-    this.project = project;
+    myProject = project;
+
     hgRepositorySelectorComponent.setTitle("Select repository to push from");
     hgRepositorySelectorComponent.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent e) {
@@ -47,30 +56,13 @@ public class HgPushDialog extends DialogWrapper {
       }
     });
 
-    revisionCbx.addChangeListener(new ChangeListener() {
-      public void stateChanged(ChangeEvent e) {
-        update();
-      }
-    });
-
-    DocumentListener documentListener = new DocumentListener() {
-      public void insertUpdate(DocumentEvent e) {
-        update();
-      }
-
-      public void removeUpdate(DocumentEvent e) {
-        update();
-      }
+    final UpdatingListener updatingListener = new UpdatingListener();
+    revisionCbx.addChangeListener(updatingListener);
+    branchCheckBox.addChangeListener(updatingListener);
+    repositoryTxt.getDocument().addDocumentListener(updatingListener);
+    revisionTxt.getDocument().addDocumentListener(updatingListener);
 
-      public void changedUpdate(DocumentEvent e) {
-        update();
-      }
-    };
-
-    repositoryTxt.getDocument().addDocumentListener(documentListener);
-    revisionTxt.getDocument().addDocumentListener(documentListener);
-
-    setTitle("Push");
+    setTitle(HgVcsMessages.message("hg4idea.push.dialog.title"));
     init();
   }
 
@@ -87,34 +79,70 @@ public class HgPushDialog extends DialogWrapper {
     return repositoryTxt.getText();
   }
 
-  public boolean isRevisionSelected() {
-    return revisionCbx.isSelected();
+  @Nullable
+  public String getRevision() {
+    return revisionCbx.isSelected() ? revisionTxt.getText() : null;
   }
 
-  public String getRevision() {
-    return revisionTxt.getText();
+  @Nullable
+  public HgTagBranch getBranch() {
+    return branchCheckBox.isSelected() ? (HgTagBranch) branchComboBox.getSelectedItem() : null;
+  }
+
+  public boolean isForce() {
+    return forceCheckBox.isSelected();
+  }
+
+  protected JComponent createCenterPanel() {
+    return contentPanel;
   }
 
   private void updateRepository() {
-    VirtualFile repo = hgRepositorySelectorComponent.getRepository();
-    HgShowConfigCommand configCommand = new HgShowConfigCommand(project);
-    String defaultPath = configCommand.getDefaultPath(repo);
+    final VirtualFile repo = hgRepositorySelectorComponent.getRepository();
+    final HgShowConfigCommand configCommand = new HgShowConfigCommand(myProject);
+    final String defaultPath = configCommand.getDefaultPath(repo);
     repositoryTxt.setText(defaultPath);
+    loadBranches(repo);
     update();
   }
 
-  protected JComponent createCenterPanel() {
-    return contentPanel;
+  private void loadBranches(VirtualFile root) {
+    final List<HgTagBranch> branches = new HgTagBranchCommand(myProject, root).listBranches();
+    branchComboBox.setModel(new DefaultComboBoxModel(branches.toArray()));
   }
 
   private void update() {
     setOKActionEnabled(validateOptions());
     revisionTxt.setEnabled(revisionCbx.isSelected());
+    branchComboBox.setEnabled(branchCheckBox.isSelected());
   }
 
   private boolean validateOptions() {
     return StringUtils.isNotBlank(repositoryTxt.getText())
-      && !(revisionCbx.isSelected() && StringUtils.isBlank(revisionTxt.getText()));
+      && !(revisionCbx.isSelected() && StringUtils.isBlank(revisionTxt.getText()))
+      && !(branchCheckBox.isSelected() && (branchComboBox.getSelectedItem() == null));
+  }
+
+  /**
+   * Updates the form on every change.
+   */
+  private class UpdatingListener implements ChangeListener, DocumentListener {
+
+    public void stateChanged(ChangeEvent e) {
+      update();
+    }
+
+    public void insertUpdate(DocumentEvent e) {
+      update();
+    }
+
+    public void removeUpdate(DocumentEvent e) {
+      update();
+    }
+
+    public void changedUpdate(DocumentEvent e) {
+      update();
+    }
   }
 
 }