mirror of
https://github.com/tcsenpai/swingmusic.git
synced 2025-06-07 03:35:35 +00:00
feat: add migration to move old files to xdg directory
+ add db column for migration version + handle pre-init migrations + handle post-init migration
This commit is contained in:
parent
97e29c3254
commit
b77b1747f1
64
app/db/sqlite/migrations.py
Normal file
64
app/db/sqlite/migrations.py
Normal file
@ -0,0 +1,64 @@
|
||||
"""
|
||||
Reads and saves the latest database migrations version.
|
||||
"""
|
||||
|
||||
|
||||
from app.db.sqlite.utils import SQLiteManager
|
||||
|
||||
|
||||
class MigrationManager:
|
||||
all_get_sql = "SELECT * FROM migrations"
|
||||
pre_init_set_sql = "UPDATE migrations SET pre_init_version = ? WHERE id = 1"
|
||||
post_init_set_sql = "UPDATE migrations SET post_init_version = ? WHERE id = 1"
|
||||
|
||||
@classmethod
|
||||
def get_preinit_version(cls) -> int:
|
||||
"""
|
||||
Returns the latest userdata pre-init database version.
|
||||
"""
|
||||
with SQLiteManager() as cur:
|
||||
cur.execute(cls.all_get_sql)
|
||||
return int(cur.fetchone()[1])
|
||||
|
||||
@classmethod
|
||||
def get_maindb_postinit_version(cls) -> int:
|
||||
"""
|
||||
Returns the latest maindb post-init database version.
|
||||
"""
|
||||
with SQLiteManager() as cur:
|
||||
cur.execute(cls.all_get_sql)
|
||||
return int(cur.fetchone()[2])
|
||||
|
||||
@classmethod
|
||||
def get_userdatadb_postinit_version(cls) -> int:
|
||||
"""
|
||||
Returns the latest userdata post-init database version.
|
||||
"""
|
||||
with SQLiteManager(userdata_db=True) as cur:
|
||||
cur.execute(cls.all_get_sql)
|
||||
return cur.fetchone()[2]
|
||||
|
||||
# 👇 Setters 👇
|
||||
@classmethod
|
||||
def set_preinit_version(cls, version: int):
|
||||
"""
|
||||
Sets the userdata pre-init database version.
|
||||
"""
|
||||
with SQLiteManager() as cur:
|
||||
cur.execute(cls.pre_init_set_sql, (version,))
|
||||
|
||||
@classmethod
|
||||
def set_maindb_postinit_version(cls, version: int):
|
||||
"""
|
||||
Sets the maindb post-init database version.
|
||||
"""
|
||||
with SQLiteManager() as cur:
|
||||
cur.execute(cls.post_init_set_sql, (version,))
|
||||
|
||||
@classmethod
|
||||
def set_userdatadb_postinit_version(cls, version: int):
|
||||
"""
|
||||
Sets the userdata post-init database version.
|
||||
"""
|
||||
with SQLiteManager(userdata_db=True) as cur:
|
||||
cur.execute(cls.post_init_set_sql, (version,))
|
@ -69,3 +69,13 @@ CREATE TABLE IF NOT EXISTS folders (
|
||||
trackcount integer NOT NULL
|
||||
);
|
||||
"""
|
||||
|
||||
CREATE_MIGRATIONS_TABLE = """
|
||||
CREATE TABLE IF NOT EXISTS migrations (
|
||||
id integer PRIMARY KEY,
|
||||
pre_init_version integer NOT NULL DEFAULT 0,
|
||||
post_init_version integer NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
INSERT INTO migrations (pre_init_version, post_init_version) VALUES (0, 0);
|
||||
"""
|
||||
|
@ -2,19 +2,43 @@
|
||||
Migrations module.
|
||||
|
||||
Reads and applies the latest database migrations.
|
||||
|
||||
PLEASE NOTE: OLDER MIGRATIONS CAN NEVER BE DELETED.
|
||||
ONLY MODIFY OLD MIGRATIONS FOR BUG FIXES OR ENHANCEMENTS ONLY
|
||||
[TRY NOT TO MODIFY BEHAVIOR, UNLESS YOU KNOW WHAT YOU'RE DOING].
|
||||
"""
|
||||
|
||||
|
||||
from app.db.sqlite.migrations import MigrationManager
|
||||
from app.logger import log
|
||||
|
||||
from .main import main_db_migrations
|
||||
from .userdata import userdata_db_migrations
|
||||
|
||||
|
||||
def apply_migrations():
|
||||
userdb_version = 0
|
||||
maindb_version = 0
|
||||
"""
|
||||
Applies the latest database migrations.
|
||||
"""
|
||||
|
||||
userdb_version = MigrationManager.get_userdatadb_postinit_version()
|
||||
maindb_version = MigrationManager.get_maindb_postinit_version()
|
||||
|
||||
for migration in main_db_migrations:
|
||||
if migration.version > maindb_version:
|
||||
log.info("Running new MAIN-DB post-init migration: %s", migration.name)
|
||||
migration.migrate()
|
||||
|
||||
for migration in userdata_db_migrations:
|
||||
if migration.version > userdb_version:
|
||||
log.info("Running new USERDATA-DB post-init migration: %s", migration.name)
|
||||
migration.migrate()
|
||||
|
||||
|
||||
def set_postinit_migration_versions():
|
||||
"""
|
||||
Sets the post-init migration versions.
|
||||
"""
|
||||
# TODO: Don't forget to remove the zeros below when you add a valid migration 👇.
|
||||
MigrationManager.set_maindb_postinit_version(0)
|
||||
MigrationManager.set_userdatadb_postinit_version(0)
|
||||
|
38
app/migrations/_preinit/__init__.py
Normal file
38
app/migrations/_preinit/__init__.py
Normal file
@ -0,0 +1,38 @@
|
||||
"""
|
||||
Pre-init migrations are executed before the database is created.
|
||||
Useful when you need to move files or folders before the database is created.
|
||||
|
||||
PLEASE NOTE: OLDER MIGRATIONS CAN NEVER BE DELETED.
|
||||
ONLY MODIFY OLD MIGRATIONS FOR BUG FIXES OR ENHANCEMENTS ONLY.
|
||||
[TRY NOT TO MODIFY BEHAVIOR, UNLESS YOU KNOW WHAT YOU'RE DOING].
|
||||
"""
|
||||
from sqlite3 import OperationalError
|
||||
|
||||
from app.db.sqlite.migrations import MigrationManager
|
||||
from app.logger import log
|
||||
|
||||
from .move_to_xdg_folder import MoveToXdgFolder
|
||||
|
||||
all_preinits = [MoveToXdgFolder]
|
||||
|
||||
|
||||
def run_preinit_migrations():
|
||||
"""
|
||||
Runs all pre-init migrations.
|
||||
"""
|
||||
try:
|
||||
userdb_version = MigrationManager.get_preinit_version()
|
||||
except (OperationalError):
|
||||
userdb_version = 0
|
||||
|
||||
for migration in all_preinits:
|
||||
if migration.version > userdb_version:
|
||||
log.warn("Running new pre-init migration: %s", migration.name)
|
||||
migration.migrate()
|
||||
|
||||
|
||||
def set_preinit_migration_versions():
|
||||
"""
|
||||
Sets the migration versions.
|
||||
"""
|
||||
MigrationManager.set_preinit_version(all_preinits[-1].version)
|
49
app/migrations/_preinit/move_to_xdg_folder.py
Normal file
49
app/migrations/_preinit/move_to_xdg_folder.py
Normal file
@ -0,0 +1,49 @@
|
||||
"""
|
||||
This migration handles moving the config folder to the XDG standard location.
|
||||
It also handles moving the userdata and the downloaded artist images to the new location.
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from app.settings import APP_DIR, USER_HOME_DIR
|
||||
from app.logger import log
|
||||
|
||||
|
||||
class MoveToXdgFolder:
|
||||
version = 1
|
||||
name = "MoveToXdgFolder"
|
||||
|
||||
@staticmethod
|
||||
def migrate():
|
||||
old_config_dir = os.path.join(USER_HOME_DIR, ".swing")
|
||||
new_config_dir = APP_DIR
|
||||
|
||||
if not os.path.exists(old_config_dir):
|
||||
log.info("No old config folder found. Skipping migration.")
|
||||
return
|
||||
|
||||
log.info("Found old config folder: %s", old_config_dir)
|
||||
old_imgs_dir = os.path.join(old_config_dir, "images")
|
||||
|
||||
# move images to new location
|
||||
if os.path.exists(old_imgs_dir):
|
||||
shutil.copytree(
|
||||
old_imgs_dir,
|
||||
os.path.join(new_config_dir, "images"),
|
||||
copy_function=shutil.copy2,
|
||||
dirs_exist_ok=True,
|
||||
)
|
||||
|
||||
log.warn("Moved artist images to: %s", new_config_dir)
|
||||
|
||||
# move userdata.db to new location
|
||||
userdata_db = os.path.join(old_config_dir, "userdata.db")
|
||||
if os.path.exists(userdata_db):
|
||||
shutil.copy2(userdata_db, new_config_dir)
|
||||
|
||||
log.warn("Moved userdata.db to: %s", new_config_dir)
|
||||
log.warn("Migration complete. ✅")
|
||||
|
||||
# swing.db is not moved because the new code fixes bugs which require
|
||||
# the whole database to be recreated anyway. (ie. the bug which caused duplicate album and artist color entries)
|
@ -1,4 +1,10 @@
|
||||
from .sample import SampleMigrationModel
|
||||
"""
|
||||
Migrations for the main database.
|
||||
|
||||
main_db_migrations = [SampleMigrationModel]
|
||||
PLEASE NOTE: OLDER MIGRATIONS CAN NEVER BE DELETED.
|
||||
ONLY MODIFY OLD MIGRATIONS FOR BUG FIXES OR ENHANCEMENTS ONLY
|
||||
[TRY NOT TO MODIFY BEHAVIOR, UNLESS YOU KNOW WHAT YOU'RE DOING].
|
||||
"""
|
||||
|
||||
|
||||
main_db_migrations = []
|
||||
|
@ -1,6 +0,0 @@
|
||||
class SampleMigrationModel:
|
||||
version = 1
|
||||
|
||||
@staticmethod
|
||||
def migrate():
|
||||
print("executing sample main db migration")
|
@ -1,4 +1,10 @@
|
||||
from .sample import SampleMigrationModel
|
||||
"""
|
||||
Migrations for the userdata database.
|
||||
|
||||
userdata_db_migrations = [SampleMigrationModel]
|
||||
PLEASE NOTE: OLDER MIGRATIONS CAN NEVER BE DELETED.
|
||||
ONLY MODIFY OLD MIGRATIONS FOR BUG FIXES OR ENHANCEMENTS ONLY
|
||||
[TRY NOT TO MODIFY BEHAVIOR, UNLESS YOU KNOW WHAT YOU'RE DOING].
|
||||
"""
|
||||
|
||||
|
||||
userdata_db_migrations = []
|
||||
|
@ -1,6 +0,0 @@
|
||||
class SampleMigrationModel:
|
||||
version = 1
|
||||
|
||||
@staticmethod
|
||||
def migrate():
|
||||
print("executing sample userdata db migration")
|
@ -3,14 +3,19 @@ Contains the functions to prepare the server for use.
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
from configparser import ConfigParser
|
||||
|
||||
from app import settings
|
||||
from app.db.sqlite import create_connection, create_tables, queries
|
||||
from app.db.store import Store
|
||||
from app.migrations import apply_migrations, set_postinit_migration_versions
|
||||
from app.migrations._preinit import (
|
||||
run_preinit_migrations,
|
||||
set_preinit_migration_versions,
|
||||
)
|
||||
from app.settings import APP_DB_PATH, USERDATA_DB_PATH
|
||||
from app.utils import get_home_res_path
|
||||
from app.migrations import apply_migrations
|
||||
|
||||
config = ConfigParser()
|
||||
|
||||
@ -102,6 +107,7 @@ def setup_sqlite():
|
||||
"""
|
||||
# if os.path.exists(DB_PATH):
|
||||
# os.remove(DB_PATH)
|
||||
run_preinit_migrations()
|
||||
|
||||
app_db_conn = create_connection(APP_DB_PATH)
|
||||
playlist_db_conn = create_connection(USERDATA_DB_PATH)
|
||||
@ -109,10 +115,15 @@ def setup_sqlite():
|
||||
create_tables(app_db_conn, queries.CREATE_APPDB_TABLES)
|
||||
create_tables(playlist_db_conn, queries.CREATE_USERDATA_TABLES)
|
||||
|
||||
create_tables(app_db_conn, queries.CREATE_MIGRATIONS_TABLE)
|
||||
create_tables(playlist_db_conn, queries.CREATE_MIGRATIONS_TABLE)
|
||||
|
||||
app_db_conn.close()
|
||||
playlist_db_conn.close()
|
||||
|
||||
apply_migrations()
|
||||
set_preinit_migration_versions()
|
||||
set_postinit_migration_versions()
|
||||
|
||||
Store.load_all_tracks()
|
||||
Store.process_folders()
|
||||
|
Loading…
x
Reference in New Issue
Block a user