From 00487547c4aff6bf0c94438768191960a3369365 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 27 Sep 2022 13:42:55 +0200 Subject: [proxy] facilitate manually pruning orphaned packages (including installed ones) --- .../proxy/state_impl/_operations/prune_orphans.py | 82 +++++++++++++--------- src/hydrilla/proxy/state_impl/base.py | 2 +- src/hydrilla/proxy/state_impl/concrete_state.py | 28 +++++++- src/hydrilla/proxy/state_impl/items.py | 2 +- src/hydrilla/proxy/state_impl/repos.py | 2 +- 5 files changed, 78 insertions(+), 38 deletions(-) (limited to 'src/hydrilla/proxy/state_impl') diff --git a/src/hydrilla/proxy/state_impl/_operations/prune_orphans.py b/src/hydrilla/proxy/state_impl/_operations/prune_orphans.py index 7123047..5eb8cf7 100644 --- a/src/hydrilla/proxy/state_impl/_operations/prune_orphans.py +++ b/src/hydrilla/proxy/state_impl/_operations/prune_orphans.py @@ -37,37 +37,52 @@ import sqlite3 from pathlib import Path -_remove_item_versions_sqls = [ - ''' - CREATE TEMPORARY TABLE __removed_versions( - item_version_id INTEGER PRIMARY KEY - ); - ''', ''' - INSERT INTO - __removed_versions - SELECT - iv.item_version_id - FROM - item_versions AS iv - JOIN orphan_iterations AS oi USING (repo_iteration_id) - WHERE - iv.installed != 'I'; - ''', ''' - UPDATE - mapping_statuses - SET - active_version_id = NULL - WHERE - active_version_id IN __removed_versions; - ''', ''' - DELETE FROM - item_versions - WHERE - item_version_id IN __removed_versions; - ''', ''' - DROP TABLE __removed_versions; - ''' -] +def _remove_item_versions(cursor: sqlite3.Cursor, with_installed: bool) -> None: + cursor.execute( + ''' + CREATE TEMPORARY TABLE __removed_versions( + item_version_id INTEGER PRIMARY KEY + ); + ''' + ) + + condition = "iv.active != 'R'" if with_installed else "iv.installed != 'I'" + + cursor.execute( + f''' + INSERT INTO + __removed_versions + SELECT + iv.item_version_id + FROM + item_versions AS iv + JOIN orphan_iterations AS oi USING (repo_iteration_id) + WHERE + {condition}; + ''' + ) + + cursor.execute( + ''' + UPDATE + mapping_statuses + SET + active_version_id = NULL + WHERE + active_version_id IN __removed_versions; + ''' + ) + + cursor.execute( + ''' + DELETE FROM + item_versions + WHERE + item_version_id IN __removed_versions; + ''' + ) + + cursor.execute('DROP TABLE __removed_versions;') _remove_items_sql = ''' WITH removed_items AS ( @@ -159,11 +174,10 @@ WHERE repo_id IN removed_repos; ''' -def prune_orphans(cursor: sqlite3.Cursor) -> None: +def prune_orphans(cursor: sqlite3.Cursor, aggressive: bool = False) -> None: assert cursor.connection.in_transaction - for sql in _remove_item_versions_sqls: - cursor.execute(sql) + _remove_item_versions(cursor, with_installed=aggressive) cursor.execute(_remove_items_sql) cursor.execute(_remove_files_sql) cursor.execute(_forget_files_data_sql) diff --git a/src/hydrilla/proxy/state_impl/base.py b/src/hydrilla/proxy/state_impl/base.py index d603504..d99feab 100644 --- a/src/hydrilla/proxy/state_impl/base.py +++ b/src/hydrilla/proxy/state_impl/base.py @@ -227,7 +227,7 @@ class HaketiloStateWithFields(st.HaketiloState): ... @abstractmethod - def prune_orphans(self) -> None: + def soft_prune_orphan_items(self) -> None: ... @abstractmethod diff --git a/src/hydrilla/proxy/state_impl/concrete_state.py b/src/hydrilla/proxy/state_impl/concrete_state.py index 04bb67f..d8706e8 100644 --- a/src/hydrilla/proxy/state_impl/concrete_state.py +++ b/src/hydrilla/proxy/state_impl/concrete_state.py @@ -146,7 +146,33 @@ class ConcreteHaketiloState(base.HaketiloStateWithFields): self.rebuild_structures(rules=False) - def prune_orphans(self) -> None: + def count_orphan_items(self) -> st.OrphanItemsStats: + with self.cursor() as cursor: + cursor.execute( + ''' + SELECT + COALESCE(SUM(i.type = 'M'), 0), + COALESCE(SUM(i.type = 'R'), 0) + FROM + item_versions AS iv + JOIN items AS i USING (item_id) + JOIN orphan_iterations AS oi USING (repo_iteration_id) + WHERE + iv.active != 'R'; + ''' + ) + + (orphan_mappings, orphan_resources), = cursor.fetchall() + + return st.OrphanItemsStats(orphan_mappings, orphan_resources) + + def prune_orphan_items(self) -> None: + with self.cursor(transaction=True) as cursor: + _operations.prune_orphans(cursor, aggressive=True) + + self.recompute_dependencies() + + def soft_prune_orphan_items(self) -> None: with self.cursor() as cursor: assert self.connection.in_transaction diff --git a/src/hydrilla/proxy/state_impl/items.py b/src/hydrilla/proxy/state_impl/items.py index e9cabb5..d312db9 100644 --- a/src/hydrilla/proxy/state_impl/items.py +++ b/src/hydrilla/proxy/state_impl/items.py @@ -124,7 +124,7 @@ def _uninstall_version(ref: VersionRefVar) -> t.Optional[VersionRefVar]: _set_installed_status(cursor, ref.id, 'N') - ref.state.prune_orphans() + ref.state.soft_prune_orphan_items() if active_status != 'N': ref.state.recompute_dependencies() diff --git a/src/hydrilla/proxy/state_impl/repos.py b/src/hydrilla/proxy/state_impl/repos.py index 998548e..85117c8 100644 --- a/src/hydrilla/proxy/state_impl/repos.py +++ b/src/hydrilla/proxy/state_impl/repos.py @@ -194,7 +194,7 @@ class ConcreteRepoRef(st.RepoRef): (self.id,) ) - self.state.prune_orphans() + self.state.soft_prune_orphan_items() self.state.recompute_dependencies() def update( -- cgit v1.2.3