Merge branch 'master' of git.labs.intellij.net:idea/community
authorKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Tue, 13 Jul 2010 06:21:00 +0000 (10:21 +0400)
committerKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Tue, 13 Jul 2010 06:21:00 +0000 (10:21 +0400)
13 files changed:
plugins/hg4idea/hg4idea.iml
plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
plugins/hg4idea/src/META-INF/plugin.xml
plugins/hg4idea/src/org/zmlx/hg4idea/HgRootsHandler.java [new file with mode: 0644]
plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java
plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java
plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandService.java
plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java
plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java
plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.form
plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java

index f7efe10c0e5fbeae7429e4b25f66bd795b7efb5c..1c036a8a3851545f12d389018d1c03e0337e126c 100644 (file)
@@ -16,6 +16,7 @@
     <orderEntry type="module" module-name="platform-api" />
     <orderEntry type="module" module-name="vcs-impl" />
     <orderEntry type="module" module-name="platform-impl" />
+    <orderEntry type="module" module-name="lang-api" />
   </component>
 </module>
 
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 6fea72617466b5a30499dd13f00229c32fafe557..d5d089952b2a98cff828fac174e46f8b2534a75a 100644 (file)
@@ -33,6 +33,8 @@
                     serviceImplementation="org.zmlx.hg4idea.HgProjectSettings"/>
     <projectService serviceInterface="org.zmlx.hg4idea.command.HgCommandService"
                     serviceImplementation="org.zmlx.hg4idea.command.HgCommandService"/>
+    <projectService serviceInterface="org.zmlx.hg4idea.HgRootsHandler"
+                    serviceImplementation="org.zmlx.hg4idea.HgRootsHandler" />
   </extensions>
 
   <actions>
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRootsHandler.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRootsHandler.java
new file mode 100644 (file)
index 0000000..5da6243
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.zmlx.hg4idea;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.AbstractVcs;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.vcsUtil.VcsUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public class HgRootsHandler implements AbstractVcs.RootsConvertor {
+
+  private final Project myProject;
+
+  public HgRootsHandler(Project project) {
+    myProject = project;
+  }
+
+  public static HgRootsHandler getInstance(Project project) {
+    return ServiceManager.getService(project, HgRootsHandler.class);
+  }
+
+  @Override
+  public List<VirtualFile> convertRoots(List<VirtualFile> original) {
+    final Set<VirtualFile> result = new THashSet<VirtualFile>(original.size());
+    for (VirtualFile vf : original) {
+      final VirtualFile root = convertRoot(vf);
+      if (root != null) {
+        result.add(root);
+      }
+    }
+    return new ArrayList<VirtualFile>(result);
+  }
+
+  @Nullable
+  public VirtualFile getRootFor(VirtualFile file) {
+    return convertRoot(VcsUtil.getVcsRootFor(myProject, file));
+  }
+
+  @Nullable
+  public VirtualFile getRootFor(FilePath filepath) {
+    return convertRoot(VcsUtil.getVcsRootFor(myProject, filepath));
+  }
+
+  @Nullable
+  private VirtualFile convertRoot(@Nullable VirtualFile root) {
+    return HgUtil.getHgRootOrNull(myProject, root);
+  }
+
+}
+
index e882af9bd3259358a699fc06b442da00bc1c6ebe..d08fbbb75f1dd011585ad94681a60a6bd6372548 100644 (file)
@@ -196,8 +196,7 @@ public abstract class HgUtil {
    */
   @Nullable
   public static VirtualFile getHgRootOrNull(Project project, FilePath filePath) {
-    final VirtualFile vf = VcsUtil.getVcsRootFor(project, filePath);
-    return (vf == null || !isHgRoot(vf) ? null : vf);
+    return getNearestHgRoot(VcsUtil.getVcsRootFor(project, filePath));
   }
 
   /**
index 52e92e0ef1098ed42fd9a6341914c116637d30cd..4b8d677c9267f351c94348be12b889e1dba26b2a 100644 (file)
 package org.zmlx.hg4idea;
 
 import com.intellij.concurrency.JobScheduler;
+import com.intellij.execution.ui.ConsoleViewContentType;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diff.impl.patch.formove.FilePathComparator;
+import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
 import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
 import com.intellij.openapi.fileEditor.FileEditorManagerListener;
@@ -34,13 +37,18 @@ import com.intellij.openapi.vcs.diff.DiffProvider;
 import com.intellij.openapi.vcs.history.VcsHistoryProvider;
 import com.intellij.openapi.vcs.rollback.RollbackEnvironment;
 import com.intellij.openapi.vcs.update.UpdateEnvironment;
+import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileListener;
 import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.openapi.wm.StatusBar;
 import com.intellij.openapi.wm.WindowManager;
+import com.intellij.util.containers.ComparatorDelegate;
+import com.intellij.util.containers.Convertor;
 import com.intellij.util.messages.MessageBusConnection;
 import com.intellij.util.messages.Topic;
+import org.jetbrains.annotations.NotNull;
 import org.zmlx.hg4idea.provider.*;
 import org.zmlx.hg4idea.provider.annotate.HgAnnotationProvider;
 import org.zmlx.hg4idea.provider.commit.HgCheckinEnvironment;
@@ -51,10 +59,12 @@ import org.zmlx.hg4idea.ui.HgCurrentBranchStatus;
 
 import javax.swing.*;
 import java.io.File;
+import java.util.Collections;
+import java.util.List;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
-public class HgVcs extends AbstractVcs {
+public class HgVcs extends AbstractVcs<CommittedChangeList> {
 
   public static final Topic<HgUpdater> BRANCH_TOPIC =
     new Topic<HgUpdater>("hg4idea.branch", HgUpdater.class);
@@ -94,16 +104,19 @@ public class HgVcs extends AbstractVcs {
   private ScheduledFuture<?> changesUpdaterScheduledFuture;
   private final HgGlobalSettings globalSettings;
   private final HgProjectSettings projectSettings;
+  private final ProjectLevelVcsManager myVcsManager;
 
   private boolean started = false;
   private HgVFSListener myVFSListener;
   private VirtualFileListener myDirStateChangeListener;
 
   public HgVcs(Project project,
-    HgGlobalSettings globalSettings, HgProjectSettings projectSettings) {
+    HgGlobalSettings globalSettings, HgProjectSettings projectSettings,
+    ProjectLevelVcsManager vcsManager) {
     super(project, VCS_NAME);
     this.globalSettings = globalSettings;
     this.projectSettings = projectSettings;
+    myVcsManager = vcsManager;
     configurable = new HgProjectConfigurable(projectSettings);
     changeProvider = new HgChangeProvider(project, getKeyInstanceMethod());
     rollbackEnvironment = new HgRollbackEnvironment(project);
@@ -212,6 +225,43 @@ public class HgVcs extends AbstractVcs {
   }
 
   @Override
+  public boolean allowsNestedRoots() {
+    return true;
+  }
+
+  @Override
+  public <S> List<S> filterUniqueRoots(final List<S> in, final Convertor<S, VirtualFile> convertor) {
+    Collections.sort(in, new ComparatorDelegate<S, VirtualFile>(convertor, FilePathComparator.getInstance()));
+
+    for (int i = 1; i < in.size(); i++) {
+      final S sChild = in.get(i);
+      final VirtualFile child = convertor.convert(sChild);
+      final VirtualFile childRoot = HgUtil.getHgRootOrNull(myProject, child);
+      if (childRoot == null) {
+        continue;
+      }
+      for (int j = i - 1; j >= 0; --j) {
+        final S sParent = in.get(j);
+        final VirtualFile parent = convertor.convert(sParent);
+        // if the parent is an ancestor of the child and that they share common root, the child is removed
+        if (VfsUtil.isAncestor(parent, child, false) && VfsUtil.isAncestor(childRoot, parent, false)) {
+          in.remove(i);
+          //noinspection AssignmentToForLoopParameter
+          --i;
+          break;
+        }
+      }
+    }
+    return in;
+  }
+
+
+  @Override
+  public RootsConvertor getCustomConvertor() {
+    return HgRootsHandler.getInstance(myProject);
+  }
+
+    @Override
   public boolean isVersionedDirectory(VirtualFile dir) {
     return HgUtil.getNearestHgRoot(dir) != null;
   }
@@ -344,4 +394,10 @@ public class HgVcs extends AbstractVcs {
   public HgGlobalSettings getGlobalSettings() {
     return globalSettings;
   }
+
+  public void showMessageInConsole(String message, final TextAttributes style) {
+    myVcsManager.addMessageToConsoleWindow(message, style);
+  }
+
+
 }
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 5efd3bba869c202d735d068c5f0cfdf27735485c..aefb8fc54fa2677066ed03ee1b79ba547faee07a 100644 (file)
@@ -12,6 +12,7 @@
 // limitations under the License.
 package org.zmlx.hg4idea.command;
 
+import com.intellij.execution.ui.ConsoleViewContentType;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.components.ServiceManager;
@@ -19,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.vcsUtil.VcsUtil;
+import org.apache.commons.lang.StringUtils;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.*;
 
@@ -40,7 +42,7 @@ public final class HgCommandService {
 
   static final Logger LOG = Logger.getInstance(HgCommandService.class.getName());
 
-  private static final List<String> DEFAULT_OPTIONS = Arrays.asList(
+  static final List<String> DEFAULT_OPTIONS = Arrays.asList(
     "--config", "ui.merge=internal:merge"
   );
 
@@ -77,6 +79,11 @@ public final class HgCommandService {
   @Nullable
   HgCommandResult execute(VirtualFile repo, List<String> hgOptions,
     String operation, List<String> arguments, Charset charset) {
+    return execute(repo, hgOptions, operation, arguments, charset, false);
+  }
+
+  HgCommandResult execute(VirtualFile repo, List<String> hgOptions,
+    String operation, List<String> arguments, Charset charset, boolean suppressCommandOutput) {
 
     if (!validator.check(mySettings)) {
       return null;
@@ -134,6 +141,17 @@ public final class HgCommandService {
     }
     String warnings = warningReceiver.getWarnings();
     result.setWarnings(warnings);
+
+    // logging to the Version Control console (without extensions and configs)
+    final String cmdString = String.format("%s %s %s", HgVcs.HG_EXECUTABLE_FILE_NAME, operation,
+            StringUtils.join(arguments, " "));
+    final HgVcs hgVcs = HgVcs.getInstance(myProject);
+    hgVcs.showMessageInConsole(cmdString, ConsoleViewContentType.USER_INPUT.getAttributes());
+    if (!suppressCommandOutput) {
+      hgVcs.showMessageInConsole(result.getRawOutput(), ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
+    }
+    hgVcs.showMessageInConsole(result.getRawError(), ConsoleViewContentType.ERROR_OUTPUT.getAttributes());
+
     return result;
 
   }
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 210ac7de88e2c0748d7872dd7471ee4a8b429c64..7c429d2d400e35ec1315b7902167787876cb37cb 100644 (file)
@@ -22,6 +22,7 @@ import org.zmlx.hg4idea.HgFile;
 import org.zmlx.hg4idea.HgRevisionNumber;
 
 import java.io.File;
+import java.nio.charset.Charset;
 import java.util.*;
 
 public class HgStatusCommand {
@@ -135,7 +136,7 @@ public class HgStatusCommand {
       arguments.add(file);
     }
 
-    HgCommandResult result = service.execute(repo, "status", arguments);
+    HgCommandResult result = service.execute(repo, HgCommandService.DEFAULT_OPTIONS, "status", arguments, Charset.defaultCharset(), true);
     Set<HgChange> changes = new HashSet<HgChange>();
     HgChange previous = null;
     if (result == null) {
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();
+    }
   }
 
 }
index 8c6bea1597660c0e4ba2b34c9ca82c88924073df..affa07b792b90a130439a0bee0cb86e2d331d158 100644 (file)
@@ -50,35 +50,6 @@ public class HgRepositorySelectorComponent {
     return ((RepositoryDisplay) repositorySelector.getSelectedItem()).repo;
   }
 
-  {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-    $$$setupUI$$$();
-  }
-
-  /**
-   * Method generated by IntelliJ IDEA GUI Designer
-   * >>> IMPORTANT!! <<<
-   * DO NOT edit this method OR call it in your code!
-   *
-   * @noinspection ALL
-   */
-  private void $$$setupUI$$$() {
-    mainPanel = new JPanel();
-    mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
-    mainPanel.setBorder(BorderFactory.createTitledBorder("Select repository"));
-    repositorySelector = new JComboBox();
-    mainPanel.add(repositorySelector, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
-  }
-
-  /**
-   * @noinspection ALL
-   */
-  public JComponent $$$getRootComponent$$$() {
-    return mainPanel;
-  }
-
   private class RepositoryDisplay {
     private final VirtualFile repo;