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.
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;
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;
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"
));
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 {
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;
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;
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);
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;
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;
arguments.add("--follow");
arguments.add("--template");
- arguments.add(TEMPLATE);
+ arguments.add(HgChangesetUtil.makeTemplate(TEMPLATE_ITEMS));
if (limit != -1) {
arguments.add("--limit");
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;
}
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;
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());
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]));
}
--- /dev/null
+/*
+ * 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();
+ }
+
+}