IDEA-67921 IDEA-65888 Mercurial installed via easy_install/pip on Windows.

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.
This commit is contained in:
Kirill Likhodedov
2011-04-14 10:52:02 +04:00
parent da3c058a19
commit 636f5cf38c
5 changed files with 70 additions and 24 deletions
@@ -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 {
@@ -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;
@@ -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;
}
@@ -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]));
}
@@ -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();
}
}