diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index 7594b138d450..5f2a8ccc89e2 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -66,7 +66,9 @@ import org.zmlx.hg4idea.util.HgVersion; import javax.swing.event.HyperlinkEvent; import java.io.File; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class HgVcs extends AbstractVcs { @@ -111,6 +113,7 @@ public class HgVcs extends AbstractVcs { private HgIncomingOutgoingWidget myIncomingWidget; private HgIncomingOutgoingWidget myOutgoingWidget; @NotNull private HgVersion myVersion = HgVersion.NULL; // version of Hg which this plugin uses. + @NotNull private Set unsupportedExtension = new HashSet(); public HgVcs(Project project, @NotNull HgGlobalSettings globalSettings, @@ -451,7 +454,7 @@ public class HgVcs extends AbstractVcs { } }; try { - myVersion = HgVersion.identifyVersion(executable); + myVersion = HgVersion.identifyVersion(executable, unsupportedExtension); //if version is not supported, but have valid hg executable if (!myVersion.isSupported()) { LOG.info("Unsupported Hg version: " + myVersion); @@ -459,7 +462,12 @@ public class HgVcs extends AbstractVcs { "The minimal supported version is %s. Please update.", myVersion, HgVersion.MIN); errorNotification.notifyError(null, "Unsupported Hg version", message, linkAdapter); - + } + if (!unsupportedExtension.isEmpty()) { + LOG.warn("Unsupported Hg extensions: " + unsupportedExtension.toString()); + message = String.format("Some hg extensions %s are not found or not supported by your hg version and will be ignored.\n" + + "Please, update your hgrc or Mercurial.ini file", unsupportedExtension.toString()); + errorNotification.notifyWarning("Unsupported Hg version", message); } } catch (Exception e) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java index 65aa3f60d440..fa9b2e7b6386 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java @@ -96,7 +96,7 @@ public class HgLogCommand { */ public final List execute(final HgFile hgFile, int limit, boolean includeFiles, @Nullable List argsForCmd) throws HgCommandException { - if ((limit <= 0 && limit != -1) || hgFile == null || hgFile.getRepo() == null) { + if ((limit <= 0 && limit != -1) || hgFile == null) { return Collections.emptyList(); } @@ -116,7 +116,10 @@ public class HgLogCommand { List errors = result.getErrorLines(); if (errors != null && !errors.isEmpty()) { - throw new HgCommandException(errors.toString()); + if (result.getExitValue() != 0) { + throw new HgCommandException(errors.toString()); + } + LOG.warn(errors.toString()); } String output = result.getRawOutput(); String[] changeSets = output.split(HgChangesetUtil.CHANGESET_SEPARATOR); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java index 460973cbd46c..9e94a0558810 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java @@ -599,7 +599,7 @@ public abstract class HgUtil { return false; } HgCommandResult result = getVersionOutput(executable); - return result.getRawError().isEmpty(); + return result.getExitValue() == 0 && !result.getRawOutput().isEmpty(); } catch (Throwable e) { LOG.info("Error during hg executable validation: ", e); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java index eb41f43a31f9..40da22a8aa99 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java @@ -24,6 +24,10 @@ import org.zmlx.hg4idea.execution.HgCommandResult; import org.zmlx.hg4idea.execution.ShellCommandException; import java.text.ParseException; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -37,7 +41,8 @@ public final class HgVersion implements Comparable { private static final Pattern HG_VERSION_PATTERN = Pattern.compile(".+\\(\\s*\\S+\\s+(\\d+)\\.(\\d+)[\\.]?(\\d)?.*\\s*\\)\\s*.*\\s*", Pattern.CASE_INSENSITIVE); //f.e. Mercurial Distributed SCM (version 2.6+20130507) or Mercurial Distributed SCM (version 2.6.2), 2.7-rc+5-ca2dfc2f63eb - + private static final Pattern HG_UNSUPPORTED_EXTENSION = + Pattern.compile("\\*\\*\\*\\s*failed to import\\s+extension\\s+([a-zA-z0-9\\.-]+).*", Pattern.CASE_INSENSITIVE); /** * The minimal supported version */ @@ -48,7 +53,7 @@ public final class HgVersion implements Comparable { // since 2.3 - 2.5.3 hg has bug with join function with file_copies // see http://mercurial.808500.n3.nabble.com/Bug-3887-New-hg-log-template-quot-rev-join-file-copies-n-quot-prints-literal-quot-sourcename-quot-fos-td4000129.html public static final HgVersion BUILT_IN_FUNCTION_SUPPORTED = new HgVersion(2, 6, 0); - public static final HgVersion PARENT_REVISION_TEMPLATES_SUPPORTED = new HgVersion(2,4,0); + public static final HgVersion PARENT_REVISION_TEMPLATES_SUPPORTED = new HgVersion(2, 4, 0); //see http://selenic.com/pipermail/mercurial-devel/2013-May/051209.html fixed since 2.7 private static final HgVersion LARGEFILES_WITH_FOLLOW_SUPPORTED = new HgVersion(2, 7, 0); @@ -73,18 +78,41 @@ public final class HgVersion implements Comparable { */ @NotNull - public static HgVersion parseVersion(@Nullable String output) throws ParseException { + public static HgVersion parseVersionAndExtensionInfo(@Nullable String output, + @NotNull List errorLines, + @NotNull Set unsupportedExtensions) + throws ParseException { if (StringUtil.isEmptyOrSpaces(output)) { throw new ParseException("Empty hg version output: " + output, 0); } Matcher matcher = HG_VERSION_PATTERN.matcher(output); if (matcher.matches()) { + unsupportedExtensions.addAll(parseUnsupportedExtensions(errorLines)); return new HgVersion(getIntGroup(matcher, 1), getIntGroup(matcher, 2), getIntGroup(matcher, 3)); } LOGGER.error("Couldn't identify hg version: " + output); throw new ParseException("Unsupported format of hg version output: " + output, 0); } + @NotNull + public static Collection parseUnsupportedExtensions(@NotNull List errorLines) { + // hg version command execute with null start directory, + // but hgrc configuration file may be related to one of repository then extension may be failed to import too + //before fixed use command exit value instead if errors.isEmpty + //todo store all unsupported extensions for all repository and notify once + Set extensions = new HashSet(); + if (errorLines.isEmpty()) { + return extensions; + } + for (String line : errorLines) { + Matcher matcher = HG_UNSUPPORTED_EXTENSION.matcher(line); + if (matcher.matches()) { + extensions.add(matcher.group(1)); + } + } + return extensions; + } + // Utility method used in parsing - checks that the given capture group exists and captured something - then returns the captured value, // otherwise returns 0. private static int getIntGroup(@NotNull Matcher matcher, int group) { @@ -100,10 +128,10 @@ public final class HgVersion implements Comparable { } @NotNull - public static HgVersion identifyVersion(@NotNull String executable) + public static HgVersion identifyVersion(@NotNull String executable, @NotNull Set unsupportedExtensions) throws ShellCommandException, InterruptedException, ParseException { HgCommandResult versionResult = HgUtil.getVersionOutput(executable); - return parseVersion(versionResult.getRawOutput()); + return parseVersionAndExtensionInfo(versionResult.getRawOutput(), versionResult.getErrorLines(), unsupportedExtensions); } /** diff --git a/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java b/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java index 6a0e21ae9fd9..b4ece22aca6b 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java @@ -15,10 +15,16 @@ */ package hg4idea.test.version; +import com.intellij.openapi.vcs.VcsTestUtil; +import com.intellij.util.containers.HashSet; import hg4idea.test.HgPlatformTest; import org.zmlx.hg4idea.util.HgVersion; import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; /** * @author Nadya Zabrodina @@ -41,20 +47,37 @@ public class HgVersionTest extends HgPlatformTest { }; public void testParseSupported() throws Exception { + Set unsupportedExceptions = new HashSet(); for (TestHgVersion test : commonTests) { - HgVersion version = HgVersion.parseVersion(test.output); + HgVersion version = HgVersion.parseVersionAndExtensionInfo(test.output, Collections.emptyList(), unsupportedExceptions); assertEqualVersions(version, test); assertTrue(version.isSupported()); } } public void testParseUnsupported() throws Exception { + Set unsupportedExceptions = new HashSet(); TestHgVersion unsupportedVersion = new TestHgVersion("Mercurial Distributed SCM (version 1.5.1)", 1, 5, 1); - HgVersion parsedVersion = HgVersion.parseVersion(unsupportedVersion.output); + HgVersion parsedVersion = + HgVersion.parseVersionAndExtensionInfo(unsupportedVersion.output, Collections.emptyList(), unsupportedExceptions); assertEqualVersions(parsedVersion, unsupportedVersion); assertFalse(parsedVersion.isSupported()); } + public void testParseImportExtensionsError() { + List errorLines = Arrays.asList("*** failed to import extension hgcr-gui: No module named hgcr-gui", + "*** failed to import extension hgcr-gui-qt: No module named hgcr-gui-qt"); + VcsTestUtil.assertEqualCollections(HgVersion.parseUnsupportedExtensions(errorLines), Arrays.asList("hgcr-gui", "hgcr-gui-qt")); + } + + public void testParseImportDeprecatedExtensionsError() { + List errorLines = Arrays.asList("*** failed to import extension kilnpath from" + + " C:\\Users\\Developer\\AppData\\Local\\KilnExtensions\\kilnpath.py:" + + " kilnpath is deprecated, and does not work in Mercurial 2.3 or higher." + + " Use the official schemes extension instead"); + VcsTestUtil.assertEqualCollections(HgVersion.parseUnsupportedExtensions(errorLines), Arrays.asList("kilnpath")); + } + private static void assertEqualVersions(HgVersion actual, TestHgVersion expected) throws Exception { Field field = HgVersion.class.getDeclaredField("myMajor"); field.setAccessible(true);