Skip to content

Commit 6973a54

Browse files
authored
Merge pull request #2289 from aboutcode-org/package-bulk-create-fix
fix: ignore conflicts while bulk creating v2 packages
2 parents 60fee54 + b729bad commit 6973a54

3 files changed

Lines changed: 46 additions & 14 deletions

File tree

vulnerabilities/models.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3399,19 +3399,12 @@ def get_or_create_from_purl(self, purl: Union[PackageURL, str]):
33993399
return package, is_created
34003400

34013401
def bulk_get_or_create_from_purls(self, purls: List[Union[PackageURL, str]]):
3402-
"""
3403-
Return new or existing Packages given ``purls`` list of PackageURL object or PURL string.
3404-
"""
3405-
purl_strings = [str(p) for p in purls]
3406-
existing_packages = PackageV2.objects.filter(package_url__in=purl_strings)
3407-
existing_purls = set(existing_packages.values_list("package_url", flat=True))
3402+
"""Return queryset of Packages for a list of PURLs, bulk create any that do not already exist."""
34083403

3409-
all_packages = list(existing_packages)
34103404
packages_to_create = []
3411-
for purl in purls:
3412-
if str(purl) in existing_purls:
3413-
continue
3405+
normalize_purls = []
34143406

3407+
for purl in purls:
34153408
purl_dict = purl_to_dict(purl)
34163409
purl = PackageURL(**purl_dict)
34173410

@@ -3422,16 +3415,16 @@ def bulk_get_or_create_from_purls(self, purls: List[Union[PackageURL, str]]):
34223415
purl_dict["package_url"] = str(normalized)
34233416
purl_dict["plain_package_url"] = str(utils.plain_purl(normalized))
34243417

3418+
normalize_purls.append(str(normalized))
34253419
packages_to_create.append(PackageV2(**purl_dict))
34263420

34273421
try:
3428-
new_packages = PackageV2.objects.bulk_create(packages_to_create)
3422+
PackageV2.objects.bulk_create(packages_to_create, ignore_conflicts=True)
34293423
except Exception as e:
34303424
logging.error(f"Error creating PackageV2: {e} \n {traceback_format_exc()}")
34313425
return []
34323426

3433-
all_packages.extend(new_packages)
3434-
return all_packages
3427+
return PackageV2.objects.filter(package_url__in=normalize_purls)
34353428

34363429
def only_vulnerable(self):
34373430
return self._vulnerable(True)

vulnerabilities/pipelines/v2_improvers/unfurl_version_range.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ def bulk_create_with_m2m(purls, impact, relation, logger):
166166

167167
affected_packages_v2 = PackageV2.objects.bulk_get_or_create_from_purls(purls=purls)
168168

169-
affected_packages_v2[-1].calculate_version_rank
169+
if not affected_packages_v2.exists():
170+
return 0
171+
172+
affected_packages_v2.first().calculate_version_rank
170173

171174
relations = [
172175
relation(impacted_package=impact, package=package) for package in affected_packages_v2

vulnerabilities/tests/test_models.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from vulnerabilities.models import AdvisorySeverity
3535
from vulnerabilities.models import Alias
3636
from vulnerabilities.models import Package
37+
from vulnerabilities.models import PackageV2
3738
from vulnerabilities.models import Patch
3839
from vulnerabilities.models import Vulnerability
3940
from vulnerabilities.severity_systems import CVSSV3
@@ -827,3 +828,38 @@ def test_advisoryv2_duplication_data(self):
827828
result = models.AdvisoryV2.objects.count()
828829

829830
self.assertEqual(result, 2)
831+
832+
833+
class TestPackageV2BulkCreate(DjangoTestCase):
834+
def setUp(self):
835+
PackageV2.objects.get_or_create_from_purl(
836+
"pkg:deb/ubuntu/linux@6.17.0-19.19?arch=source&distro=questing"
837+
)
838+
PackageV2.objects.get_or_create_from_purl("pkg:pypi/foo@1.2.3")
839+
PackageV2.objects.get_or_create_from_purl("pkg:npm/foobar@3.2.3")
840+
PackageV2.objects.get_or_create_from_purl("pkg:maven/foo@1.2.3")
841+
PackageV2.objects.get_or_create_from_purl(
842+
"pkg:deb/ubuntu/linux@6.17.0-4.4?arch=source&distro=questing"
843+
)
844+
845+
def test_package_bulk_get_or_create_from_purls(self):
846+
purls = [
847+
"pkg:npm/foo@1.2.3",
848+
"pkg:pypi/foo@1.2.3",
849+
"pkg:npm/foobar@3.2.3",
850+
"pkg:maven/foo@1.2.3",
851+
"pkg:nuget/foo@1.2.3",
852+
"pkg:deb/ubuntu/linux@6.17.0-22.22?arch=source&distro=questing",
853+
"pkg:deb/ubuntu/linux@6.17.0-20.20?arch=source&distro=questing",
854+
"pkg:deb/ubuntu/linux@6.17.0-14.14?arch=source&distro=questing",
855+
"pkg:deb/ubuntu/linux@6.17.0-12.12?arch=source&distro=questing",
856+
"pkg:deb/ubuntu/linux@6.17.0-8.8?arch=source&distro=questing",
857+
"pkg:deb/ubuntu/linux@6.17.0-7.7?arch=source&distro=questing",
858+
"pkg:deb/ubuntu/linux@6.17.0-6.6?arch=source&distro=questing",
859+
"pkg:deb/ubuntu/linux@6.17.0-5.5?arch=source&distro=questing",
860+
"pkg:deb/ubuntu/linux@6.17.0-4.4?arch=source&distro=questing",
861+
]
862+
result_qs = PackageV2.objects.bulk_get_or_create_from_purls(purls)
863+
result = [p.package_url for p in result_qs]
864+
865+
self.assertCountEqual(result, purls)

0 commit comments

Comments
 (0)