|
36 | 36 | from commoncode import fileutils |
37 | 37 | from commoncode.resource import VirtualCodebase |
38 | 38 | from extractcode import api as extractcode_api |
| 39 | +from packagedcode import get_package_handler |
| 40 | +from packagedcode import models as packagedcode_models |
39 | 41 | from scancode import ScancodeError |
40 | 42 | from scancode import Scanner |
41 | 43 | from scancode import api as scancode_api |
@@ -230,10 +232,9 @@ def save_scan_package_results(codebase_resource, scan_results, scan_errors): |
230 | 232 | Saves the resource scan package results in the database. |
231 | 233 | Creates project errors if any occurred during the scan. |
232 | 234 | """ |
233 | | - packages = scan_results.get("package_data", []) |
234 | | - if packages: |
235 | | - for package_data in packages: |
236 | | - codebase_resource.create_and_add_package(package_data) |
| 235 | + package_data = scan_results.get("package_data", []) |
| 236 | + if package_data: |
| 237 | + codebase_resource.package_data = package_data |
237 | 238 | codebase_resource.status = "application-package" |
238 | 239 | codebase_resource.save() |
239 | 240 |
|
@@ -310,18 +311,81 @@ def scan_for_files(project): |
310 | 311 |
|
311 | 312 | def scan_for_application_packages(project): |
312 | 313 | """ |
313 | | - Runs a package scan on files without a status for a `project`. |
| 314 | + Runs a package scan on files without a status for a `project`, then create |
| 315 | + DiscoveredPackage instances from the detected package data. |
314 | 316 |
|
315 | | - Multiprocessing is enabled by default on this pipe, the number of processes can be |
316 | | - controlled through the SCANCODEIO_PROCESSES setting. |
| 317 | + Multiprocessing is enabled by default on this pipe, the number of processes |
| 318 | + can be controlled through the SCANCODEIO_PROCESSES setting. |
317 | 319 | """ |
318 | 320 | resource_qs = project.codebaseresources.no_status() |
| 321 | + |
| 322 | + # Collect detected Package data and save it to the CodebaseResource it was |
| 323 | + # detected from. |
319 | 324 | _scan_and_save( |
320 | 325 | resource_qs=resource_qs, |
321 | 326 | scan_func=scan_for_package_data, |
322 | 327 | save_func=save_scan_package_results, |
323 | 328 | ) |
324 | 329 |
|
| 330 | + # Iterate through CodebaseResources with Package data and handle them using |
| 331 | + # the proper Package handler from packagedcode. |
| 332 | + assemble_packages(project=project) |
| 333 | + |
| 334 | + |
| 335 | +def add_to_package(package_uid, resource, project): |
| 336 | + """ |
| 337 | + Relate a DiscoveredPackage to `resource` from `project` using `package_uid`. |
| 338 | + """ |
| 339 | + if not package_uid: |
| 340 | + return |
| 341 | + |
| 342 | + resource_package = resource.discovered_packages.filter(package_uid=package_uid) |
| 343 | + if not resource_package.exists(): |
| 344 | + package = project.discoveredpackages.get(package_uid=package_uid) |
| 345 | + resource.discovered_packages.add(package) |
| 346 | + |
| 347 | + |
| 348 | +def assemble_packages(project): |
| 349 | + """ |
| 350 | + Create instances of DiscoveredPackage and DiscoveredDependency for `project` |
| 351 | + from the parsed package data present in the CodebaseResources of `project`. |
| 352 | + """ |
| 353 | + logger.info(f"Project {project} assemble_packages:") |
| 354 | + seen_resource_paths = set() |
| 355 | + |
| 356 | + for resource in project.codebaseresources.has_package_data(): |
| 357 | + if resource.path in seen_resource_paths: |
| 358 | + continue |
| 359 | + |
| 360 | + logger.info(f" Processing: {resource.path}") |
| 361 | + for package_mapping in resource.package_data: |
| 362 | + pd = packagedcode_models.PackageData.from_dict(mapping=package_mapping) |
| 363 | + logger.info(f" Package data: {pd.purl}") |
| 364 | + |
| 365 | + handler = get_package_handler(pd) |
| 366 | + logger.info(f" Selected package handler: {handler.__name__}") |
| 367 | + |
| 368 | + items = handler.assemble( |
| 369 | + package_data=pd, |
| 370 | + resource=resource, |
| 371 | + codebase=project, |
| 372 | + package_adder=add_to_package, |
| 373 | + ) |
| 374 | + |
| 375 | + for item in items: |
| 376 | + logger.info(f" Processing item: {item}") |
| 377 | + if isinstance(item, packagedcode_models.Package): |
| 378 | + package_data = item.to_dict() |
| 379 | + pipes.update_or_create_package(project, package_data) |
| 380 | + elif isinstance(item, packagedcode_models.Dependency): |
| 381 | + # We will handle Dependencies when we properly implement the |
| 382 | + # DiscoveredDependency model |
| 383 | + pass |
| 384 | + elif isinstance(item, CodebaseResource): |
| 385 | + seen_resource_paths.add(item.path) |
| 386 | + else: |
| 387 | + logger.info(f"Unknown Package assembly item type: {item!r}") |
| 388 | + |
325 | 389 |
|
326 | 390 | def run_scancode(location, output_file, options, raise_on_error=False): |
327 | 391 | """ |
|
0 commit comments