def __init__(self, mach_cmd): super(NodeRunner, self).__init__(mach_cmd) self.topsrcdir = mach_cmd.topsrcdir self._mach_context = mach_cmd._mach_context self.python_path = mach_cmd.virtualenv_manager.python_path from mozbuild.nodeutil import find_node_executable self.node_path = os.path.abspath(find_node_executable()[0])
def node(command_context, args): from mozbuild.nodeutil import find_node_executable # Avoid logging the command command_context.log_manager.terminal_handler.setLevel(logging.CRITICAL) node_path, _ = find_node_executable() return command_context.run_process( [node_path] + args, pass_thru=True, # Allow user to run Node interactively. ensure_exit_code=False, # Don't throw on non-zero exit code. )
def lint(paths, config, binary=None, fix=None, setup=None, **lintargs): """Run eslint.""" log = lintargs["log"] setup_helper.set_project_root(lintargs["root"]) module_path = setup_helper.get_project_root() # Valid binaries are: # - Any provided by the binary argument. # - Any pointed at by the ESLINT environmental variable. # - Those provided by |mach lint --setup|. if not binary: binary, _ = find_node_executable() if not binary: print(ESLINT_NOT_FOUND_MESSAGE) return 1 extra_args = lintargs.get("extra_args") or [] exclude_args = [] for path in config.get("exclude", []): exclude_args.extend( ["--ignore-pattern", os.path.relpath(path, lintargs["root"])]) cmd_args = ([ binary, os.path.join(module_path, "node_modules", "eslint", "bin", "eslint.js"), # This keeps ext as a single argument. "--ext", "[{}]".format(",".join(config["extensions"])), "--format", "json", "--no-error-on-unmatched-pattern", ] + extra_args + exclude_args + paths) log.debug("Command: {}".format(" ".join(cmd_args))) results = run(cmd_args, config) fixed = 0 # eslint requires that --fix be set before the --ext argument. if fix: fixed += len(results) cmd_args.insert(2, "--fix") results = run(cmd_args, config) fixed = fixed - len(results) return {"results": results, "fixed": fixed}
def check_node_executables_valid(): node_path, version = find_node_executable() if not node_path: print(NODE_NOT_FOUND_MESSAGE) return False if not version: print(NODE_MACHING_VERSION_NOT_FOUND_MESSAGE % NODE_MIN_VERSION) return False npm_path, version = find_npm_executable() if not npm_path: print(NPM_NOT_FOUND_MESSAGE) return False if not version: print(NPM_MACHING_VERSION_NOT_FOUND_MESSAGE % NPM_MIN_VERSION) return False return True
def setUp(self): if not buildconfig.substs.get("NODEJS"): buildconfig.substs['NODEJS'] = find_node_executable()[0] SCRIPT_ALLOWLIST.append(TEST_SCRIPT)
def _node_path(self): from mozbuild.nodeutil import find_node_executable node, _ = find_node_executable() return os.path.dirname(node)
def lint(paths, config, binary=None, fix=None, setup=None, **lintargs): """Run eslint.""" setup_helper.set_project_root(lintargs['root']) module_path = setup_helper.get_project_root() # Valid binaries are: # - Any provided by the binary argument. # - Any pointed at by the ESLINT environmental variable. # - Those provided by |mach lint --setup|. if not binary: binary, _ = find_node_executable() if not binary: print(ESLINT_NOT_FOUND_MESSAGE) return 1 extra_args = lintargs.get('extra_args') or [] exclude_args = [] for path in config.get('exclude', []): exclude_args.extend( ['--ignore-pattern', os.path.relpath(path, lintargs['root'])]) cmd_args = [ binary, os.path.join(module_path, "node_modules", "eslint", "bin", "eslint.js"), # Enable the HTML plugin. # We can't currently enable this in the global config file # because it has bad interactions with the SublimeText # ESLint plugin (bug 1229874). '--plugin', 'html', # This keeps ext as a single argument. '--ext', '[{}]'.format(','.join(config['extensions'])), '--format', 'json', ] + extra_args + exclude_args + paths # eslint requires that --fix be set before the --ext argument. if fix: cmd_args.insert(2, '--fix') shell = False if os.environ.get('MSYSTEM') in ('MINGW32', 'MINGW64'): # The eslint binary needs to be run from a shell with msys shell = True orig = signal.signal(signal.SIGINT, signal.SIG_IGN) proc = ProcessHandler(cmd_args, env=os.environ, stream=None, shell=shell) proc.run() signal.signal(signal.SIGINT, orig) try: proc.wait() except KeyboardInterrupt: proc.kill() return [] if not proc.output: return [] # no output means success try: jsonresult = json.loads(proc.output[0]) except ValueError: print(ESLINT_ERROR_MESSAGE.format("\n".join(proc.output))) return 1 results = [] for obj in jsonresult: errors = obj['messages'] for err in errors: err.update({ 'hint': err.get('fix'), 'level': 'error' if err['severity'] == 2 else 'warning', 'lineno': err.get('line') or 0, 'path': obj['filePath'], 'rule': err.get('ruleId'), }) results.append(result.from_config(config, **err)) return results
def node_path(): from mozbuild.nodeutil import find_node_executable node, _ = find_node_executable() return os.path.abspath(node)
def package_setup( package_root, package_name, should_update=False, should_clobber=False, no_optional=False, ): """Ensure `package_name` at `package_root` is installed. When `should_update` is true, clobber, install, and produce a new "package-lock.json" file. This populates `package_root/node_modules`. """ orig_project_root = get_project_root() orig_cwd = os.getcwd() if should_update: should_clobber = True try: set_project_root(package_root) sys.path.append(os.path.dirname(__file__)) # npm sometimes fails to respect cwd when it is run using check_call so # we manually switch folders here instead. project_root = get_project_root() os.chdir(project_root) if should_clobber: node_modules_path = os.path.join(project_root, "node_modules") print("Clobbering %s..." % node_modules_path) if sys.platform.startswith("win") and have_winrm(): process = subprocess.Popen(["winrm", "-rf", node_modules_path]) process.wait() else: mozfileremove(node_modules_path) npm_path, _ = find_npm_executable() if not npm_path: return 1 node_path, _ = find_node_executable() if not node_path: return 1 extra_parameters = ["--loglevel=error"] if no_optional: extra_parameters.append("--no-optional") package_lock_json_path = os.path.join(get_project_root(), "package-lock.json") if should_update: cmd = [npm_path, "install"] mozfileremove(package_lock_json_path) else: cmd = [npm_path, "ci"] # On non-Windows, ensure npm is called via node, as node may not be in the # path. if platform.system() != "Windows": cmd.insert(0, node_path) # Ensure that bare `node` and `npm` in scripts, including post-install scripts, finds the # binary we're invoking with. Without this, it's easy for compiled extensions to get # mismatched versions of the Node.js extension API. extra_parameters.append("--scripts-prepend-node-path") cmd.extend(extra_parameters) print('Installing %s for mach using "%s"...' % (package_name, " ".join(cmd))) result = call_process(package_name, cmd) if not result: return 1 bin_path = os.path.join(get_project_root(), "node_modules", ".bin", package_name) print("\n%s installed successfully!" % package_name) print("\nNOTE: Your local %s binary is at %s\n" % (package_name, bin_path)) finally: set_project_root(orig_project_root) os.chdir(orig_cwd)
def eslint_setup(should_clobber=False): """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. """ orig_cwd = os.getcwd() sys.path.append(os.path.dirname(__file__)) # npm sometimes fails to respect cwd when it is run using check_call so # we manually switch folders here instead. project_root = get_project_root() os.chdir(project_root) if should_clobber: node_modules_path = os.path.join(project_root, "node_modules") print("Clobbering node_modules...") if sys.platform.startswith('win') and have_winrm(): process = subprocess.Popen(['winrm', '-rf', node_modules_path]) process.wait() else: mozfileremove(node_modules_path) npm_path, version = find_npm_executable() if not npm_path: return 1 node_path, _ = find_node_executable() if not node_path: return 1 extra_parameters = ["--loglevel=error"] package_lock_json_path = os.path.join(get_project_root(), "package-lock.json") package_lock_json_tmp_path = os.path.join(tempfile.gettempdir(), "package-lock.json.tmp") # If we have an npm version newer than 5.8.0, just use 'ci', as that's much # simpler and does exactly what we want. npm_is_older_version = version < StrictVersion("5.8.0").version if npm_is_older_version: cmd = [node_path, npm_path, "install"] shutil.copy2(package_lock_json_path, package_lock_json_tmp_path) else: cmd = [node_path, npm_path, "ci"] cmd.extend(extra_parameters) print("Installing eslint for mach using \"%s\"..." % (" ".join(cmd))) result = call_process("eslint", cmd) if npm_is_older_version: shutil.move(package_lock_json_tmp_path, package_lock_json_path) if not result: return 1 eslint_path = os.path.join(get_project_root(), "node_modules", ".bin", "eslint") print("\nESLint and approved plugins installed successfully!") print("\nNOTE: Your local eslint binary is at %s\n" % eslint_path) os.chdir(orig_cwd)
def package_setup(package_root, package_name, should_clobber=False, no_optional=False): """Ensure `package_name` at `package_root` is installed. This populates `package_root/node_modules`. """ orig_project_root = get_project_root() orig_cwd = os.getcwd() try: set_project_root(package_root) sys.path.append(os.path.dirname(__file__)) # npm sometimes fails to respect cwd when it is run using check_call so # we manually switch folders here instead. project_root = get_project_root() os.chdir(project_root) if should_clobber: node_modules_path = os.path.join(project_root, "node_modules") print("Clobbering %s..." % node_modules_path) if sys.platform.startswith('win') and have_winrm(): process = subprocess.Popen(['winrm', '-rf', node_modules_path]) process.wait() else: mozfileremove(node_modules_path) npm_path, version = find_npm_executable() if not npm_path: return 1 node_path, _ = find_node_executable() if not node_path: return 1 extra_parameters = ["--loglevel=error"] if no_optional: extra_parameters.append('--no-optional') package_lock_json_path = os.path.join(get_project_root(), "package-lock.json") package_lock_json_tmp_path = os.path.join(tempfile.gettempdir(), "package-lock.json.tmp") # If we have an npm version newer than 5.8.0, just use 'ci', as that's much # simpler and does exactly what we want. npm_is_older_version = version < StrictVersion("5.8.0").version if npm_is_older_version: cmd = [npm_path, "install"] shutil.copy2(package_lock_json_path, package_lock_json_tmp_path) else: cmd = [npm_path, "ci"] # On non-Windows, ensure npm is called via node, as node may not be in the # path. if platform.system() != "Windows": cmd.insert(0, node_path) cmd.extend(extra_parameters) # Ensure that bare `node` and `npm` in scripts, including post-install scripts, finds the # binary we're invoking with. Without this, it's easy for compiled extensions to get # mismatched versions of the Node.js extension API. path = os.environ.get('PATH', '').split(os.pathsep) node_dir = os.path.dirname(node_path) if node_dir not in path: path = [node_dir] + path print("Installing %s for mach using \"%s\"..." % (package_name, " ".join(cmd))) result = call_process(package_name, cmd, append_env={'PATH': os.pathsep.join(path)}) if npm_is_older_version: shutil.move(package_lock_json_tmp_path, package_lock_json_path) if not result: return 1 bin_path = os.path.join(get_project_root(), "node_modules", ".bin", package_name) print("\n%s installed successfully!" % package_name) print("\nNOTE: Your local %s binary is at %s\n" % (package_name, bin_path)) finally: set_project_root(orig_project_root) os.chdir(orig_cwd)
def lint(paths, config, binary=None, fix=None, setup=None, **lintargs): """Run eslint.""" log = lintargs["log"] setup_helper.set_project_root(lintargs["root"]) module_path = setup_helper.get_project_root() # Valid binaries are: # - Any provided by the binary argument. # - Any pointed at by the ESLINT environmental variable. # - Those provided by |mach lint --setup|. if not binary: binary, _ = find_node_executable() if not binary: print(ESLINT_NOT_FOUND_MESSAGE) return 1 extra_args = lintargs.get("extra_args") or [] exclude_args = [] for path in config.get("exclude", []): exclude_args.extend( ["--ignore-pattern", os.path.relpath(path, lintargs["root"])]) cmd_args = ([ binary, os.path.join(module_path, "node_modules", "eslint", "bin", "eslint.js"), # This keeps ext as a single argument. "--ext", "[{}]".format(",".join(config["extensions"])), "--format", "json", "--no-error-on-unmatched-pattern", ] + extra_args + exclude_args + paths) log.debug("Command: {}".format(" ".join(cmd_args))) # eslint requires that --fix be set before the --ext argument. if fix: cmd_args.insert(2, "--fix") shell = False if os.environ.get("MSYSTEM") in ("MINGW32", "MINGW64"): # The eslint binary needs to be run from a shell with msys shell = True encoding = "utf-8" orig = signal.signal(signal.SIGINT, signal.SIG_IGN) proc = subprocess.Popen(cmd_args, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE) signal.signal(signal.SIGINT, orig) try: output, errors = proc.communicate() except KeyboardInterrupt: proc.kill() return [] if errors: errors = errors.decode(encoding, "replace") print(ESLINT_ERROR_MESSAGE.format(errors)) if proc.returncode >= 2: return 1 if not output: return [] # no output means success output = output.decode(encoding, "replace") try: jsonresult = json.loads(output) except ValueError: print(ESLINT_ERROR_MESSAGE.format(output)) return 1 results = [] for obj in jsonresult: errors = obj["messages"] for err in errors: err.update({ "hint": err.get("fix"), "level": "error" if err["severity"] == 2 else "warning", "lineno": err.get("line") or 0, "path": obj["filePath"], "rule": err.get("ruleId"), }) results.append(result.from_config(config, **err)) return results
def lint(paths, config, binary=None, fix=None, setup=None, **lintargs): """Run eslint.""" log = lintargs['log'] setup_helper.set_project_root(lintargs['root']) module_path = setup_helper.get_project_root() # Valid binaries are: # - Any provided by the binary argument. # - Any pointed at by the ESLINT environmental variable. # - Those provided by |mach lint --setup|. if not binary: binary, _ = find_node_executable() if not binary: print(ESLINT_NOT_FOUND_MESSAGE) return 1 extra_args = lintargs.get('extra_args') or [] exclude_args = [] for path in config.get('exclude', []): exclude_args.extend( ['--ignore-pattern', os.path.relpath(path, lintargs['root'])]) cmd_args = [ binary, os.path.join(module_path, "node_modules", "eslint", "bin", "eslint.js"), # This keeps ext as a single argument. '--ext', '[{}]'.format(','.join(config['extensions'])), '--format', 'json', '--no-error-on-unmatched-pattern', ] + extra_args + exclude_args + paths log.debug("Command: {}".format(' '.join(cmd_args))) # eslint requires that --fix be set before the --ext argument. if fix: cmd_args.insert(2, '--fix') shell = False if os.environ.get('MSYSTEM') in ('MINGW32', 'MINGW64'): # The eslint binary needs to be run from a shell with msys shell = True encoding = 'utf-8' orig = signal.signal(signal.SIGINT, signal.SIG_IGN) proc = subprocess.Popen(cmd_args, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE) signal.signal(signal.SIGINT, orig) try: output, errors = proc.communicate() except KeyboardInterrupt: proc.kill() return [] if errors: errors = errors.decode(encoding, "replace") print(ESLINT_ERROR_MESSAGE.format(errors)) if proc.returncode >= 2: return 1 if not output: return [] # no output means success output = output.decode(encoding, "replace") try: jsonresult = json.loads(output) except ValueError: print(ESLINT_ERROR_MESSAGE.format(output)) return 1 results = [] for obj in jsonresult: errors = obj['messages'] for err in errors: err.update({ 'hint': err.get('fix'), 'level': 'error' if err['severity'] == 2 else 'warning', 'lineno': err.get('line') or 0, 'path': obj['filePath'], 'rule': err.get('ruleId'), }) results.append(result.from_config(config, **err)) return results