aboutsummaryrefslogtreecommitdiff
path: root/src/hydrilla/proxy/state_impl/items.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/hydrilla/proxy/state_impl/items.py')
-rw-r--r--src/hydrilla/proxy/state_impl/items.py209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/hydrilla/proxy/state_impl/items.py b/src/hydrilla/proxy/state_impl/items.py
index d312db9..010b8ca 100644
--- a/src/hydrilla/proxy/state_impl/items.py
+++ b/src/hydrilla/proxy/state_impl/items.py
@@ -39,12 +39,30 @@ import typing as t
import dataclasses as dc
from contextlib import contextmanager
+from urllib.parse import urljoin
from ... import item_infos
from .. import state as st
from . import base
+def _get_item_id(cursor: sqlite3.Cursor, item_type: str, identifier: str) \
+ -> str:
+ cursor.execute(
+ 'SELECT item_id FROM items WHERE identifier = ? AND type = ?;',
+ (identifier, item_type)
+ )
+
+ rows = cursor.fetchall()
+
+ if rows == []:
+ raise st.MissingItemError()
+
+ (item_id,), = rows
+
+ return str(item_id)
+
+
def _get_parent_item_id(cursor: sqlite3.Cursor, version_id: str) -> str:
cursor.execute(
'''
@@ -66,6 +84,7 @@ def _get_parent_item_id(cursor: sqlite3.Cursor, version_id: str) -> str:
return str(item_id)
+
def _set_installed_status(cursor: sqlite3.Cursor, id: str, new_status: str) \
-> None:
cursor.execute(
@@ -138,6 +157,71 @@ def _uninstall_version(ref: VersionRefVar) -> t.Optional[VersionRefVar]:
return ref if version_still_present else None
+def _get_file(ref: VersionRefVar, name: str, file_type: str = 'L') \
+ -> st.FileData:
+ with ref.state.cursor() as cursor:
+ cursor.execute(
+ '''
+ SELECT
+ f.data, fu.mime_type
+ FROM
+ item_versions AS iv
+ JOIN items AS i USING (item_id)
+ JOIN file_uses AS fu USING (item_version_id)
+ JOIN files AS f USING (file_id)
+ WHERE
+ (iv.item_version_id = ? AND iv.installed = 'I') AND
+ i.type = ? AND
+ (fu.name = ? AND fu.type = ?) AND
+ f.data IS NOT NULL;
+ ''',
+ (ref.id, ref.type.value[0].upper(), name, file_type)
+ )
+
+ rows = cursor.fetchall()
+
+ if rows == []:
+ raise st.MissingItemError()
+
+ (data, mime_type), = rows
+
+ return st.FileData(mime_type, name, data)
+
+
+def _get_upstream_file_url(
+ ref: VersionRefVar,
+ name: str,
+ file_type: str = 'L'
+) -> str:
+ with ref.state.cursor() as cursor:
+ cursor.execute(
+ '''
+ SELECT
+ f.sha256, r.url
+ FROM
+ item_versions AS iv
+ JOIN repo_iterations AS ri USING(repo_iteration_id)
+ JOIN repos AS r USING(repo_id)
+ JOIN file_uses AS fu USING(item_version_id)
+ JOIN files AS f USING(file_id)
+ WHERE
+ iv.item_version_id = ? AND
+ (fu.name = ? AND fu.type = ?) AND
+ r.url IS NOT NULL;
+ ''',
+ (ref.id, name, file_type)
+ )
+
+ rows = cursor.fetchall()
+
+ if rows == []:
+ raise st.MissingItemError()
+
+ (sha256, repo_url), = rows
+
+ return urljoin(repo_url, f'file/sha256/{sha256}')
+
+
@dc.dataclass(frozen=True, unsafe_hash=True)
class ConcreteMappingRef(st.MappingRef):
state: base.HaketiloStateWithFields = dc.field(hash=False, compare=False)
@@ -405,6 +489,12 @@ class ConcreteMappingStore(st.MappingStore):
return sorted(result, key=(lambda di: di.identifier))
+ def get_by_identifier(self, identifier: str) -> st.MappingRef:
+ with self.state.cursor() as cursor:
+ item_id = _get_item_id(cursor, 'M', identifier)
+
+ return ConcreteMappingRef(item_id, self.state)
+
@dc.dataclass(frozen=True, unsafe_hash=True)
class ConcreteMappingVersionRef(st.MappingVersionRef):
@@ -472,6 +562,76 @@ class ConcreteMappingVersionRef(st.MappingVersionRef):
mapping_ref.update_status(enabled, frozen, id_to_pass)
+ def get_license_file(self, name: str) -> st.FileData:
+ return _get_file(self, name, 'L')
+
+ def get_upstream_license_file_url(self, name: str) -> str:
+ return _get_upstream_file_url(self, name, 'L')
+
+ def get_required_mapping(self, identifier: str) \
+ -> 'ConcreteMappingVersionRef':
+ with self.state.cursor() as cursor:
+ cursor.execute(
+ '''
+ SELECT
+ iv2.item_version_id
+ FROM
+ item_versions AS iv1
+ JOIN resolved_required_mappings AS rrm
+ ON iv1.item_version_id =
+ rrm.requiring_mapping_id
+ JOIN item_versions AS iv2
+ ON rrm.required_mapping_id =
+ iv2.item_version_id
+ JOIN items AS i
+ ON iv2.item_id = i.item_id
+ WHERE
+ iv1.item_version_id = ? AND
+ i.identifier = ?;
+ ''',
+ (self.id, identifier)
+ )
+
+ rows = cursor.fetchall()
+
+ if rows == []:
+ raise st.MissingItemError()
+
+ (required_id,), = rows
+
+ return ConcreteMappingVersionRef(str(required_id), self.state)
+
+ def get_payload_resource(self, pattern: str, identifier: str) \
+ -> 'ConcreteResourceVersionRef':
+ with self.state.cursor() as cursor:
+ cursor.execute(
+ '''
+ SELECT
+ iv.item_version_id
+ FROM
+ payloads AS p
+ JOIN resolved_depended_resources AS rdd
+ USING(payload_id)
+ JOIN item_versions AS iv
+ ON rdd.resource_item_id = iv.item_version_id
+ JOIN items AS i
+ USING (item_id)
+ WHERE
+ (p.mapping_item_id = ? AND p.pattern = ?) AND
+ i.identifier = ?;
+ ''',
+ (self.id, pattern, identifier)
+ )
+
+ rows = cursor.fetchall()
+
+ if rows == []:
+ raise st.MissingItemError()
+
+ (resource_ver_id,), = rows
+
+ return ConcreteResourceVersionRef(str(resource_ver_id), self.state)
+
def get_item_display_info(self) -> st.RichMappingDisplayInfo:
with self._mapping_ref() as mapping_ref:
return mapping_ref.get_display_info()
@@ -578,6 +738,12 @@ class ConcreteResourceStore(st.ResourceStore):
return sorted(result, key=(lambda di: di.identifier))
+ def get_by_identifier(self, identifier: str) -> st.ResourceRef:
+ with self.state.cursor() as cursor:
+ item_id = _get_item_id(cursor, 'R', identifier)
+
+ return ConcreteResourceRef(item_id, self.state)
+
@dc.dataclass(frozen=True, unsafe_hash=True)
class ConcreteResourceVersionRef(st.ResourceVersionRef):
@@ -589,6 +755,49 @@ class ConcreteResourceVersionRef(st.ResourceVersionRef):
def uninstall(self) -> t.Optional['ConcreteResourceVersionRef']:
return _uninstall_version(self)
+ def get_license_file(self, name: str) -> st.FileData:
+ return _get_file(self, name, 'L')
+
+ def get_resource_file(self, name: str) -> st.FileData:
+ return _get_file(self, name, 'W')
+
+ def get_upstream_license_file_url(self, name: str) -> str:
+ return _get_upstream_file_url(self, name, 'L')
+
+ def get_upstream_resource_file_url(self, name: str) -> str:
+ return _get_upstream_file_url(self, name, 'W')
+
+ def get_dependency(self, identifier: str) -> st.ResourceVersionRef:
+ with self.state.cursor() as cursor:
+ cursor.execute(
+ '''
+ SELECT
+ iv.item_version_id
+ FROM
+ resolved_depended_resources AS rdd1
+ JOIN payloads AS p
+ ON rdd1.payload_id = p.payload_id
+ JOIN resolved_depended_resources AS rdd2
+ ON p.payload_id = rdd2.payload_id
+ JOIN item_versions AS iv
+ ON rdd2.resource_item_id = iv.item_version_id
+ JOIN items AS i
+ USING (item_id)
+ WHERE
+ rdd1.resource_item_id = ? AND i.identifier = ?;
+ ''',
+ (self.id, identifier)
+ )
+
+ rows = cursor.fetchall()
+
+ if rows == []:
+ raise st.MissingItemError()
+
+ (dep_id,), = rows
+
+ return ConcreteResourceVersionRef(str(dep_id), self.state)
+
def get_item_display_info(self) -> st.RichResourceDisplayInfo:
with self.state.cursor() as cursor:
resource_id = _get_parent_item_id(cursor, self.id)