IDEA-67921 IDEA-65888 Mercurial installed via easy_install/pip on Windows.
authorKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Wed, 13 Apr 2011 15:31:27 +0000 (19:31 +0400)
committerKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Thu, 14 Apr 2011 06:52:02 +0000 (10:52 +0400)
Root cause: the pipe symbol (|) used in changesets templates (--template) is interpreted by system in the case of such configuration and running via hg.bat).

If Windows, surround the template by double-quotes.
It breaks UNIX version, however, so don't do it for UNIX.

Refactored all usages of --template to go through HgChangesetUtil.makeTemplate() using common separators and quoting if needed.

plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChangesetsCommand.java
plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRevisionsCommand.java
plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTrackFileNamesAccrossRevisionsCommand.java
plugins/hg4idea/src/org/zmlx/hg4idea/command/HgWorkingCopyRevisionsCommand.java
plugins/hg4idea/src/org/zmlx/hg4idea/util/HgChangesetUtil.java [new file with mode: 0644]

index 261fdda52a77c302988881b6644087558e462b9d..c8f1ad54d7e8780a0c46fa7d53f4ea94b34c2d83 100644 (file)
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgRevisionNumber;
 import org.zmlx.hg4idea.execution.HgCommandExecutor;
 import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.util.HgChangesetUtil;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -33,8 +34,6 @@ public abstract class HgChangesetsCommand {
 
   private static final Logger LOG = Logger.getInstance(HgChangesetsCommand.class.getName());
 
-  private static final String SEPARATOR_STRING = "\u0017"; //ascii: end of transmission block
-  
   protected final Project project;
   protected final String command;
 
@@ -50,7 +49,7 @@ public abstract class HgChangesetsCommand {
   protected List<HgRevisionNumber> getRevisions(VirtualFile repo) {
     List<String> args = new ArrayList<String>(Arrays.asList(
       "--template",
-      "{rev}|{node|short}|{author}|{desc|firstline}" + SEPARATOR_STRING,
+      HgChangesetUtil.makeTemplate("{rev}", "{node|short}", "{author}", "{desc|firstline}"),
       "--quiet"
     ));
 
@@ -67,11 +66,11 @@ public abstract class HgChangesetsCommand {
       return Collections.emptyList();
     }
     
-    String[] changesets = output.split(SEPARATOR_STRING);
+    String[] changesets = output.split(HgChangesetUtil.CHANGESET_SEPARATOR);
     List<HgRevisionNumber> revisions = new ArrayList<HgRevisionNumber>(changesets.length);
     
     for(String changeset: changesets) {
-      String[] parts = StringUtils.split(changeset, "|", 4);
+      String[] parts = StringUtils.split(changeset, HgChangesetUtil.ITEM_SEPARATOR, 4);
       if (parts.length == 4) {
         revisions.add(HgRevisionNumber.getInstance(parts[0], parts[1], parts[2], parts[3]));
       } else {
index 3e5ee5319ce6cb3a61f183ad8e5120409e0e7ace..ce13c6e053fab822282cdf732478bf567c1a3b65 100644 (file)
@@ -23,6 +23,7 @@ import org.zmlx.hg4idea.HgFile;
 import org.zmlx.hg4idea.HgFileRevision;
 import org.zmlx.hg4idea.HgRevisionNumber;
 import org.zmlx.hg4idea.HgUtil;
+import org.zmlx.hg4idea.util.HgChangesetUtil;
 import org.zmlx.hg4idea.execution.HgCommandResult;
 import org.zmlx.hg4idea.execution.HgCommandExecutor;
 
@@ -33,12 +34,10 @@ import java.util.*;
 abstract class HgRevisionsCommand {
 
   private static final Logger LOG = Logger.getInstance(HgRevisionsCommand.class.getName());
-  private static final String SEPARATOR_STRING = "\u0017"; //ascii: end of transmission block
 
-  private static final String SHORT_TEMPLATE = "{rev}|{node|short}|{parents}|{date|isodatesec}|{author}|{branches}|{desc}" + SEPARATOR_STRING;
-  private static final int SHORT_ITEM_COUNT = 7;
-  private static final String LONG_TEMPLATE = "{rev}|{node|short}|{parents}|{date|isodatesec}|{author}|{branches}|{desc}|{file_adds}|{file_mods}|{file_dels}|{file_copies}" + SEPARATOR_STRING;
-  private static final int LONG_ITEM_COUNT = 11;
+  private static final String[] SHORT_TEMPLATE_ITEMS = { "{rev}","{node|short}", "{parents}", "{date|isodatesec}", "{author}", "{branches}", "{desc}" };
+  private static final String[] LONG_TEMPLATE_ITEMS =
+    { "{rev}", "{node|short}", "{parents}", "{date|isodatesec}", "{author}", "{branches}", "{desc}", "{file_adds}", "{file_mods}", "{file_dels}", "{file_copies}" };
 
   private static final int REVISION_INDEX = 0;
   private static final int CHANGESET_INDEX = 1;
@@ -73,8 +72,8 @@ abstract class HgRevisionsCommand {
 
     HgCommandExecutor hgCommandExecutor = new HgCommandExecutor(project);
 
-    String template = includeFiles ? LONG_TEMPLATE : SHORT_TEMPLATE;
-    int itemCount = includeFiles ? LONG_ITEM_COUNT : SHORT_ITEM_COUNT;
+    String template = HgChangesetUtil.makeTemplate(includeFiles ? LONG_TEMPLATE_ITEMS : SHORT_TEMPLATE_ITEMS);
+    int itemCount = includeFiles ? LONG_TEMPLATE_ITEMS.length : SHORT_TEMPLATE_ITEMS.length;
 
     FilePath originalFileName = HgUtil.getOriginalFileName(hgFile.toFilePath(), ChangeListManager.getInstance(project));
     HgFile originalHgFile = new HgFile(hgFile.getRepo(), originalFileName);
@@ -84,10 +83,10 @@ abstract class HgRevisionsCommand {
 
     List<HgFileRevision> revisions = new LinkedList<HgFileRevision>();
     String output = result.getRawOutput();
-    String[] changeSets = output.split(SEPARATOR_STRING);
+    String[] changeSets = output.split(HgChangesetUtil.CHANGESET_SEPARATOR);
     for (String line : changeSets) {
       try {
-        String[] attributes = StringUtils.splitPreserveAllTokens(line, '|');
+        String[] attributes = line.split(HgChangesetUtil.ITEM_SEPARATOR);
         if (attributes.length != itemCount) {
           LOG.debug("Wrong format. Skipping line " + line);
           continue;
index ee141ca08e9ae0acbc9816dcf73c8ef20094eff9..49e171540ebfec3e8d517a8e17d9f974627e63cc 100644 (file)
@@ -19,16 +19,15 @@ import org.apache.commons.lang.StringUtils;
 import org.zmlx.hg4idea.HgFile;
 import org.zmlx.hg4idea.execution.HgCommandExecutor;
 import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.util.HgChangesetUtil;
 
 import java.util.*;
 
 class HgTrackFileNamesAccrossRevisionsCommand {
 
   private static final Logger LOG = Logger.getInstance(HgTrackFileNamesAccrossRevisionsCommand.class.getName());
-  private static final String SEPARATOR_STRING = "\u0027"; //ascii: end of transmission block
 
-  private static final String TEMPLATE = "{rev}|{file_dels}|{file_copies}" + SEPARATOR_STRING;
-  private static final int ITEM_COUNT = 3;
+  private static final String[] TEMPLATE_ITEMS = { "{rev}", "{file_dels}", "{file_copies}" };
 
   private static final int REVISION_INDEX = 0;
   private static final int FILES_DELETED_INDEX = 1;
@@ -48,7 +47,7 @@ class HgTrackFileNamesAccrossRevisionsCommand {
 
     arguments.add("--follow");
     arguments.add("--template");
-    arguments.add(TEMPLATE);
+    arguments.add(HgChangesetUtil.makeTemplate(TEMPLATE_ITEMS));
 
     if (limit != -1) {
       arguments.add("--limit");
@@ -69,15 +68,15 @@ class HgTrackFileNamesAccrossRevisionsCommand {
     HgCommandResult result = execute(hgCommandExecutor, hgFile.getRepo(), limit, hgFile, currentRevision, givenRevision);
 
     String output = result.getRawOutput();
-    String[] changeSets = output.split(SEPARATOR_STRING);
+    String[] changeSets = output.split(HgChangesetUtil.CHANGESET_SEPARATOR);
     String currentFileName = hgFile.getRelativePath();
     // needed on windows machines
     currentFileName = currentFileName.replaceAll("\\\\", "/");
 
     for (String line : changeSets) {
       try {
-        String[] attributes = StringUtils.splitPreserveAllTokens(line, '|');
-        if (attributes.length != ITEM_COUNT) {
+        String[] attributes = line.split(HgChangesetUtil.ITEM_SEPARATOR);
+        if (attributes.length != TEMPLATE_ITEMS.length) {
           LOG.debug("Wrong format. Skipping line " + line);
           continue;
         }
index db4e5de1ab98d8fdc9407dafb567d18f2fc1798d..689ceb481b7d844f68dacf721bfe6c95b9b812e3 100644 (file)
@@ -25,6 +25,7 @@ import org.zmlx.hg4idea.HgRevisionNumber;
 import org.zmlx.hg4idea.HgUtil;
 import org.zmlx.hg4idea.execution.HgCommandResult;
 import org.zmlx.hg4idea.execution.HgCommandExecutor;
+import org.zmlx.hg4idea.util.HgChangesetUtil;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -165,7 +166,7 @@ public class HgWorkingCopyRevisionsCommand {
                                               boolean silent) {
     final List<String> args = new LinkedList<String>();
     args.add("--template");
-    args.add("{rev}|{node|short}\\n");
+    args.add(HgChangesetUtil.makeTemplate("{rev}", "{node|short}"));
     if (revision != null) {
       args.add("-r");
       args.add(revision.getChangeset());
@@ -180,10 +181,10 @@ public class HgWorkingCopyRevisionsCommand {
     if (result == null) {
       return new ArrayList<HgRevisionNumber>(0);
     }
-    final List<String> lines = result.getOutputLines();
+    final List<String> lines = Arrays.asList(result.getRawOutput().split(HgChangesetUtil.CHANGESET_SEPARATOR));
     final List<HgRevisionNumber> revisions = new ArrayList<HgRevisionNumber>(lines.size());
     for(String line: lines) {
-      final String[] parts = StringUtils.split(line, '|');
+      final String[] parts = StringUtils.split(line, HgChangesetUtil.ITEM_SEPARATOR);
       revisions.add(HgRevisionNumber.getInstance(parts[0], parts[1]));
     }
     
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgChangesetUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgChangesetUtil.java
new file mode 100644 (file)
index 0000000..9118dc2
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2011 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.util;
+
+import com.intellij.openapi.util.SystemInfo;
+
+/**
+ * Utilities for operations involving working with a number of changesets: log, incoming, outgoing, parents, etc.
+ * @author Kirill Likhodedov
+ */
+public class HgChangesetUtil {
+
+  public static final String CHANGESET_SEPARATOR = "\u0003";
+  public static final String ITEM_SEPARATOR = "\u0017";
+
+  /**
+   * Common method for hg commands which receive templates via --template option.
+   * @param templateItems template items like <pre>{rev}</pre>, <pre>{node}</pre>.
+   * @return items joined by ITEM_SEPARATOR, ended by CHANGESET_SEPARATOR, and, if needed (for Windows), surrounded with double-quotes.
+   */
+  public static String makeTemplate(String... templateItems) {
+    StringBuilder template = new StringBuilder();
+
+    for (String item : templateItems) {
+      template.append(item).append(ITEM_SEPARATOR);
+    }
+
+    template.append(CHANGESET_SEPARATOR);
+    if (SystemInfo.isWindows) {
+      return "\"" + template + "\"";
+    }
+    return template.toString();
+  }
+
+}