def install_package(name, version, dest_directory, npm_directory): if is_recognized_github_uri(version): # In the GitHub URI case, the files are already unzipped. package_dir = find_dir_for_github_uri(version, npm_directory) shutil.copytree(package_dir, dest_directory) else: available_versions = find_available_versions(name, npm_directory) semver_range = version if version != 'latest' else '*' matching_versions = find_version_in_range(available_versions, semver_range) if not matching_versions: raise Exception('No package found for %s@%s' % (name, version)) # In the common case, package_dir contains two entries: # - package.tgz # - package/package.json package_dir = os.path.join(npm_directory, name, matching_versions[-1]) # The package.tgz has one root entry, package/, which contains all of the package contents. # # In practice, I have seen one exception, which is [email protected] (and other versions of defs) # where the root folder is named "defs" instead of "package". tgz = os.path.join(package_dir, 'package.tgz') temp_dir = tempfile.mkdtemp() subprocess.check_call(['tar', '-xzf', tgz], cwd=temp_dir) tar_folder = os.listdir(temp_dir)[0] shutil.move(os.path.join(temp_dir, tar_folder), dest_directory) shutil.rmtree(temp_dir)
def _verify_node(): '''Ensures that Node v0.12.0 or later is on the user's $PATH.''' # As noted in _install_apm_and_npm_os_x(), ultimately that function should be responsible for # doing this work. # First, check for the presence of node. Make sure it is at least v0.12.0. node_executable = platform_checker.get_node_executable() if _is_executable_on_path(node_executable): node_version = fs.cross_platform_check_output([node_executable, '--version']).rstrip() if semver.find_version_in_range([node_version], '>=0.12.0'): return raise Exception('Must install Node v0.12.0 or later. Not found in %s' % os.environ['PATH'])
def has_ancestor_with_dep(name, version, node_modules): candidate_dir = os.path.join(node_modules, name) if os.path.isdir(candidate_dir): package_json = os.path.join(candidate_dir, 'package.json') discovered_version = json_load(package_json)['version'] if find_version_in_range([discovered_version], version): return True # Look upwards to the next node_modules, if present. parent_node_modules = os.path.normpath(os.path.join(node_modules, '../../')) if os.path.basename(parent_node_modules) == 'node_modules': return has_ancestor_with_dep(name, version, parent_node_modules) else: return False
def write_dependencies(self, output_dir): package_to_version_set = {} for config in self._package_manager.get_configs(): src_path = config['packageRootAbsolutePath'] package_json = os.path.join(src_path, 'package.json') self._process_package_json( package_json, package_to_version_set, include_dev_dependencies=config['includeDevDependencies']) # Write deps based on package_to_version_set. # Leveraging semver from npm makes this fairly straightforward. for package, versions in package_to_version_set.items(): package_dir = os.path.join(self._dot_npm_directory, package) if not os.path.isdir(package_dir): raise Exception( 'ERROR: Could not find directory for package %s at %s' % (package, package_dir)) available_versions = os.listdir(package_dir) for version in versions: if is_recognized_github_uri(version): add_github_uri_to_output_dir(version, output_dir, package) continue semver_range = version if version != 'latest' else '*' matching_versions = find_version_in_range( available_versions, semver_range) if not matching_versions: # Note that there are other valid version formats, such as local dependencies # and URL formats that we have not added logic for # (https://docs.npmjs.com/files/package.json#git-urls-as-dependencies). # Currently, we can get away with this because these formats are not used by our # transitive dependencies, so we may have to expand what we support in the # future. raise Exception('No package found for %s@%s' % (package, version)) else: # By default, we pick the newest version available. desired_version = matching_versions[-1] if version == 'latest': logging.warn( 'Warning: choosing "latest" among what is locally available for %s: (%s).', package, desired_version) src_dir = os.path.join(package_dir, desired_version) dest_dir = os.path.join(output_dir, package, desired_version) if not os.path.isdir(dest_dir): mkdirs(os.path.dirname(dest_dir)) shutil.copytree(src_dir, dest_dir)
def _verify_node(): '''Ensures that Node v0.12.0 or later is on the user's $PATH.''' # As noted in _install_apm_and_npm_os_x(), ultimately that function should be responsible for # doing this work. # First, check for the presence of node. Make sure it is at least v0.12.0. node_executable = platform_checker.get_node_executable() if _is_executable_on_path(node_executable): node_version = fs.cross_platform_check_output( [node_executable, '--version']).rstrip() if semver.find_version_in_range([node_version], '>=0.12.0'): return raise Exception('Must install Node v0.12.0 or later. Not found in %s' % os.environ['PATH'])
def write_dependencies(self, output_dir): package_to_version_set = {} for config in self._package_manager.get_configs(): if config.get('excludeFromRelease', False): continue src_path = config['packageRootAbsolutePath'] package_json = os.path.join(src_path, 'package.json') self._process_package_json(package_json, package_to_version_set, include_dev_dependencies=config['includeDevDependencies']) # Write deps based on package_to_version_set. # Leveraging semver from npm makes this fairly straightforward. for package, versions in package_to_version_set.items(): package_dir = os.path.join(self._dot_npm_directory, package) if not os.path.isdir(package_dir): raise Exception('ERROR: Could not find directory for package %s at %s' % (package, package_dir)) available_versions = os.listdir(package_dir) for version in versions: if is_recognized_github_uri(version): add_github_uri_to_output_dir(version, output_dir, package) continue semver_range = version if version != 'latest' else '*' matching_versions = find_version_in_range(available_versions, semver_range) if not matching_versions: # Note that there are other valid version formats, such as local dependencies # and URL formats that we have not added logic for # (https://docs.npmjs.com/files/package.json#git-urls-as-dependencies). # Currently, we can get away with this because these formats are not used by our # transitive dependencies, so we may have to expand what we support in the # future. raise Exception('No package found for %s@%s' % (package, version)) else: # By default, we pick the newest version available. desired_version = matching_versions[-1] if version == 'latest': logging.warn( 'Warning: choosing "latest" among what is locally available for %s: (%s).', package, desired_version) src_dir = os.path.join(package_dir, desired_version) dest_dir = os.path.join(output_dir, package, desired_version) if not os.path.isdir(dest_dir): mkdirs(os.path.dirname(dest_dir)) shutil.copytree(src_dir, dest_dir)
def is_compatible(version, expected_range): matches = find_version_in_range([version], expected_range) return matches and len(matches)