Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/plugin_api/7272.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Harden RepositoryVersion memoization against bugs that could lead to incorrect counts and repository content.
8 changes: 8 additions & 0 deletions pulpcore/app/models/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,7 @@ def add_content(self, content):
complete RepositoryVersion
"""

assert issubclass(content.model, Content)
if self.complete:
raise ResourceImmutableError(self)

Expand All @@ -1077,6 +1078,7 @@ def add_content(self, content):
.exclude(pulp_domain_id=get_domain_pk())
.exists()
)

repo_content = []
to_add = set(content.values_list("pk", flat=True)) - set(self._get_content_ids())
with transaction.atomic():
Expand Down Expand Up @@ -1115,12 +1117,14 @@ def remove_content(self, content):
complete RepositoryVersion
"""

assert issubclass(content.model, Content)
if self.complete:
raise ResourceImmutableError(self)

if not content or not content.count():
return

# check that all content is within the current domain
assert (
not Content.objects.filter(pk__in=content)
.exclude(pulp_domain_id=get_domain_pk())
Expand Down Expand Up @@ -1158,6 +1162,7 @@ def set_content(self, content):
pulpcore.exception.ResourceImmutableError: if set_content is called on a
complete RepositoryVersion
"""
assert issubclass(content.model, Content)
self.remove_content(self.content.exclude(pk__in=content))
self.add_content(content.exclude(pk__in=self.content))

Expand Down Expand Up @@ -1307,6 +1312,9 @@ def _compute_counts(self):
objects and makes new ones with each call.
"""
with transaction.atomic():
# relatively inexpensive sanity check for memoization
assert len(self.content_ids) == self._content_relationships().count()
# delete existing content details and recompute them all
RepositoryVersionContentDetails.objects.filter(repository_version=self).delete()
counts_list = []
for value, name in RepositoryVersionContentDetails.COUNT_TYPE_CHOICES:
Expand Down
Loading