diff --git a/src/tagstudio/core/library/alchemy/library.py b/src/tagstudio/core/library/alchemy/library.py index 06c3b54b..2e373416 100644 --- a/src/tagstudio/core/library/alchemy/library.py +++ b/src/tagstudio/core/library/alchemy/library.py @@ -413,7 +413,6 @@ class Library: return self.migrate_lib(library_dir, storage_path) def new_lib(self, library_dir: Path, storage_path: str) -> LibraryStatus: - is_new = True connection_string = URL.create( drivername="sqlite", database=storage_path, @@ -427,7 +426,6 @@ class Library: # Under -> sqlite-the-sqlite-dialect-now-uses-nullpool-for-file-based-databases poolclass = None if storage_path == ":memory:" else NullPool loaded_db_version: int = 0 - initial_db_version: int = DB_VERSION logger.info( "[Library] Opening SQLite Library", @@ -436,84 +434,58 @@ class Library: ) self.engine = create_engine(connection_string, poolclass=poolclass) - # Don't check DB version when creating new library - if not is_new: - loaded_db_version = self.get_version(DB_VERSION_CURRENT_KEY) - initial_db_version = self.get_version(DB_VERSION_INITIAL_KEY) - - # ======================== Library Database Version Checking ======================= - # DB_VERSION 6 is the first supported SQLite DB version. - # If the DB_VERSION is >= 100, that means it's a compound major + minor version. - # - Dividing by 100 and flooring gives the major (breaking changes) version. - # - If a DB has major version higher than the current program, don't load it. - # - If only the minor version is higher, it's still allowed to load. - if loaded_db_version < 6 or ( - loaded_db_version >= 100 and loaded_db_version // 100 > DB_VERSION // 100 - ): - mismatch_text = Translations["status.library_version_mismatch"] - found_text = Translations["status.library_version_found"] - expected_text = Translations["status.library_version_expected"] - return LibraryStatus( - success=False, - message=( - f"{mismatch_text}\n" - f"{found_text} v{loaded_db_version}, " - f"{expected_text} v{DB_VERSION}" - ), - ) - logger.info(f"[Library] Library DB version: {loaded_db_version}") make_tables(self.engine) with Session(self.engine) as session: - if is_new: - # Add default tag color namespaces. - namespaces = default_color_groups.namespaces() - try: - session.add_all(namespaces) - session.commit() - except IntegrityError as e: - logger.error("[Library] Couldn't add default tag color namespaces", error=e) - session.rollback() + # Add default tag color namespaces. + namespaces = default_color_groups.namespaces() - # Add default tag colors. - tag_colors: list[TagColorGroup] = default_color_groups.standard() - tag_colors += default_color_groups.pastels() - tag_colors += default_color_groups.shades() - tag_colors += default_color_groups.grayscale() - tag_colors += default_color_groups.earth_tones() - tag_colors += default_color_groups.neon() - if is_new: - try: - session.add_all(tag_colors) - session.commit() - except IntegrityError as e: - logger.error("[Library] Couldn't add default tag colors", error=e) - session.rollback() + # TODO: do these try excepts even make sense? Shouldn't library creation just fail + # in these cases? + try: + session.add_all(namespaces) + session.commit() + except IntegrityError as e: + logger.error("[Library] Couldn't add default tag color namespaces", error=e) + session.rollback() - # Add default tags. - tags = get_default_tags() + # Add default tag colors. + tag_colors: list[TagColorGroup] = default_color_groups.standard() + tag_colors += default_color_groups.pastels() + tag_colors += default_color_groups.shades() + tag_colors += default_color_groups.grayscale() + tag_colors += default_color_groups.earth_tones() + tag_colors += default_color_groups.neon() + + try: + session.add_all(tag_colors) + session.commit() + except IntegrityError as e: + logger.error("[Library] Couldn't add default tag colors", error=e) + session.rollback() + + # Add default tags. + tags = get_default_tags() + try: + session.add_all(tags) + session.commit() + except IntegrityError: + session.rollback() + + # Add default field templates + for template in get_default_field_templates(): try: - session.add_all(tags) + session.add(template) session.commit() except IntegrityError: + logger.info("[Library] FieldTemplate already exists", field_template=template) session.rollback() - # Add default field templates - for template in get_default_field_templates(): - try: - session.add(template) - session.commit() - except IntegrityError: - logger.info( - "[Library] FieldTemplate already exists", field_template=template - ) - session.rollback() - # Ensure version rows are present with catch_warnings(record=True): try: - initial = DB_VERSION if is_new else 100 + initial = DB_VERSION session.add(Version(key=DB_VERSION_INITIAL_KEY, value=initial)) session.commit() except IntegrityError: @@ -524,6 +496,7 @@ class Library: session.commit() except IntegrityError: session.rollback() + self.set_version(DB_VERSION_CURRENT_KEY, DB_VERSION) # check if folder matching current path exists already self.folder = session.scalar(select(Folder).where(Folder.path == library_dir)) @@ -538,56 +511,13 @@ class Library: self.folder = folder # Generate default .ts_ignore file - if is_new: - try: - ts_ignore_template = ( - Path(__file__).parents[3] / "resources/templates/ts_ignore_template.txt" - ) - shutil.copy2(ts_ignore_template, library_dir / TS_FOLDER_NAME / IGNORE_NAME) - except Exception as e: - logger.error("[ERROR][Library] Could not generate '.ts_ignore' file!", error=e) - - # Apply any post-SQL migration patches. - if not is_new: - assert loaded_db_version >= 6 - - # save backup if patches will be applied - if loaded_db_version < DB_VERSION: - self.library_dir = library_dir - self.save_library_backup_to_disk() - self.library_dir = None - - # migrate DB step by step from one version to the next - if loaded_db_version < 7: - # changes: value_type, tags - self.__apply_db7_migration(session) - if loaded_db_version < 8: - # changes: tag_colors - self.__apply_db8_migration(session) - if loaded_db_version < 9: - # changes: entries - self.__apply_db9_migration(session) - if loaded_db_version < 100: - # changes: tag_parents - self.__apply_db100_migration(session) - if loaded_db_version < 102: - # changes: tag_parents - self.__apply_db102_migration(session) - if loaded_db_version < 103: - # changes: tags - self.__apply_db103_migration(session) - if loaded_db_version < 104: - # changes: deletes preferences - self.__apply_db104_migration(session, library_dir) - if loaded_db_version < 200: - # changes: field tables - self.__apply_db200_migration(session) - if initial_db_version < 200 and loaded_db_version < 201: - # changes: field tables - self.__apply_db201_migration(session) - if loaded_db_version < 202: - # changes: tag_parents - self.__apply_db202_migration(session) + try: + ts_ignore_template = ( + Path(__file__).parents[3] / "resources/templates/ts_ignore_template.txt" + ) + shutil.copy2(ts_ignore_template, library_dir / TS_FOLDER_NAME / IGNORE_NAME) + except Exception as e: + logger.error("[ERROR][Library] Could not generate '.ts_ignore' file!", error=e) session.execute( text("CREATE INDEX IF NOT EXISTS idx_tags_name_shorthand ON tags (name, shorthand)") @@ -603,11 +533,6 @@ class Library: ) ) - # Update DB_VERSION - if loaded_db_version < DB_VERSION: - logger.info(f"[Library] Library migrated to DB version {DB_VERSION}") - self.set_version(DB_VERSION_CURRENT_KEY, DB_VERSION) - # everything is fine, set the library path self.library_dir = library_dir return LibraryStatus(success=True, library_path=library_dir) @@ -637,79 +562,34 @@ class Library: self.engine = create_engine(connection_string, poolclass=poolclass) # Don't check DB version when creating new library - if not is_new: - loaded_db_version = self.get_version(DB_VERSION_CURRENT_KEY) - initial_db_version = self.get_version(DB_VERSION_INITIAL_KEY) + loaded_db_version = self.get_version(DB_VERSION_CURRENT_KEY) + initial_db_version = self.get_version(DB_VERSION_INITIAL_KEY) - # ======================== Library Database Version Checking ======================= - # DB_VERSION 6 is the first supported SQLite DB version. - # If the DB_VERSION is >= 100, that means it's a compound major + minor version. - # - Dividing by 100 and flooring gives the major (breaking changes) version. - # - If a DB has major version higher than the current program, don't load it. - # - If only the minor version is higher, it's still allowed to load. - if loaded_db_version < 6 or ( - loaded_db_version >= 100 and loaded_db_version // 100 > DB_VERSION // 100 - ): - mismatch_text = Translations["status.library_version_mismatch"] - found_text = Translations["status.library_version_found"] - expected_text = Translations["status.library_version_expected"] - return LibraryStatus( - success=False, - message=( - f"{mismatch_text}\n" - f"{found_text} v{loaded_db_version}, " - f"{expected_text} v{DB_VERSION}" - ), - ) + # ======================== Library Database Version Checking ======================= + # DB_VERSION 6 is the first supported SQLite DB version. + # If the DB_VERSION is >= 100, that means it's a compound major + minor version. + # - Dividing by 100 and flooring gives the major (breaking changes) version. + # - If a DB has major version higher than the current program, don't load it. + # - If only the minor version is higher, it's still allowed to load. + if loaded_db_version < 6 or ( + loaded_db_version >= 100 and loaded_db_version // 100 > DB_VERSION // 100 + ): + mismatch_text = Translations["status.library_version_mismatch"] + found_text = Translations["status.library_version_found"] + expected_text = Translations["status.library_version_expected"] + return LibraryStatus( + success=False, + message=( + f"{mismatch_text}\n" + f"{found_text} v{loaded_db_version}, " + f"{expected_text} v{DB_VERSION}" + ), + ) logger.info(f"[Library] Library DB version: {loaded_db_version}") make_tables(self.engine) with Session(self.engine) as session: - if is_new: - # Add default tag color namespaces. - namespaces = default_color_groups.namespaces() - try: - session.add_all(namespaces) - session.commit() - except IntegrityError as e: - logger.error("[Library] Couldn't add default tag color namespaces", error=e) - session.rollback() - - # Add default tag colors. - tag_colors: list[TagColorGroup] = default_color_groups.standard() - tag_colors += default_color_groups.pastels() - tag_colors += default_color_groups.shades() - tag_colors += default_color_groups.grayscale() - tag_colors += default_color_groups.earth_tones() - tag_colors += default_color_groups.neon() - if is_new: - try: - session.add_all(tag_colors) - session.commit() - except IntegrityError as e: - logger.error("[Library] Couldn't add default tag colors", error=e) - session.rollback() - - # Add default tags. - tags = get_default_tags() - try: - session.add_all(tags) - session.commit() - except IntegrityError: - session.rollback() - - # Add default field templates - for template in get_default_field_templates(): - try: - session.add(template) - session.commit() - except IntegrityError: - logger.info( - "[Library] FieldTemplate already exists", field_template=template - ) - session.rollback() - # Ensure version rows are present with catch_warnings(record=True): try: @@ -737,57 +617,46 @@ class Library: session.commit() self.folder = folder - # Generate default .ts_ignore file - if is_new: - try: - ts_ignore_template = ( - Path(__file__).parents[3] / "resources/templates/ts_ignore_template.txt" - ) - shutil.copy2(ts_ignore_template, library_dir / TS_FOLDER_NAME / IGNORE_NAME) - except Exception as e: - logger.error("[ERROR][Library] Could not generate '.ts_ignore' file!", error=e) - # Apply any post-SQL migration patches. - if not is_new: - assert loaded_db_version >= 6 + assert loaded_db_version >= 6 - # save backup if patches will be applied - if loaded_db_version < DB_VERSION: - self.library_dir = library_dir - self.save_library_backup_to_disk() - self.library_dir = None + # save backup if patches will be applied + if loaded_db_version < DB_VERSION: + self.library_dir = library_dir + self.save_library_backup_to_disk() + self.library_dir = None - # migrate DB step by step from one version to the next - if loaded_db_version < 7: - # changes: value_type, tags - self.__apply_db7_migration(session) - if loaded_db_version < 8: - # changes: tag_colors - self.__apply_db8_migration(session) - if loaded_db_version < 9: - # changes: entries - self.__apply_db9_migration(session) - if loaded_db_version < 100: - # changes: tag_parents - self.__apply_db100_migration(session) - if loaded_db_version < 102: - # changes: tag_parents - self.__apply_db102_migration(session) - if loaded_db_version < 103: - # changes: tags - self.__apply_db103_migration(session) - if loaded_db_version < 104: - # changes: deletes preferences - self.__apply_db104_migration(session, library_dir) - if loaded_db_version < 200: - # changes: field tables - self.__apply_db200_migration(session) - if initial_db_version < 200 and loaded_db_version < 201: - # changes: field tables - self.__apply_db201_migration(session) - if loaded_db_version < 202: - # changes: tag_parents - self.__apply_db202_migration(session) + # migrate DB step by step from one version to the next + if loaded_db_version < 7: + # changes: value_type, tags + self.__apply_db7_migration(session) + if loaded_db_version < 8: + # changes: tag_colors + self.__apply_db8_migration(session) + if loaded_db_version < 9: + # changes: entries + self.__apply_db9_migration(session) + if loaded_db_version < 100: + # changes: tag_parents + self.__apply_db100_migration(session) + if loaded_db_version < 102: + # changes: tag_parents + self.__apply_db102_migration(session) + if loaded_db_version < 103: + # changes: tags + self.__apply_db103_migration(session) + if loaded_db_version < 104: + # changes: deletes preferences + self.__apply_db104_migration(session, library_dir) + if loaded_db_version < 200: + # changes: field tables + self.__apply_db200_migration(session) + if initial_db_version < 200 and loaded_db_version < 201: + # changes: field tables + self.__apply_db201_migration(session) + if loaded_db_version < 202: + # changes: tag_parents + self.__apply_db202_migration(session) session.execute( text("CREATE INDEX IF NOT EXISTS idx_tags_name_shorthand ON tags (name, shorthand)")