|
16 | 16 | from functools import cached_property |
17 | 17 | from itertools import groupby |
18 | 18 | from operator import attrgetter |
| 19 | +from traceback import format_exc as traceback_format_exc |
| 20 | +from typing import List |
19 | 21 | from typing import Union |
20 | 22 | from urllib.parse import urljoin |
21 | 23 |
|
@@ -3067,6 +3069,41 @@ def get_or_create_from_purl(self, purl: Union[PackageURL, str]): |
3067 | 3069 |
|
3068 | 3070 | return package, is_created |
3069 | 3071 |
|
| 3072 | + def bulk_get_or_create_from_purls(self, purls: List[Union[PackageURL, str]]): |
| 3073 | + """ |
| 3074 | + Return new or existing Packages given ``purls`` list of PackageURL object or PURL string. |
| 3075 | + """ |
| 3076 | + purl_strings = [str(p) for p in purls] |
| 3077 | + existing_packages = PackageV2.objects.filter(package_url__in=purl_strings) |
| 3078 | + existing_purls = set(existing_packages.values_list("package_url", flat=True)) |
| 3079 | + |
| 3080 | + all_packages = list(existing_packages) |
| 3081 | + packages_to_create = [] |
| 3082 | + for purl in purls: |
| 3083 | + if str(purl) in existing_purls: |
| 3084 | + continue |
| 3085 | + |
| 3086 | + purl_dict = purl_to_dict(purl) |
| 3087 | + purl = PackageURL(**purl_dict) |
| 3088 | + |
| 3089 | + normalized = normalize_purl(purl=purl) |
| 3090 | + for name, value in purl_to_dict(normalized).items(): |
| 3091 | + setattr(self, name, value) |
| 3092 | + |
| 3093 | + purl_dict["package_url"] = str(normalized) |
| 3094 | + purl_dict["plain_package_url"] = str(utils.plain_purl(normalized)) |
| 3095 | + |
| 3096 | + packages_to_create.append(PackageV2(**purl_dict)) |
| 3097 | + |
| 3098 | + try: |
| 3099 | + new_packages = PackageV2.objects.bulk_create(packages_to_create) |
| 3100 | + except Exception as e: |
| 3101 | + logging.error(f"Error creating PackageV2: {e} \n {traceback_format_exc()}") |
| 3102 | + return [] |
| 3103 | + |
| 3104 | + all_packages.extend(new_packages) |
| 3105 | + return all_packages |
| 3106 | + |
3070 | 3107 | def only_vulnerable(self): |
3071 | 3108 | return self._vulnerable(True) |
3072 | 3109 |
|
|
0 commit comments