Skip to content

Commit

Permalink
Fix package name case-insensitivity
Browse files Browse the repository at this point in the history
Prevent newly uploaded packages from having the same name but in a
different case.
  • Loading branch information
x753 committed Sep 23, 2024
1 parent aba4310 commit dfe2b0b
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
10 changes: 9 additions & 1 deletion django/thunderstore/repository/package_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
PackageVersionField,
StrictCharField,
)
from thunderstore.repository.utils import does_contain_package, has_duplicate_packages
from thunderstore.repository.utils import (
does_contain_package,
has_different_case,
has_duplicate_packages,
)


class PackageInstallerSerializer(serializers.Serializer):
Expand Down Expand Up @@ -96,6 +100,10 @@ def validate(self, data):
)
if does_contain_package(result["dependencies"], reference):
raise ValidationError("Package depending on itself is not allowed")
if has_different_case(reference.without_version):
raise ValidationError(
"Package name already exists with different capitalization"
)
return result

def update(self, instance, validated_data):
Expand Down
19 changes: 19 additions & 0 deletions django/thunderstore/repository/package_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,22 @@ def exists(self) -> bool:
:rtype: bool
"""
return self.queryset.exists()

@cached_property
def exists_in_any_case(self) -> bool:
"""
Check if a package with a name with different capitalization exists in the db
:return: True if a different case package exists, False otherwise
:rtype: bool
"""
if self.version:
return Package.objects.filter(
package__owner__name=self.namespace,
package__name__iexact=self.name,
version_number=self.version_str,
).exists()
else:
return Package.objects.filter(
owner__name=self.namespace, name__iexact=self.name
).exists()
22 changes: 22 additions & 0 deletions django/thunderstore/repository/tests/test_package_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,28 @@ def test_manifest_v1_serializer_version_already_exists(
)


@pytest.mark.django_db
def test_manifest_v1_serializer_package_already_exists_with_different_case(
user, manifest_v1_data, package
):
TeamMember.objects.create(
user=user,
team=package.owner,
role=TeamMemberRole.owner,
)
manifest_v1_data["name"] = package.name.swapcase()
serializer = ManifestV1Serializer(
user=user,
team=package.owner,
data=manifest_v1_data,
)
assert serializer.is_valid() is False
assert len(serializer.errors["non_field_errors"]) == 1
assert "Package name already exists with different capitalization" in str(
serializer.errors["non_field_errors"][0]
)


@pytest.mark.django_db
def test_manifest_v1_serializer_duplicate_dependency(
user, manifest_v1_data, package_version, namespace
Expand Down
8 changes: 8 additions & 0 deletions django/thunderstore/repository/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ def has_duplicate_packages(packages: List["PackageReference"]) -> bool:
return False


def has_different_case(reference: "PackageReference") -> bool:
if reference.exists:
return False
elif reference.exists_in_any_case:
return True
return False


def unpack_serializer_errors(field, errors, error_dict=None):
if error_dict is None:
error_dict = {}
Expand Down

0 comments on commit dfe2b0b

Please sign in to comment.