Multi-platform: support multiple files per version #201

Merged
Oleg-Komarov merged 43 commits from multi-os into main 2024-07-09 16:27:46 +02:00
4 changed files with 44 additions and 11 deletions
Showing only changes of commit 8af96c48c0 - Show all commits

View File

@ -682,6 +682,13 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
return len(self.get_remaining_platforms()) > 0 return len(self.get_remaining_platforms()) > 0
def add_file(self, file: File): def add_file(self, file: File):
current_platforms = set([p.slug for p in self.platforms.all()])
file_platforms = set(file.get_platforms() or [])
if overlap := current_platforms & file_platforms:
raise ValueError(
f'add_file failed: File pk={file.pk} and Version pk={self.pk} have '
f'overlapping platforms: {overlap}'
)
self.files.add(file) self.files.add(file)
self.update_platforms() self.update_platforms()
@ -716,6 +723,16 @@ class Version(CreatedModifiedMixin, TrackChangesMixin, models.Model):
all_platforms -= set(platforms) all_platforms -= set(platforms)
return all_platforms return all_platforms
def get_file_for_platform(self, platform):
for file in self.files.all():
platforms = file.get_platforms()
# not platform-specific, matches all platforms
if not platforms:
return file
if platform is None or platform in platforms:
return file
return None
@property @property
def is_listed(self): def is_listed(self):
# To be public, at least one version file must have a public status. # To be public, at least one version file must have a public status.

View File

@ -125,6 +125,29 @@ class VersionTest(TestCase):
Platform.objects.filter(slug__in=['linux-x64']).order_by('slug'), Platform.objects.filter(slug__in=['linux-x64']).order_by('slug'),
) )
def test_add_file(self):
version = create_version(metadata__platforms=['linux-x64'])
file = FileFactory(metadata__platforms=['linux-x64'])
with self.assertRaises(ValueError):
version.add_file(file)
def test_get_file_for_platform(self):
version = create_version(metadata__platforms=['linux-x64'])
file = FileFactory(metadata__platforms=['windows-x64'])
version.add_file(file)
self.assertIsNotNone(version.get_file_for_platform(None))
self.assertIsNotNone(version.get_file_for_platform('linux-x64'))
self.assertIsNotNone(version.get_file_for_platform('windows-x64'))
self.assertIsNone(version.get_file_for_platform('windows-arm64'))
file2 = FileFactory(metadata__platforms=['macos-x64', 'macos-arm64'])
version.add_file(file2)
self.assertIsNotNone(version.get_file_for_platform('macos-x64'))
version2 = create_version(metadata__platforms=[])
self.assertIsNotNone(version2.get_file_for_platform(None))
self.assertIsNotNone(version2.get_file_for_platform('macos-x64'))
class UpdateMetadataTest(TestCase): class UpdateMetadataTest(TestCase):
fixtures = ['dev', 'licenses'] fixtures = ['dev', 'licenses']

View File

@ -71,12 +71,7 @@ class ListedExtensionsSerializer(serializers.ModelSerializer):
v.blender_version_max, v.blender_version_max,
): ):
continue continue
for file in v.files.all(): if file := v.get_file_for_platform(self.platform):
# empty platforms field matches any platform filter
# UNKNOWN_PLATFORM matches only empty platforms field
platforms = file.get_platforms()
if self.platform and (platforms and self.platform not in platforms):
continue
return (file, v) return (file, v)
return (None, None) return (None, None)

View File

@ -73,9 +73,7 @@ def extension_version_platform_download(request, type_slug, slug, version, platf
extension_version = get_object_or_404(Version, extension__slug=slug, version=version) extension_version = get_object_or_404(Version, extension__slug=slug, version=version)
ExtensionDownload.create_from_request(request, object_id=extension_version.extension_id) ExtensionDownload.create_from_request(request, object_id=extension_version.extension_id)
VersionDownload.create_from_request(request, object_id=extension_version.pk) VersionDownload.create_from_request(request, object_id=extension_version.pk)
for file in extension_version.files.all(): if file := extension_version.get_file_for_platform(platform):
platforms = file.get_platforms() or []
if platform is None or platform in platforms:
url = file.source.url url = file.source.url
return redirect(f'{url}?filename={filename}') return redirect(f'{url}?filename={filename}')
raise Http404() raise Http404()