--- a/python/mach_commands.py
+++ b/python/mach_commands.py
@@ -7,16 +7,17 @@ from __future__ import absolute_import,
import argparse
import logging
import mozpack.path as mozpath
import os
import platform
import subprocess
import sys
import which
+from distutils.version import LooseVersion
from mozbuild.base import (
MachCommandBase,
)
from mach.decorators import (
CommandArgument,
CommandProvider,
@@ -29,17 +30,17 @@ environment variable, and then at your p
with
mach eslint --setup
and try again.
'''.strip()
NODE_NOT_FOUND_MESSAGE = '''
-nodejs is either not installed or is installed to a non-standard path.
+nodejs v4.2.3 is either not installed or is installed to a non-standard path.
Please install nodejs from https://nodejs.org and try again.
Valid installation paths:
'''.strip()
NPM_NOT_FOUND_MESSAGE = '''
Node Package Manager (npm) is either not installed or installed to a
non-standard path. Please install npm from https://nodejs.org (it comes as an
@@ -156,16 +157,21 @@ class MachCommands(MachCommandBase):
@CommandArgument('-e', '--ext', default='[.js,.jsm,.jsx,.xml,.html]',
help='Filename extensions to lint, default: "[.js,.jsm,.jsx,.xml,.html]".')
@CommandArgument('-b', '--binary', default=None,
help='Path to eslint binary.')
@CommandArgument('args', nargs=argparse.REMAINDER) # Passed through to eslint.
def eslint(self, setup, ext=None, binary=None, args=None):
'''Run eslint.'''
+ # eslint requires at least node 4.2.3
+ nodePath = self.getNodeOrNpmPath("node", LooseVersion("4.2.3"))
+ if not nodePath:
+ return 1
+
if setup:
return self.eslint_setup()
if not binary:
binary = os.environ.get('ESLINT', None)
if not binary:
try:
binary = which.which('eslint')
@@ -204,21 +210,16 @@ class MachCommands(MachCommandBase):
"""Ensure eslint is optimally configured.
This command will inspect your eslint configuration and
guide you through an interactive wizard helping you configure
eslint for optimal use on Mozilla projects.
"""
sys.path.append(os.path.dirname(__file__))
- # At the very least we need node installed.
- nodePath = self.getNodeOrNpmPath("node")
- if not nodePath:
- return 1
-
npmPath = self.getNodeOrNpmPath("npm")
if not npmPath:
return 1
# Install eslint.
success = self.callProcess("eslint",
[npmPath, "install", "eslint", "-g"])
if not success:
@@ -270,32 +271,34 @@ class MachCommands(MachCommandBase):
return list({
"%s\\nodejs" % os.environ.get("SystemDrive"),
os.path.join(os.environ.get("ProgramFiles"), "nodejs"),
os.path.join(os.environ.get("PROGRAMW6432"), "nodejs"),
os.path.join(os.environ.get("PROGRAMFILES"), "nodejs")
})
- def getNodeOrNpmPath(self, filename):
+ def getNodeOrNpmPath(self, filename, minversion=None):
"""
Return the nodejs or npm path.
"""
if platform.system() == "Windows":
for ext in [".cmd", ".exe", ""]:
try:
nodeOrNpmPath = which.which(filename + ext,
path=self.getPossibleNodePathsWin())
- if self.is_valid(nodeOrNpmPath):
+ if self.is_valid(nodeOrNpmPath, minversion):
return nodeOrNpmPath
except which.WhichError:
pass
else:
try:
- return which.which(filename)
+ nodeOrNpmPath = which.which(filename)
+ if self.is_valid(nodeOrNpmPath, minversion):
+ return nodeOrNpmPath
except which.WhichError:
pass
if filename == "node":
print(NODE_NOT_FOUND_MESSAGE)
elif filename == "npm":
print(NPM_NOT_FOUND_MESSAGE)
@@ -306,15 +309,19 @@ class MachCommands(MachCommandBase):
print(" - %s" % p)
elif platform.system() == "Darwin":
print(" - /usr/local/bin/node")
elif platform.system() == "Linux":
print(" - /usr/bin/nodejs")
return None
- def is_valid(self, path):
+ def is_valid(self, path, minversion = None):
try:
- with open(os.devnull, "w") as fnull:
- subprocess.check_call([path, "--version"], stdout=fnull)
- return True
+ version_str = subprocess.check_output([path, "--version"],
+ stderr=subprocess.STDOUT)
+ if minversion:
+ # nodejs prefixes its version strings with "v"
+ version = LooseVersion(version_str.lstrip('v'))
+ return version >= minversion
+ return True
except (subprocess.CalledProcessError, WindowsError):
return False