Handle "original" size icon being absent when disabling, falling back on largest size (#22126)
This commit is contained in:
Родитель
ab2da9e475
Коммит
229e8dab84
|
@ -0,0 +1,36 @@
|
|||
from django.core.files.storage import default_storage as storage
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from olympia import amo
|
||||
from olympia.addons.models import Addon
|
||||
from olympia.addons.tasks import resize_icon
|
||||
from olympia.core.logger import getLogger
|
||||
|
||||
|
||||
log = getLogger('z.addons.fix_missing_icons')
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Fix missing icons on specific add-ons'
|
||||
addon_ids = [271830, 823490, 805933, 583250, 790974, 3006]
|
||||
|
||||
def handle(self, *args, **options):
|
||||
for addon in Addon.objects.filter(pk__in=self.addon_ids):
|
||||
icon_path = addon.get_icon_path('original')
|
||||
if storage.exists(icon_path):
|
||||
log.info(
|
||||
'Original icon already exists for addon %s, skipping.', addon.pk
|
||||
)
|
||||
continue
|
||||
backup_path = f'static/img/addon-icons/{addon.pk}-64.png'
|
||||
with open(backup_path, 'rb') as f:
|
||||
storage.save(storage.path(icon_path), f)
|
||||
resize_icon.delay(
|
||||
icon_path,
|
||||
addon.pk,
|
||||
amo.ADDON_ICON_SIZES,
|
||||
set_modified_on=addon.serializable_reference(),
|
||||
)
|
||||
log.info(
|
||||
'Saved new original icon for addon %s and triggered resizing.', addon.pk
|
||||
)
|
|
@ -97,9 +97,13 @@ def delete_all_addon_media_with_backup(id, **kwargs):
|
|||
disabled_addon_content = DisabledAddonContent.objects.get_or_create(addon=addon)[0]
|
||||
|
||||
if addon.icon_type:
|
||||
base_icon_path = os.path.join(addon.get_icon_dir(), str(addon.pk))
|
||||
icon_path = f'{base_icon_path}-original.{amo.ADDON_ICON_FORMAT}'
|
||||
if backup_storage_enabled() and storage.exists(icon_path):
|
||||
icon_path = None
|
||||
for size in ['original'] + sorted(amo.ADDON_ICON_SIZES, reverse=True):
|
||||
_icon_path = addon.get_icon_path(size)
|
||||
if storage.exists(_icon_path):
|
||||
icon_path = _icon_path
|
||||
break
|
||||
if backup_storage_enabled() and icon_path:
|
||||
backup_file_name = copy_file_to_backup_storage(icon_path, addon.icon_type)
|
||||
disabled_addon_content.update(icon_backup_name=backup_file_name)
|
||||
remove_icons(addon)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import hashlib
|
||||
import random
|
||||
from contextlib import contextmanager
|
||||
from datetime import timedelta
|
||||
|
@ -588,3 +589,32 @@ class TestPopulateAccessibilityCategory(TestCase):
|
|||
assert addon.all_categories == [accessibility_category, shopping_category]
|
||||
extra_addon.reload()
|
||||
assert extra_addon.all_categories == [shopping_category]
|
||||
|
||||
|
||||
class TestFixMissingIcons(TestCase):
|
||||
def test_basic(self):
|
||||
extra_addons = [addon_factory(), addon_factory()]
|
||||
addons_with_missing_icons = [
|
||||
addon_factory(pk=271830),
|
||||
addon_factory(pk=823490),
|
||||
addon_factory(pk=805933),
|
||||
addon_factory(pk=583250),
|
||||
addon_factory(pk=790974),
|
||||
addon_factory(pk=3006),
|
||||
]
|
||||
call_command('fix_missing_icons')
|
||||
|
||||
for addon in extra_addons:
|
||||
addon.reload()
|
||||
assert not addon.icon_hash
|
||||
for size in ['original'] + list(amo.ADDON_ICON_SIZES):
|
||||
assert not self.root_storage.exists(addon.get_icon_path(size))
|
||||
|
||||
for addon in addons_with_missing_icons:
|
||||
addon.reload()
|
||||
for size in ['original'] + list(amo.ADDON_ICON_SIZES):
|
||||
assert self.root_storage.exists(addon.get_icon_path(size))
|
||||
backup_path = f'{settings.ROOT}/static/img/addon-icons/{addon.pk}-64.png'
|
||||
with open(backup_path, 'rb') as f:
|
||||
icon_hash = hashlib.md5(f.read()).hexdigest()[:8]
|
||||
assert addon.icon_hash == icon_hash
|
||||
|
|
|
@ -690,6 +690,32 @@ class TestDeleteAndRestoreAllAddonMediaWithFromBackup(TestCase):
|
|||
DisabledAddonContent.objects.create(addon=self.addon, icon_backup_name='lol')
|
||||
self.test_delete_all_addon_media_with_backup()
|
||||
|
||||
def test_delete_icon_original_does_not_exist(self):
|
||||
self.addon.update(icon_type='image/png')
|
||||
# No original icon.
|
||||
self.root_storage.copy_stored_file(
|
||||
get_image_path('sunbird-small.png'), self.addon.get_icon_path(128)
|
||||
)
|
||||
delete_all_addon_media_with_backup(self.addon.pk)
|
||||
assert self.copy_file_to_backup_storage_mock.call_count == 1
|
||||
assert self.copy_file_to_backup_storage_mock.call_args_list[0][0] == (
|
||||
self.addon.get_icon_path(128),
|
||||
'image/png',
|
||||
)
|
||||
|
||||
def test_delete_icon_pick_largest_size_that_exists(self):
|
||||
self.addon.update(icon_type='image/png')
|
||||
# No original icon, no 128 either.
|
||||
self.root_storage.copy_stored_file(
|
||||
get_image_path('sunbird-small.png'), self.addon.get_icon_path(64)
|
||||
)
|
||||
delete_all_addon_media_with_backup(self.addon.pk)
|
||||
assert self.copy_file_to_backup_storage_mock.call_count == 1
|
||||
assert self.copy_file_to_backup_storage_mock.call_args_list[0][0] == (
|
||||
self.addon.get_icon_path(64),
|
||||
'image/png',
|
||||
)
|
||||
|
||||
def test_delete_theme(self):
|
||||
self.addon.update(type=amo.ADDON_STATICTHEME)
|
||||
for position in range(1, 3):
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.5 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.9 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 5.3 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 3.8 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 4.3 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 3.9 KiB |
Загрузка…
Ссылка в новой задаче