mirror of
https://github.com/zulip/zulip.git
synced 2025-11-10 00:46:03 +00:00
This will make django automatically remove them when we run squashmigrations. There are still some RunSQL statements which we will have to take care of manually.
112 lines
4.5 KiB
Python
112 lines
4.5 KiB
Python
import os
|
|
import shutil
|
|
|
|
from boto.s3.connection import S3Connection
|
|
from django.conf import settings
|
|
from django.db import migrations, models
|
|
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
|
|
from django.db.migrations.state import StateApps
|
|
|
|
|
|
class Uploader:
|
|
def __init__(self) -> None:
|
|
self.old_orig_image_path_template = "{realm_id}/emoji/{emoji_file_name}.original"
|
|
self.old_path_template = "{realm_id}/emoji/{emoji_file_name}"
|
|
self.new_orig_image_path_template = "{realm_id}/emoji/images/{emoji_file_name}.original"
|
|
self.new_path_template = "{realm_id}/emoji/images/{emoji_file_name}"
|
|
|
|
def copy_files(self, src_path: str, dst_path: str) -> None:
|
|
raise NotImplementedError()
|
|
|
|
def ensure_emoji_images(self, realm_id: int, old_filename: str, new_filename: str) -> None:
|
|
# Copy original image file.
|
|
old_file_path = self.old_orig_image_path_template.format(realm_id=realm_id,
|
|
emoji_file_name=old_filename)
|
|
new_file_path = self.new_orig_image_path_template.format(realm_id=realm_id,
|
|
emoji_file_name=new_filename)
|
|
self.copy_files(old_file_path, new_file_path)
|
|
|
|
# Copy resized image file.
|
|
old_file_path = self.old_path_template.format(realm_id=realm_id,
|
|
emoji_file_name=old_filename)
|
|
new_file_path = self.new_path_template.format(realm_id=realm_id,
|
|
emoji_file_name=new_filename)
|
|
self.copy_files(old_file_path, new_file_path)
|
|
|
|
class LocalUploader(Uploader):
|
|
def __init__(self) -> None:
|
|
super().__init__()
|
|
|
|
@staticmethod
|
|
def mkdirs(path: str) -> None:
|
|
dirname = os.path.dirname(path)
|
|
if not os.path.isdir(dirname):
|
|
os.makedirs(dirname)
|
|
|
|
def copy_files(self, src_path: str, dst_path: str) -> None:
|
|
src_path = os.path.join(settings.LOCAL_UPLOADS_DIR, 'avatars', src_path)
|
|
self.mkdirs(src_path)
|
|
dst_path = os.path.join(settings.LOCAL_UPLOADS_DIR, 'avatars', dst_path)
|
|
self.mkdirs(dst_path)
|
|
shutil.copyfile(src_path, dst_path)
|
|
|
|
class S3Uploader(Uploader):
|
|
def __init__(self) -> None:
|
|
super().__init__()
|
|
conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
|
|
self.bucket_name = settings.S3_AVATAR_BUCKET
|
|
self.bucket = conn.get_bucket(self.bucket_name, validate=False)
|
|
|
|
def copy_files(self, src_key: str, dst_key: str) -> None:
|
|
self.bucket.copy_key(dst_key, self.bucket_name, src_key)
|
|
|
|
def get_uploader() -> Uploader:
|
|
if settings.LOCAL_UPLOADS_DIR is None:
|
|
return S3Uploader()
|
|
return LocalUploader()
|
|
|
|
def get_emoji_file_name(emoji_file_name: str, new_name: str) -> str:
|
|
_, image_ext = os.path.splitext(emoji_file_name)
|
|
return ''.join((new_name, image_ext))
|
|
|
|
def migrate_realm_emoji_image_files(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
|
|
RealmEmoji = apps.get_model('zerver', 'RealmEmoji')
|
|
uploader = get_uploader()
|
|
for realm_emoji in RealmEmoji.objects.all():
|
|
old_file_name = realm_emoji.file_name
|
|
new_file_name = get_emoji_file_name(old_file_name, str(realm_emoji.id))
|
|
uploader.ensure_emoji_images(realm_emoji.realm_id, old_file_name, new_file_name)
|
|
realm_emoji.file_name = new_file_name
|
|
realm_emoji.save(update_fields=['file_name'])
|
|
|
|
def reversal(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
|
|
# Ensures that migration can be re-run in case of a failure.
|
|
RealmEmoji = apps.get_model('zerver', 'RealmEmoji')
|
|
for realm_emoji in RealmEmoji.objects.all():
|
|
corrupt_file_name = realm_emoji.file_name
|
|
correct_file_name = get_emoji_file_name(corrupt_file_name, realm_emoji.name)
|
|
realm_emoji.file_name = correct_file_name
|
|
realm_emoji.save(update_fields=['file_name'])
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
dependencies = [
|
|
('zerver', '0148_max_invites_forget_default'),
|
|
]
|
|
|
|
operations = [
|
|
migrations.AlterUniqueTogether(
|
|
name='realmemoji',
|
|
unique_together=set(),
|
|
),
|
|
migrations.AlterField(
|
|
model_name='realmemoji',
|
|
name='file_name',
|
|
field=models.TextField(db_index=True, null=True, blank=True),
|
|
),
|
|
migrations.RunPython(
|
|
migrate_realm_emoji_image_files,
|
|
reverse_code=reversal,
|
|
elidable=True),
|
|
]
|