Skip to content

Commit 395091c

Browse files
authored
Merge pull request #3943 from aboutcode-org/3931-update-yarn-lock-parser
Update yarn lock parser #3931
2 parents 5d50052 + e0ff11e commit 395091c

File tree

10 files changed

+596
-13
lines changed

10 files changed

+596
-13
lines changed

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,8 @@ Package detection:
886886

887887
- For Pypi packages, python_requires is treated as a package dependency.
888888

889+
- Update JavaScript package handlers to handle aliases in npm and yarn manifests.
890+
889891

890892
License Clarity Scoring Update:
891893
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/packagedcode/npm.py

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def assemble(cls, package_data, resource, codebase, package_adder):
207207

208208
@classmethod
209209
def yield_npm_dependencies_and_resources(cls, package_resource, package_data, package_uid, codebase, package_adder):
210-
210+
211211
# in all cases yield possible dependencies
212212
yield from yield_dependencies_from_package_data(package_data, package_resource.path, package_uid)
213213

@@ -276,7 +276,9 @@ def create_packages_from_workspaces(
276276
if npm_res.for_packages:
277277
continue
278278

279-
npm_res.for_packages = workspace_package_uids
279+
for package_uid in workspace_package_uids:
280+
package_adder(package_uid, npm_res, codebase)
281+
280282
npm_res.save(codebase)
281283

282284
@classmethod
@@ -374,6 +376,18 @@ def update_dependencies_by_purl(
374376
if '_' in metadata:
375377
requirement, _extra = metadata.split('_')
376378

379+
if ':' in requirement and '@' in requirement:
380+
# dependencies with requirements like this are aliases and should be reported
381+
aliased_package, _, constraint = requirement.rpartition('@')
382+
_, _, aliased_package_name = aliased_package.rpartition(':')
383+
sdns, _ , sdname = aliased_package_name.rpartition('/')
384+
dep_purl = PackageURL(
385+
type=cls.default_package_type,
386+
namespace=sdns,
387+
name=sdname
388+
).to_string()
389+
requirement = constraint
390+
377391
dep_package = models.DependentPackage(
378392
purl=dep_purl,
379393
scope=scope,
@@ -424,7 +438,7 @@ def get_workspace_members(cls, workspaces, codebase, workspace_root_path):
424438
workspace_members.append(resource)
425439

426440
# Case 3: This is a complex glob pattern, we are doing a full codebase walk
427-
# and glob matching each resource
441+
# and glob matching each resource
428442
else:
429443
for resource in workspace_root_path:
430444
if NpmPackageJsonHandler.is_datafile(resource.location) and fnmatch.fnmatch(
@@ -469,7 +483,7 @@ def update_workspace_members(cls, workspace_members, codebase):
469483
workspace_package_versions_by_base_purl[base_purl] = version
470484

471485
# Update workspace member package information from
472-
# workspace level data
486+
# workspace level data
473487
for base_purl, dependency in workspace_dependencies_by_base_purl.items():
474488
extracted_requirement = dependency.get('extracted_requirement')
475489
if 'workspace' in extracted_requirement:
@@ -1011,6 +1025,13 @@ def parse(cls, location, package_only=False):
10111025
if '"' in ns_name:
10121026
ns_name = ns_name.replace('"', '')
10131027
ns, _ , name = ns_name.rpartition('/')
1028+
1029+
if ':' in constraint and '@' in constraint:
1030+
# dependencies with requirements like this are aliases and should be reported
1031+
aliased_package, _, constraint = constraint.rpartition('@')
1032+
_, _, aliased_package_name = aliased_package.rpartition(':')
1033+
ns, _ , name = aliased_package_name.rpartition('/')
1034+
10141035
sub_dependencies.append((ns, name, constraint,))
10151036

10161037
elif line.startswith(' ' * 2):
@@ -1112,7 +1133,7 @@ def parse(cls, location, package_only=False):
11121133
resolved_package=resolved_package_data.to_dict(),
11131134
)
11141135

1115-
if not dep_purl in dependencies_by_purl:
1136+
if not dep_purl in dependencies_by_purl:
11161137
dependencies_by_purl[dep_purl] = dep.to_dict()
11171138
else:
11181139
# FIXME: We have duplicate dependencies because of aliases
@@ -1176,7 +1197,7 @@ def parse(cls, location, package_only=False):
11761197
_, name_version = sections
11771198
elif len(sections) == 3:
11781199
_, namespace, name_version = sections
1179-
1200+
11801201
name, version = name_version.split("@")
11811202
elif major_v == "5" or is_shrinkwrap:
11821203
if len(sections) == 3:
@@ -1264,7 +1285,7 @@ def parse(cls, location, package_only=False):
12641285
for key in extra_data_fields:
12651286
value = data.get(key, None)
12661287
if value is not None:
1267-
extra_data_deps[key] = value
1288+
extra_data_deps[key] = value
12681289

12691290
dependency_data = models.DependentPackage(
12701291
purl=purl,
@@ -1762,14 +1783,21 @@ def deps_mapper(deps, package, field_name, is_direct=True):
17621783
deps_by_name[npm_name] = d
17631784

17641785
for fqname, requirement in deps.items():
1765-
# Handle cases in ``resolutions`` with ``**``
1786+
# Handle cases in ``resolutions`` with ``**``
17661787
# "resolutions": {
17671788
# "**/@typescript-eslint/eslint-plugin": "^4.1.1",
17681789
if fqname.startswith('**'):
17691790
fqname = fqname.replace('**', '')
17701791
ns, name = split_scoped_package_name(fqname)
17711792
if not name:
17721793
continue
1794+
1795+
if ':' in requirement and '@' in requirement:
1796+
# dependencies with requirements like this are aliases and should be reported
1797+
aliased_package, _, requirement = requirement.rpartition('@')
1798+
_, _, aliased_package_name = aliased_package.rpartition(':')
1799+
ns, _ , name = aliased_package_name.rpartition('/')
1800+
17731801
purl = PackageURL(type='npm', namespace=ns, name=name).to_string()
17741802

17751803
# optionalDependencies override the dependencies with the same name

tests/packagedcode/data/npm/alias/package-lock.json

Lines changed: 57 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/packagedcode/data/npm/alias/package-lock.json.expected

Lines changed: 149 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)