Skip to content

Commit

Permalink
Update cocoapods podfile.lock parser #1279
Browse files Browse the repository at this point in the history
Reference: aboutcode-org/scancode.io#1279
Signed-off-by: Ayan Sinha Mahapatra <[email protected]>
  • Loading branch information
AyanSinhaMahapatra committed Jun 24, 2024
1 parent c326a0b commit b42a49d
Show file tree
Hide file tree
Showing 7 changed files with 3,212 additions and 101 deletions.
136 changes: 129 additions & 7 deletions src/packagedcode/cocoapods.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

from packagedcode import models
from packagedcode import spec
from packagedcode import utils
from packagedcode.utils import get_base_purl
from packagedcode.utils import build_description

"""
Handle cocoapods packages manifests for macOS and iOS
Expand Down Expand Up @@ -232,7 +233,7 @@ def parse(cls, location, package_only=False):
extracted_license_statement = podspec.get('license')
summary = podspec.get('summary')
description = podspec.get('description')
description = utils.build_description(
description = build_description(
summary=summary,
description=description,
)
Expand Down Expand Up @@ -292,6 +293,7 @@ class PodfileLockHandler(BasePodHandler):
default_primary_language = 'Objective-C'
description = 'Cocoapods Podfile.lock'
documentation_url = 'https://guides.cocoapods.org/using/the-podfile.html'
is_lockfile = True

@classmethod
def parse(cls, location, package_only=False):
Expand All @@ -301,48 +303,168 @@ def parse(cls, location, package_only=False):
with open(location) as pfl:
data = saneyaml.load(pfl)

pods = data['PODS']
dependencies = []
pods = data.get('PODS')

# collect versions of all dependencies
versions_by_base_purl = {}
for pod in pods:
if isinstance(pod, dict):
for main_pod, _dep_pods in pod.items():
purl, xreq = parse_dep_requirements(main_pod)
base_purl = get_base_purl(purl.to_string())
versions_by_base_purl[base_purl] = xreq

elif isinstance(pod, str):
purl, xreq = parse_dep_requirements(pod)
base_purl = get_base_purl(purl.to_string())
versions_by_base_purl[base_purl] = xreq

direct_dependencies = data.get('DEPENDENCIES')
direct_dependency_purls = []
for direct_dep in direct_dependencies:
purl, _xreq = parse_dep_requirements(direct_dep)
base_purl = get_base_purl(purl.to_string())
direct_dependency_purls.append(base_purl)

spec_repos = data.get('SPEC REPOS')
spec_by_base_purl = {}
for spec_repo, packages in spec_repos.items():
for package in packages:
purl, _xreq = parse_dep_requirements(package)
base_purl = get_base_purl(purl.to_string())
spec_by_base_purl[base_purl] = spec_repo

checksums = data.get('SPEC CHECKSUMS')
checksum_by_base_purl = {}
for name, checksum in checksums.items():
purl, _xreq = parse_dep_requirements(name)
base_purl = get_base_purl(purl.to_string())
checksum_by_base_purl[base_purl] = checksum

dependencies = []
for pod in pods:
# dependencies with mappings have direct dependencies
if isinstance(pod, dict):
for main_pod, dep_pods in pod.items():

purl, xreq = parse_dep_requirements(main_pod)
base_purl = get_base_purl(purl.to_string())

dependencies_for_resolved = []
for dep_pod in dep_pods:
dep_purl, _dep_xreq = parse_dep_requirements(dep_pod)
base_dep_purl = get_base_purl(dep_purl.to_string())

dep_version = versions_by_base_purl.get(base_dep_purl)
if not dep_purl.version:
purl_mapping = dep_purl.to_dict()
purl_mapping["version"] = dep_version
dep_purl = PackageURL(**purl_mapping)

dependency_for_resolved = models.DependentPackage(
purl=dep_purl.to_string(),
# FIXME: why dev?
scope='requires',
extracted_requirement=xreq,
is_runtime=False,
is_optional=True,
is_resolved=True,
is_direct=True,
).to_dict()
dependencies_for_resolved.append(dependency_for_resolved)

resolved_package_mapping = dict(
datasource_id=cls.datasource_id,
type=cls.default_package_type,
primary_language=cls.default_primary_language,
namespace=purl.namespace,
name=purl.name,
version=purl.version,
dependencies=dependencies_for_resolved,
is_virtual=True,
)
resolved_package = models.PackageData.from_data(resolved_package_mapping)

checksum = checksum_by_base_purl.get(base_purl)
if checksum:
resolved_package.sha1 = checksum

is_direct = False
if base_purl in direct_dependency_purls:
is_direct = True

spec_repo = spec_by_base_purl.get(base_purl)
if spec_repo:
resolved_package.extra_data["spec_repo"] = spec_repo

dependencies.append(
models.DependentPackage(
purl=str(purl),
purl=purl.to_string(),
# FIXME: why dev?
scope='requires',
extracted_requirement=xreq,
is_runtime=False,
is_optional=True,
is_resolved=True,
is_direct=is_direct,
resolved_package=resolved_package,
)
)

# These packages have no direct dependencies
elif isinstance(pod, str):

purl, xreq = parse_dep_requirements(pod)
base_purl = get_base_purl(purl.to_string())
resolved_package_mapping = dict(
datasource_id=cls.datasource_id,
type=cls.default_package_type,
primary_language=cls.default_primary_language,
namespace=purl.namespace,
name=purl.name,
version=purl.version,
is_virtual=True,
)
resolved_package = models.PackageData.from_data(resolved_package_mapping)

checksum = checksum_by_base_purl.get(base_purl)
if checksum:
resolved_package.sha1 = checksum

is_direct = False
if base_purl in direct_dependency_purls:
is_direct = True

spec_repo = spec_by_base_purl.get(base_purl)
if spec_repo:
resolved_package.extra_data["spec_repo"] = spec_repo

dependencies.append(
models.DependentPackage(
purl=str(purl),
purl=purl.to_string(),
# FIXME: why dev?
scope='requires',
extracted_requirement=xreq,
is_runtime=False,
is_optional=True,
is_resolved=True,
is_direct=is_direct,
resolved_package=resolved_package,
)
)

podfile_checksum = data.get('PODFILE CHECKSUM')
cocoapods_version = data.get('COCOAPODS')
extra_data = {
'cocoapods': cocoapods_version,
'podfile_checksum': podfile_checksum,
}

package_data = dict(
datasource_id=cls.datasource_id,
type=cls.default_package_type,
primary_language=cls.default_primary_language,
dependencies=dependencies,
extra_data=extra_data,
)
yield models.PackageData.from_data(package_data, package_only)

Expand Down
Loading

0 comments on commit b42a49d

Please sign in to comment.