nodejs-packaging/nodejs.prov
Stephen Gallagher 2e5760403e Fix incorrect flag for fedpkg scratch-build
bundler: Handle deprecated license metadata

Adds support for archaic forms of the license metadata in
package.json where the license field is an object rather than a
string.

Also removes the need to post-process the 'null' entries.

Resolves: rhbz#1920206

Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>

bundler: Add warning for deps missing license tag

Resolves: rhbz#1920223

Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>

Spec: fix line-length for rpmlint

Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>

Update to 2021.06

bundler: Handle archaic license metadata
bundler: Warn about bundled dependencies with no license metadata

Actually use the value of OUTPUT_DIR when copying bundled sources in nodejs-packaging-bundler

In nodejs-packaging-bundler, use %{_sourcedir} for output

Fixes RHBZ#1974709

Fix hard-coded output directory in the bundler

Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>

- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild

Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>

fix typos

nodejs.prov: find namespaced bundled dependencies

The previous behaviour assumed that in a bundled package path,
there is always `node_modules` directory on each other spot – i.e.:

npm/node_modules/<dep1>/node_modules/<subdep>
    ^                   ^

With namespaced bundled packages, this is no longer necessary the truth:

npm/node_modules/@nmcli/<dep1>/node_modules/…
    ^                   ! – expected node_modules

NPM bundler: also find namespaced bundled dependencies

Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>

Related: #1990096
Related RHELPLAN-119396
2022-06-28 17:01:06 +02:00

122 lines
4.4 KiB
Python
Executable File

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright 2012 T.C. Hollingsworth <tchollingsworth@gmail.com>
# Copyright 2017 Tomas Tomecek <ttomecek@redhat.com>
# Copyright 2019 Jan Staněk <jstanek@redhat.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
"""Automatic provides generator for Node.js libraries.
Metadata taken from package.json. See `man npm-json` for details.
"""
from __future__ import print_function, with_statement
import json
import os
import sys
from itertools import chain, groupby
DEPENDENCY_TEMPLATE = "npm(%(name)s) = %(version)s"
BUNDLED_TEMPLATE = "bundled(nodejs-%(name)s) = %(version)s"
NODE_MODULES = {"node_modules", "node_modules_prod"}
class PrivatePackage(RuntimeError):
"""Private package metadata that should not be listed."""
#: Something is wrong with the ``package.json`` file
_INVALID_METADATA_FILE = (IOError, PrivatePackage, KeyError)
def format_metadata(metadata, bundled=False):
"""Format ``package.json``-like metadata into RPM dependency.
Arguments:
metadata (dict): Package metadata, presumably read from ``package.json``.
bundled (bool): Should the bundled dependency format be used?
Returns:
str: RPM dependency (i.e. ``npm(example) = 1.0.0``)
Raises:
KeyError: Expected key (i.e. ``name``, ``version``) missing in metadata.
PrivatePackage: The metadata indicate private (unlisted) package.
"""
# Skip private packages
if metadata.get("private", False):
raise PrivatePackage(metadata)
template = BUNDLED_TEMPLATE if bundled else DEPENDENCY_TEMPLATE
return template % metadata
def generate_dependencies(module_path, module_dir_set=NODE_MODULES):
"""Generate RPM dependency for a module and all it's dependencies.
Arguments:
module_path (str): Path to a module directory or it's ``package.json``
module_dir_set (set): Base names of directories to look into
for bundled dependencies.
Yields:
str: RPM dependency for the module and each of it's (public) bundled dependencies.
Raises:
ValueError: module_path is not valid module or ``package.json`` file
"""
# Determine paths to root module directory and package.json
if os.path.isdir(module_path):
root_dir = module_path
elif os.path.basename(module_path) == "package.json":
root_dir = os.path.dirname(module_path)
else: # Invalid metadata path
raise ValueError("Invalid module path '%s'" % module_path)
for dir_path, subdir_list, file_list in os.walk(root_dir):
# We are only interested in directories that contain package.json
if "package.json" not in file_list:
continue
# Read and format metadata
metadata_path = os.path.join(dir_path, "package.json")
bundled = dir_path != root_dir
try:
with open(metadata_path, mode="r") as metadata_file:
metadata = json.load(metadata_file)
yield format_metadata(metadata, bundled=bundled)
except _INVALID_METADATA_FILE:
pass # Ignore
# Only visit subdirectories in module_dir_set
subdir_list[:] = list(module_dir_set & set(subdir_list))
if __name__ == "__main__":
module_paths = (path.strip() for path in sys.stdin)
provides = chain.from_iterable(generate_dependencies(m) for m in module_paths)
# sort|uniq
for provide, __ in groupby(sorted(provides)):
print(provide)