Remove nodeenv dependency

This commit is contained in:
Max R 2021-03-18 13:23:07 -04:00
parent d6ec6cf719
commit c85f08bcb5
3 changed files with 113 additions and 10 deletions

View file

@ -13,6 +13,7 @@ from pre_commit.envcontext import UNSET
from pre_commit.envcontext import Var from pre_commit.envcontext import Var
from pre_commit.hook import Hook from pre_commit.hook import Hook
from pre_commit.languages import helpers from pre_commit.languages import helpers
from pre_commit.languages.node_env import install_node
from pre_commit.languages.python import bin_dir from pre_commit.languages.python import bin_dir
from pre_commit.prefix import Prefix from pre_commit.prefix import Prefix
from pre_commit.util import clean_path_on_failure from pre_commit.util import clean_path_on_failure
@ -89,27 +90,22 @@ def install_environment(
if sys.platform == 'win32': # pragma: no cover if sys.platform == 'win32': # pragma: no cover
envdir = fr'\\?\{os.path.normpath(envdir)}' envdir = fr'\\?\{os.path.normpath(envdir)}'
with clean_path_on_failure(envdir): with clean_path_on_failure(envdir):
cmd = [ npm = install_node(envdir, version)
sys.executable, '-mnodeenv', '--prebuilt', '--clean-src', envdir,
]
if version != C.DEFAULT:
cmd.extend(['-n', version])
cmd_output_b(*cmd)
with in_env(prefix, version): with in_env(prefix, version):
# https://npm.community/t/npm-install-g-git-vs-git-clone-cd-npm-install-g/5449 # https://npm.community/t/npm-install-g-git-vs-git-clone-cd-npm-install-g/5449
# install as if we installed from git # install as if we installed from git
local_install_cmd = ( local_install_cmd = (
'npm', 'install', '--dev', '--prod', npm, 'install', '--dev', '--prod',
'--ignore-prepublish', '--no-progress', '--no-save', '--ignore-prepublish', '--no-progress', '--no-save',
) )
helpers.run_setup_cmd(prefix, local_install_cmd) helpers.run_setup_cmd(prefix, local_install_cmd)
_, pkg, _ = cmd_output('npm', 'pack', cwd=prefix.prefix_dir) _, pkg, _ = cmd_output(npm, 'pack', cwd=prefix.prefix_dir)
pkg = prefix.path(pkg.strip()) pkg = prefix.path(pkg.strip())
install = ('npm', 'install', '-g', pkg, *additional_dependencies) install = (npm, 'install', '-g', pkg, *additional_dependencies)
helpers.run_setup_cmd(prefix, install) helpers.run_setup_cmd(prefix, install)
# clean these up after installation # clean these up after installation

View file

@ -0,0 +1,108 @@
import io
import os
import platform
import re
import sys
import sysconfig
from tarfile import TarFile
from tarfile import TarInfo
from typing import Generator
from urllib.parse import urljoin
from urllib.request import urlopen
from zipfile import ZipFile
import pre_commit.constants as C
ARCHITECTURES = {
'x86': 'x86', # Windows Vista 32
'i686': 'x86',
'x86_64': 'x64', # Linux Ubuntu 64
'amd64': 'x64', # FreeBSD 64bits
'AMD64': 'x64', # Windows Server 2012 R2 (x64)
'armv6l': 'armv6l', # arm
'armv7l': 'armv7l',
'armv8l': 'armv7l',
'aarch64': 'arm64',
'arm64': 'arm64',
'arm64/v8': 'arm64',
'armv8': 'arm64',
'armv8.4': 'arm64',
'ppc64le': 'ppc64le', # Power PC
's390x': 's390x', # IBM S390x
}
NIX_NODE_SUBDIRS = re.compile(r'node[^/]+/(bin|lib|include|share)')
WINDOWS_NODE_SUBDIRS = re.compile(r'node[^/]+(np|node)')
def install_node(envdir: str, language_version: str) -> str:
windows = sys.platform in ('cygwin', 'win32')
if sysconfig.get_config_var('HOST_GNU_TYPE') == 'x86_64-pc-linux-musl':
domain = 'https://unofficial-builds.nodejs.org'
suffix = 'linux-x64-musl.tar.gz'
else:
domain = 'https://nodejs.org'
arch = ARCHITECTURES[platform.machine()]
if windows:
suffix = f'win-{arch}.zip'
else:
suffix = f'{platform.system().lower()}-{arch}.tar.gz'
version = _node_version(domain, language_version)
archive_name = f'node-{version}-{suffix}'
with urlopen(
urljoin(domain, f'download/release/{version}/{archive_name}'),
) as release:
compressed = io.BytesIO(release.read())
# TODO should i just extractall + rm the extra bits instead of partially
# extracting & renaming?
if windows:
# TODO this doesn't quite work
def renamed_members(z: ZipFile) -> Generator[str, None, None]:
prefix_len = len(f'{archive_name}/')
for m in z.filelist:
if WINDOWS_NODE_SUBDIRS.match(m.filename):
m.filename = m.filename[prefix_len:]
yield m.filename
with ZipFile(compressed) as z:
z.extractall(envdir, renamed_members(z))
raise NotImplementedError('TODO')
else:
def rename_members_tf(tf: TarFile) -> Generator[TarInfo, None, None]:
prefix_len = len(f'{archive_name}/')
for m in tf.getmembers():
if NIX_NODE_SUBDIRS.match(m.name):
m.path = m.path[prefix_len:]
yield m
with TarFile.open(fileobj=compressed) as tf:
tf.extractall(envdir, rename_members_tf(tf)) # type: ignore
for file in ('npm', 'npx', 'node'):
path = os.path.join(envdir, 'bin', file)
os.chmod(path, os.stat(path).st_mode | 0o111)
os.symlink('node', os.path.join(envdir, 'bin', 'nodejs'))
return os.path.join(envdir, 'bin', 'npm')
def _node_version(domain: str, language_version: str) -> str:
"""Looks up the node.js version based on the configured
version (uses the latest by default)"""
if language_version == C.DEFAULT:
# grab latest
with urlopen(urljoin(domain, 'download/release/index.tab')) as index:
_ = next(index) # header
version = next(index).split()[0].decode()
else:
version = f'v{language_version.replace("v", "")}'
return version

View file

@ -25,7 +25,6 @@ packages = find:
install_requires = install_requires =
cfgv>=2.0.0 cfgv>=2.0.0
identify>=1.0.0 identify>=1.0.0
nodeenv>=0.11.1
pyyaml>=5.1 pyyaml>=5.1
toml toml
virtualenv>=20.0.8 virtualenv>=20.0.8