summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-08-25 10:18:33 +0200
committerWojtek Kosior <koszko@koszko.org>2022-09-28 12:54:53 +0200
commitedbb8286146920583087080809f6e904ca856cc9 (patch)
tree0a7b3bf4c207707a211e66c45bafec7fab579e07
parentf1204084f5fd377e66f15b3f23e81e13a063512e (diff)
downloadhaketilo-hydrilla-edbb8286146920583087080809f6e904ca856cc9.tar.gz
haketilo-hydrilla-edbb8286146920583087080809f6e904ca856cc9.zip
[proxy] make package version info page also display other versions; fix&improve some aspects of package loading and dependency recomputing
-rw-r--r--src/hydrilla/proxy/state.py32
-rw-r--r--src/hydrilla/proxy/state_impl/_operations/load_packages.py52
-rw-r--r--src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py66
-rw-r--r--src/hydrilla/proxy/state_impl/mappings.py155
-rw-r--r--src/hydrilla/proxy/state_impl/repos.py30
-rw-r--r--src/hydrilla/proxy/tables.sql71
-rw-r--r--src/hydrilla/proxy/web_ui/packages.py34
-rw-r--r--src/hydrilla/proxy/web_ui/root.py6
-rw-r--r--src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja12
-rw-r--r--src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja36
-rw-r--r--src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja12
11 files changed, 288 insertions, 218 deletions
diff --git a/src/hydrilla/proxy/state.py b/src/hydrilla/proxy/state.py
index 0e45725..e5c7bd7 100644
--- a/src/hydrilla/proxy/state.py
+++ b/src/hydrilla/proxy/state.py
@@ -56,14 +56,10 @@ class EnabledStatus(Enum):
DISABLED - User wished to never apply given mapping.
- AUTO_ENABLED - User has not configured given mapping but it will still be
- used when automatic application of mappings is turned on.
-
NO_MARK - User has not configured given mapping and it won't be used.
"""
ENABLED = 'E'
DISABLED = 'D'
- AUTO_ENABLED = 'A'
NO_MARK = 'N'
@@ -84,6 +80,20 @@ class InstalledStatus(Enum):
FAILED_TO_INSTALL = 'F'
+class ActiveStatus(Enum):
+ """
+ REQUIRED - Mapping version got active to fulfill a requirement of some (this
+ or another) explicitly enabled mapping.
+
+ AUTO - Mapping version was activated automatically.
+
+ NOT_ACTIVE - Mapping version is not currently being used.
+ """
+ REQUIRED = 'R'
+ AUTO = 'A'
+ NOT_ACTIVE = 'N'
+
+
@dc.dataclass(frozen=True, unsafe_hash=True)
class Ref:
"""...."""
@@ -188,18 +198,17 @@ class RepoIterationRef(Ref):
@dc.dataclass(frozen=True)
class MappingDisplayInfo:
- ref: 'MappingRef'
- identifier: str
- enabled: EnabledStatus
- active_version_ref: t.Optional['MappingVersionRef']
- active_version_info: t.Optional[item_infos.MappingInfo]
+ ref: 'MappingRef'
+ identifier: str
+ enabled: EnabledStatus
+ active_version: t.Optional['MappingVersionDisplayInfo']
@dc.dataclass(frozen=True)
class MappingVersionDisplayInfo:
ref: 'MappingVersionRef'
info: item_infos.MappingInfo
installed: InstalledStatus
- is_active: bool
+ active: ActiveStatus
is_orphan: bool
is_local: bool
mapping_enabled: EnabledStatus
@@ -231,7 +240,8 @@ class MappingVersionRef(Ref):
...
@abstractmethod
- def get_display_info(self) -> MappingVersionDisplayInfo:
+ def get_all_version_display_infos(self) \
+ -> t.Sequence[MappingVersionDisplayInfo]:
...
class MappingVersionStore(Store[MappingVersionRef]):
diff --git a/src/hydrilla/proxy/state_impl/_operations/load_packages.py b/src/hydrilla/proxy/state_impl/_operations/load_packages.py
index defa9b6..76a24d1 100644
--- a/src/hydrilla/proxy/state_impl/_operations/load_packages.py
+++ b/src/hydrilla/proxy/state_impl/_operations/load_packages.py
@@ -64,18 +64,6 @@ def make_repo_iteration(cursor: sqlite3.Cursor, repo_id: int) -> int:
cursor.execute(
'''
- UPDATE
- repos
- SET
- next_iteration = ?
- WHERE
- repo_id = ?;
- ''',
- (next_iteration + 1, repo_id)
- )
-
- cursor.execute(
- '''
INSERT INTO repo_iterations(repo_id, iteration)
VALUES(?, ?);
''',
@@ -96,6 +84,30 @@ def make_repo_iteration(cursor: sqlite3.Cursor, repo_id: int) -> int:
(repo_iteration_id,), = cursor.fetchall()
+ cursor.execute(
+ '''
+ UPDATE
+ repos
+ SET
+ next_iteration = ?,
+ active_iteration_id = (
+ CASE
+ WHEN repo_id = 1 THEN NULL
+ ELSE ?
+ END
+ ),
+ last_refreshed = (
+ CASE
+ WHEN repo_id = 1 THEN NULL
+ ELSE STRFTIME('%s', 'NOW')
+ END
+ )
+ WHERE
+ repo_id = ?;
+ ''',
+ (next_iteration + 1, repo_iteration_id, repo_id)
+ )
+
return repo_iteration_id
def get_or_make_item(cursor: sqlite3.Cursor, type: str, identifier: str) -> int:
@@ -162,12 +174,9 @@ def update_or_make_item_version(
item_versions
SET
installed = (
- CASE WHEN
- installed = 'I' OR ? = 'I'
- THEN
- 'I'
- ELSE
- 'N'
+ CASE
+ WHEN installed = 'I' OR ? = 'I' THEN 'I'
+ ELSE 'N'
END
),
repo_iteration_id = ?
@@ -213,10 +222,7 @@ def update_or_make_item_version(
def make_mapping_status(cursor: sqlite3.Cursor, item_id: int) -> None:
cursor.execute(
- '''
- INSERT OR IGNORE INTO mapping_statuses(item_id, enabled, required)
- VALUES(?, 'N', FALSE);
- ''',
+ 'INSERT OR IGNORE INTO mapping_statuses(item_id) VALUES(?);',
(item_id,)
)
@@ -395,6 +401,8 @@ def _load_packages_no_state_update(
repo_id = repo_id
)
+ prune_packages(cursor)
+
_recompute_dependencies_no_state_update(
cursor = cursor,
semirepo_file_resolver = MalcontentFileResolver(malcontent_path)
diff --git a/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py b/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py
index 494d130..4b48ce8 100644
--- a/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py
+++ b/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py
@@ -51,12 +51,13 @@ def _get_infos_of_type(cursor: sqlite3.Cursor, info_type: t.Type[AnyInfoVar],) \
cursor.execute(
'''
SELECT
- i.item_id, iv.definition, r.name, ri.iteration
+ ive.item_version_id,
+ ive.definition,
+ ive.repo,
+ ive.repo_iteration
FROM
- item_versions AS iv
- JOIN items AS i USING (item_id)
- JOIN repo_iterations AS ri USING (repo_iteration_id)
- JOIN repos AS r USING (repo_id)
+ item_versions_extra AS ive
+ JOIN items AS i USING (item_id)
WHERE
i.type = ?;
''',
@@ -65,9 +66,10 @@ def _get_infos_of_type(cursor: sqlite3.Cursor, info_type: t.Type[AnyInfoVar],) \
result: dict[int, AnyInfoVar] = {}
- for item_id, definition, repo_name, repo_iteration in cursor.fetchall():
+ for item_version_id, definition, repo_name, repo_iteration \
+ in cursor.fetchall():
info = info_type.load(definition, repo_name, repo_iteration)
- result[item_id] = info
+ result[item_version_id] = info
return result
@@ -93,11 +95,8 @@ def _recompute_dependencies_no_state_update_no_pull_files(
ids_to_resources = _get_infos_of_type(cursor, item_infos.ResourceInfo)
ids_to_mappings = _get_infos_of_type(cursor, item_infos.MappingInfo)
- resources = ids_to_resources.items()
- resources_to_ids = dict((info.identifier, id) for id, info in resources)
-
- mappings = ids_to_mappings.items()
- mappings_to_ids = dict((info.identifier, id) for id, info in mappings)
+ resources_to_ids = dict((info, id) for id, info in ids_to_resources.items())
+ mappings_to_ids = dict((info, id) for id, info in ids_to_mappings.items())
requirements = [*extra_requirements]
@@ -150,17 +149,18 @@ def _recompute_dependencies_no_state_update_no_pull_files(
UPDATE
mapping_statuses
SET
- required = FALSE,
active_version_id = NULL
WHERE
enabled != 'E';
'''
)
+ cursor.execute("UPDATE item_versions SET active = 'N';")
+
cursor.execute('DELETE FROM payloads;')
for choice in mapping_choices.values():
- mapping_ver_id = mappings_to_ids[choice.info.identifier]
+ mapping_ver_id = mappings_to_ids[choice.info]
if choice.required:
_mark_version_installed(cursor, mapping_ver_id)
@@ -184,12 +184,23 @@ def _recompute_dependencies_no_state_update_no_pull_files(
UPDATE
mapping_statuses
SET
- required = ?,
active_version_id = ?
WHERE
item_id = ?;
''',
- (choice.required, mapping_ver_id, mapping_item_id)
+ (mapping_ver_id, mapping_item_id)
+ )
+
+ cursor.execute(
+ '''
+ UPDATE
+ item_versions
+ SET
+ active = ?
+ WHERE
+ item_version_id = ?;
+ ''',
+ (mapping_ver_id, 'R' if choice.required else 'A')
)
for num, (pattern, payload) in enumerate(choice.payloads.items()):
@@ -226,7 +237,7 @@ def _recompute_dependencies_no_state_update_no_pull_files(
(payload_id,), = cursor.fetchall()
for res_num, resource_info in enumerate(payload.resources):
- resource_ver_id = resources_to_ids[resource_info.identifier]
+ resource_ver_id = resources_to_ids[resource_info]
if choice.required:
_mark_version_installed(cursor, resource_ver_id)
@@ -243,6 +254,27 @@ def _recompute_dependencies_no_state_update_no_pull_files(
(payload_id, resource_ver_id, res_num)
)
+ new_status = 'R' if choice.required else 'A'
+
+ cursor.execute(
+ '''
+ UPDATE
+ item_versions
+ SET
+ active = (
+ CASE
+ WHEN active = 'R' OR ? = 'R' THEN 'R'
+ WHEN active = 'A' OR ? = 'A' THEN 'A'
+ ELSE 'N'
+ END
+ )
+ WHERE
+ item_version_id = ?;
+ ''',
+ (new_status, new_status, resource_ver_id)
+ )
+
+
def _recompute_dependencies_no_state_update(
cursor: sqlite3.Cursor,
extra_requirements: t.Iterable[sds.MappingRequirement] = (),
diff --git a/src/hydrilla/proxy/state_impl/mappings.py b/src/hydrilla/proxy/state_impl/mappings.py
index 946df14..7d08e58 100644
--- a/src/hydrilla/proxy/state_impl/mappings.py
+++ b/src/hydrilla/proxy/state_impl/mappings.py
@@ -51,19 +51,20 @@ class ConcreteMappingRef(st.MappingRef):
cursor.execute(
'''
SELECT
- item_version_id,
- definition,
- repo,
- repo_iteration,
- installed,
- is_active,
- is_orphan,
- is_local,
- enabled
+ ive.item_version_id,
+ ive.definition,
+ ive.repo,
+ ive.repo_iteration,
+ ive.installed,
+ ive.active,
+ ive.is_orphan,
+ ive.is_local,
+ ms.enabled
FROM
- mapping_display_infos
+ item_versions_extra AS ive
+ JOIN mapping_statuses AS ms USING (item_id)
WHERE
- item_id = ?;
+ ive.item_id = ?;
''',
(self.id,)
)
@@ -75,8 +76,9 @@ class ConcreteMappingRef(st.MappingRef):
result = []
- for (item_version_id, definition, repo, repo_iteration, installed,
- is_active, is_orphan, is_local, status_letter) in rows:
+ for (item_version_id, definition, repo, repo_iteration,
+ installed_status, active_status, is_orphan, is_local,
+ enabled_status) in rows:
ref = ConcreteMappingVersionRef(str(item_version_id), self.state)
item_info = item_infos.MappingInfo.load(
@@ -88,11 +90,11 @@ class ConcreteMappingRef(st.MappingRef):
display_info = st.MappingVersionDisplayInfo(
ref = ref,
info = item_info,
- installed = st.InstalledStatus(installed),
- is_active = is_active,
+ installed = st.InstalledStatus(installed_status),
+ active = st.ActiveStatus(active_status),
is_orphan = is_orphan,
is_local = is_local,
- mapping_enabled = st.EnabledStatus(status_letter)
+ mapping_enabled = st.EnabledStatus(enabled_status)
)
result.append(display_info)
@@ -104,22 +106,31 @@ class ConcreteMappingStore(st.MappingStore):
state: base.HaketiloStateWithFields
def get(self, id: str) -> st.MappingRef:
- return ConcreteMappingRef(id, self.state)
+ return ConcreteMappingRef(str(int(id)), self.state)
def get_display_infos(self) -> t.Sequence[st.MappingDisplayInfo]:
with self.state.cursor() as cursor:
cursor.execute(
'''
- SELECT DISTINCT
- item_id,
- identifier,
- CASE WHEN is_active THEN item_version_id ELSE NULL END,
- CASE WHEN is_active THEN definition ELSE NULL END,
- CASE WHEN is_active THEN repo ELSE NULL END,
- CASE WHEN is_active THEN repo_iteration ELSE NULL END,
- enabled
+ SELECT
+ i.item_id,
+ i.identifier,
+ ive.item_version_id,
+ ive.definition,
+ ive.repo,
+ ive.repo_iteration,
+ ive.installed,
+ ive.active,
+ ive.is_orphan,
+ ive.is_local,
+ ms.enabled
FROM
- mapping_display_infos;
+ items AS i
+ JOIN mapping_statuses AS ms
+ USING (item_id)
+ LEFT JOIN item_versions_extra AS ive
+ ON ms.active_version_id = ive.item_version_id AND
+ ive.active IN ('R', 'A');
'''
)
@@ -128,34 +139,45 @@ class ConcreteMappingStore(st.MappingStore):
result = []
for (item_id, identifier, item_version_id, definition, repo,
- repo_iteration, status_letter) in rows:
+ repo_iteration, installed_status, active_status, is_orphan,
+ is_local, enabled_status) in rows:
ref = ConcreteMappingRef(str(item_id), self.state)
- active_version_ref: t.Optional[st.MappingVersionRef] = None
- item_info: t.Optional[item_infos.MappingInfo] = None
+ active_version: t.Optional[st.MappingVersionDisplayInfo] = None
if item_version_id is not None:
active_version_ref = ConcreteMappingVersionRef(
id = str(item_version_id),
state = self.state
)
- item_info = item_infos.MappingInfo.load(
+
+ active_version_info = item_infos.MappingInfo.load(
definition,
repo,
repo_iteration
)
+ active_version = st.MappingVersionDisplayInfo(
+ ref = active_version_ref,
+ info = active_version_info,
+ installed = st.InstalledStatus(installed_status),
+ active = st.ActiveStatus(active_status),
+ is_orphan = is_orphan,
+ is_local = is_local,
+ mapping_enabled = st.EnabledStatus(enabled_status)
+ )
+
+
display_info = st.MappingDisplayInfo(
- ref = ref,
- identifier = identifier,
- enabled = st.EnabledStatus(status_letter),
- active_version_ref = active_version_ref,
- active_version_info = item_info
+ ref = ref,
+ identifier = identifier,
+ enabled = st.EnabledStatus(enabled_status),
+ active_version = active_version
)
result.append(display_info)
- return result
+ return sorted(result, key=(lambda di: di.identifier))
@dc.dataclass(frozen=True, unsafe_hash=True)
@@ -181,9 +203,26 @@ class ConcreteMappingVersionRef(st.MappingVersionRef):
def install(self) -> None:
with self.state.cursor(transaction=True) as cursor:
- info = self.get_display_info()
+ cursor.execute(
+ '''
+ SELECT
+ installed
+ FROM
+ item_versions
+ WHERE
+ item_version_id = ?;
+ ''',
+ (self.id,)
+ )
+
+ rows = cursor.fetchall()
+
+ if rows == []:
+ raise st.MissingItemError()
+
+ (installed_status,), = rows
- if info.installed == st.InstalledStatus.INSTALLED:
+ if installed_status == 'I':
return
self._set_installed_status(cursor, st.InstalledStatus.INSTALLED)
@@ -204,21 +243,15 @@ class ConcreteMappingVersionRef(st.MappingVersionRef):
#
# ....
- def get_display_info(self) -> st.MappingVersionDisplayInfo:
+ def get_all_version_display_infos(self) \
+ -> t.Sequence[st.MappingVersionDisplayInfo]:
with self.state.cursor() as cursor:
cursor.execute(
'''
SELECT
- definition,
- repo,
- repo_iteration,
- installed,
- is_orphan,
- is_active,
- is_local,
- enabled
+ item_id
FROM
- mapping_display_infos
+ item_versions
WHERE
item_version_id = ?;
''',
@@ -226,28 +259,14 @@ class ConcreteMappingVersionRef(st.MappingVersionRef):
)
rows = cursor.fetchall()
+ if rows == []:
+ raise st.MissingItemError()
- if rows == []:
- raise st.MissingItemError()
-
- (definition, repo, repo_iteration, installed, is_orphan, is_active,
- is_local, status_letter), = rows
+ (mapping_id,), = rows
- item_info = item_infos.MappingInfo.load(
- definition,
- repo,
- repo_iteration
- )
+ mapping_ref = ConcreteMappingRef(str(mapping_id), self.state)
- return st.MappingVersionDisplayInfo(
- ref = self,
- info = item_info,
- installed = st.InstalledStatus(installed),
- is_active = is_active,
- is_orphan = is_orphan,
- is_local = is_local,
- mapping_enabled = st.EnabledStatus(status_letter)
- )
+ return mapping_ref.get_version_display_infos()
@dc.dataclass(frozen=True)
@@ -255,4 +274,4 @@ class ConcreteMappingVersionStore(st.MappingVersionStore):
state: base.HaketiloStateWithFields
def get(self, id: str) -> st.MappingVersionRef:
- return ConcreteMappingVersionRef(id, self.state)
+ return ConcreteMappingVersionRef(str(int(id)), self.state)
diff --git a/src/hydrilla/proxy/state_impl/repos.py b/src/hydrilla/proxy/state_impl/repos.py
index d4fbbce..346e113 100644
--- a/src/hydrilla/proxy/state_impl/repos.py
+++ b/src/hydrilla/proxy/state_impl/repos.py
@@ -202,17 +202,11 @@ class ConcreteRepoRef(st.RepoRef):
cursor.execute(
'''
SELECT
- iv.definition, r.name, ri.iteration
+ definition, repo, repo_iteration
FROM
- mapping_statuses AS ms
- JOIN item_versions AS iv
- ON ms.active_version_id = iv.item_version_id
- JOIN repo_iterations AS ri
- USING (repo_iteration_id)
- JOIN repos AS r
- USING (repo_id)
+ item_versions_extra
WHERE
- ms.required
+ active = 'R';
'''
)
@@ -288,18 +282,6 @@ class ConcreteRepoRef(st.RepoRef):
self.state.rebuild_structures()
- cursor.execute(
- '''
- UPDATE
- repos
- SET
- last_refreshed = STRFTIME('%s', 'NOW')
- WHERE
- repo_id = ?;
- ''',
- (self.id,)
- )
-
return ConcreteRepoIterationRef(str(new_iteration_id), self.state)
def get_display_info(self) -> st.RepoDisplayInfo:
@@ -332,7 +314,7 @@ class ConcreteRepoStore(st.RepoStore):
state: base.HaketiloStateWithFields
def get(self, id: str) -> st.RepoRef:
- return ConcreteRepoRef(id, self.state)
+ return ConcreteRepoRef(str(int(id)), self.state)
def add(self, name: str, url: str) -> st.RepoRef:
name = name.strip()
@@ -360,8 +342,8 @@ class ConcreteRepoStore(st.RepoStore):
cursor.execute(
'''
- INSERT INTO repos(name, url, deleted, next_iteration)
- VALUES (?, ?, FALSE, 1)
+ INSERT INTO repos(name, url)
+ VALUES (?, ?)
ON CONFLICT (name)
DO UPDATE SET
name = excluded.name,
diff --git a/src/hydrilla/proxy/tables.sql b/src/hydrilla/proxy/tables.sql
index 863c989..918c1f1 100644
--- a/src/hydrilla/proxy/tables.sql
+++ b/src/hydrilla/proxy/tables.sql
@@ -68,8 +68,8 @@ CREATE TABLE repos(
name VARCHAR NOT NULL,
url VARCHAR NOT NULL,
- deleted BOOLEAN NOT NULL,
- next_iteration INTEGER NOT NULL,
+ deleted BOOLEAN NOT NULL DEFAULT FALSE,
+ next_iteration INTEGER NOT NULL DEFAULT 1,
active_iteration_id INTEGER NULL,
last_refreshed INTEGER NULL,
@@ -93,8 +93,8 @@ CREATE TABLE repos(
ON DELETE SET NULL
);
-INSERT INTO repos(repo_id, name, url, deleted, next_iteration)
-VALUES(1, '', '', TRUE, 1);
+INSERT INTO repos(repo_id, name, url, deleted)
+VALUES(1, '', '', TRUE);
CREATE TABLE repo_iterations(
repo_iteration_id INTEGER PRIMARY KEY,
@@ -139,30 +139,22 @@ CREATE TABLE mapping_statuses(
-- "enabled" determines whether mapping's status is ENABLED,
-- DISABLED or NO_MARK.
- enabled CHAR(1) NOT NULL,
+ enabled CHAR(1) NOT NULL DEFAULT 'N',
-- "frozen" determines whether an enabled mapping is to be kept in its
-- EXACT_VERSION, is to be updated only with versions from the same
-- REPOSITORY or is NOT_FROZEN at all.
frozen CHAR(1) NULL,
- -- The last 2 fields defined below shall be updated when dependency tree
- -- is recomputed.
- -- When "required" is TRUE, the mapping is assumed to either be enabled
- -- or be (directly or indirectly) required by another mapping which is
- -- enabled (i.e. has "enabled" set to 'E').
- required BOOLEAN NOT NULL,
-- Only one version of a mapping is allowed to be active at any time.
-- "active_version_id" indicates which version it is. Only a mapping
-- version referenced by "active_version_id" is allowed to have rows
-- in the "payloads" table reference it.
+ -- "active_version_id" shall be updated every time dependency tree is
+ -- recomputed.
active_version_id INTEGER NULL,
CHECK (enabled IN ('E', 'D', 'N')),
CHECK ((frozen IS NULL) = (enabled != 'E')),
CHECK (frozen IS NULL OR frozen in ('E', 'R', 'N')),
- CHECK (enabled != 'E' OR required),
- CHECK (enabled != 'D' OR NOT required),
- CHECK (not required OR active_version_id IS NOT NULL),
- CHECK (enabled != 'D' OR active_version_id IS NULL),
FOREIGN KEY (item_id)
REFERENCES items (item_id)
@@ -189,11 +181,18 @@ CREATE TABLE item_versions(
repo_iteration_id INTEGER NOT NULL,
definition BLOB NOT NULL,
definition_sha256 CHAR(64) NOT NULL,
+ -- "active" determines whether a version of this mapping is active
+ -- because it is REQUIRED, has been AUTO activated or is NOT_ACTIVE.
+ -- "active" shall be updated every time dependency tree is recomputed.
+ -- It shall be set to NOT_ACTIVE if and only if given row does not
+ -- correspond to "active_version_id" of any row in "mapping_statuses".
+ active CHAR(1) NOT NULL DEFAULT 'N',
UNIQUE (item_id, version, repo_iteration_id),
-- Constraint below needed to allow foreign key from "mapping_statuses".
UNIQUE (item_version_id, item_id),
CHECK (installed in ('I', 'N', 'F')),
+ CHECK (active in ('R', 'A', 'N')),
FOREIGN KEY (item_id)
REFERENCES items (item_id),
@@ -236,35 +235,25 @@ CREATE TABLE payloads(
ON DELETE CASCADE
);
-CREATE VIEW mapping_display_infos
+CREATE VIEW item_versions_extra
AS
SELECT
- i.item_id, i.identifier,
- CASE WHEN
- ms.enabled = 'N' AND
- COALESCE(ms.active_version_id, -1) = iv.item_version_id
- THEN
- 'A' -- AUTO_ENABLED mapping
- ELSE
- ms.enabled
- END AS enabled,
- iv.item_version_id, iv.definition, iv.installed,
- r.name AS repo,
- ri.iteration AS repo_iteration,
- COALESCE(r.active_iteration_id, -1) != ri.repo_iteration_id AND
- r.repo_id != 1 AS is_orphan,
- r.repo_id = 1 AS is_local,
- COALESCE(ms.active_version_id, -1) = iv.item_version_id AS is_active
+ iv.item_version_id,
+ iv.item_id,
+ iv.version,
+ iv.installed,
+ iv.repo_iteration_id,
+ iv.definition,
+ iv.active,
+ r.name AS repo,
+ ri.iteration AS repo_iteration,
+ COALESCE(r.active_iteration_id, -1) != ri.repo_iteration_id AND r.repo_id != 1
+ AS is_orphan,
+ r.repo_id = 1 AS is_local
FROM
- items AS i
- JOIN mapping_statuses AS ms
- USING (item_id)
- JOIN item_versions AS iv
- USING (item_id)
- JOIN repo_iterations AS ri
- USING (repo_iteration_id)
- JOIN repos AS r
- USING (repo_id);
+ item_versions AS iv
+ JOIN repo_iterations AS ri USING (repo_iteration_id)
+ JOIN repos AS r USING (repo_id);
CREATE TABLE resolved_depended_resources(
payload_id INTEGER,
diff --git a/src/hydrilla/proxy/web_ui/packages.py b/src/hydrilla/proxy/web_ui/packages.py
index ac8b480..e14c1fd 100644
--- a/src/hydrilla/proxy/web_ui/packages.py
+++ b/src/hydrilla/proxy/web_ui/packages.py
@@ -42,6 +42,7 @@ import werkzeug
from ...exceptions import HaketiloException
from ...translations import smart_gettext as _
+from ... import item_infos
from .. import state as st
from . import _app
@@ -109,17 +110,17 @@ def show_package(mapping_id: str) -> werkzeug.Response:
mapping_ref = store.get(str(mapping_id))
version_display_infos = mapping_ref.get_version_display_infos()
- active_list = [info for info in version_display_infos if info.is_active]
+ active_version: t.Optional[st.MappingVersionDisplayInfo] = None
- active_version_ref = None if active_list == [] else active_list[0].ref
- active_version_info = None if active_list == [] else active_list[0].info
+ for info in version_display_infos:
+ if info.active != st.ActiveStatus.NOT_ACTIVE:
+ active_version = info
display_info = st.MappingDisplayInfo(
- ref = mapping_ref,
- identifier = version_display_infos[0].info.identifier,
- enabled = version_display_infos[0].mapping_enabled,
- active_version_ref = active_version_ref,
- active_version_info = active_version_info
+ ref = mapping_ref,
+ identifier = version_display_infos[0].info.identifier,
+ enabled = version_display_infos[0].mapping_enabled,
+ active_version = active_version
)
html = flask.render_template(
@@ -138,11 +139,24 @@ def show_package_version(
) -> werkzeug.Response:
try:
store = _app.get_haketilo_state().mapping_version_store()
- display_info = store.get(mapping_version_id).get_display_info()
+ version_ref = store.get(mapping_version_id)
+ display_infos = version_ref.get_all_version_display_infos()
+
+ other_infos: list[st.MappingVersionDisplayInfo] = []
+ this_info: t.Optional[st.MappingVersionDisplayInfo] = None
+
+ for info in display_infos:
+ if info.ref == version_ref:
+ this_info = info
+ else:
+ other_infos.append(info)
+
+ assert this_info is not None
html = flask.render_template(
'packages/show_single_version.html.jinja',
- display_info = display_info,
+ display_info = this_info,
+ version_display_infos = other_infos,
**errors
)
return flask.make_response(html, 200)
diff --git a/src/hydrilla/proxy/web_ui/root.py b/src/hydrilla/proxy/web_ui/root.py
index c3e0c80..a6e3151 100644
--- a/src/hydrilla/proxy/web_ui/root.py
+++ b/src/hydrilla/proxy/web_ui/root.py
@@ -76,14 +76,16 @@ class WebUIAppImpl(_app.WebUIApp):
'autoescape': jinja2.select_autoescape(['html.jinja']),
'extensions': [
*self.jinja_options.get('extensions', []),
- 'jinja2.ext.i18n'
+ 'jinja2.ext.i18n',
+ 'jinja2.ext.do'
]
}
self.jinja_env.globals['versions'] = versions
self.jinja_env.globals['get_current_endpoint'] = get_current_endpoint
- self.jinja_env.globals['InstalledStatus'] = st.InstalledStatus
self.jinja_env.globals['EnabledStatus'] = st.EnabledStatus
+ self.jinja_env.globals['InstalledStatus'] = st.InstalledStatus
+ self.jinja_env.globals['ActiveStatus'] = st.ActiveStatus
self.before_request(authenticate_by_referrer)
diff --git a/src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja b/src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja
index bac774e..cbdd3d9 100644
--- a/src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja
+++ b/src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja
@@ -35,11 +35,15 @@ in a proprietary work, I am not going to enforce this in court.
<div>
{{ info.identifier }}
</div>
- {% if info.active_version_ref is not none %}
+ {%-
+ if info.active_version is not none and
+ info.active_version.active == ActiveStatus.REQUIRED
+ %}
+ {%- set ver = info.active_version.info.version %}
+ {%- set ver_str = versions.version_string(ver) %}
+ {%- set ver_desc = ver_str + '@' + info.active_version.info.repo %}
<div class="small-print">
- {{ versions.version_string(info.active_version_info.version) }}
- @
- {{ info.active_version_info.repo }}
+ {{ _('web_ui.packages.enabled_version_{}').format(ver_desc) }}
</div>
{% endif %}
</a>
diff --git a/src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja b/src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja
index 17f958c..e362fa9 100644
--- a/src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja
+++ b/src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja
@@ -27,22 +27,32 @@ in a proprietary work, I am not going to enforce this in court.
{% include 'include/item_list_style.css.jinja' %}
{% endblock %}
{% block main %}
- <h3>
- {{
- _('web_ui.packages.single.heading.name_{}')
- .format(display_info.identifier)
- }}
- </h3>
- TODO: add more info...
- <h4>{{ _('web_ui.packages.single.version_list_heading') }}</h4>
+ {% block main_info %}
+ <h3>
+ {{
+ _('web_ui.packages.single.heading.name_{}')
+ .format(display_info.identifier)
+ }}
+ </h3>
+ TODO: add more info...
+ {% endblock %}
+ <h4>
+ {% if version_display_infos|length > 0 %}
+ {% block version_list_heading %}
+ {{ _('web_ui.packages.single.version_list_heading') }}
+ {% endblock %}
+ {% endif %}
+ </h4>
<ul id="item_list">
{%- for info in version_display_infos %}
- {% if info.info.repo == '<local>' -%}
- {%- set entry_classes = 'version-entry-local' -%}
- {%- else -%}
- {%- set entry_classes = '' -%}
+ {%- set entry_classes = [] %}
+ {% if info.is_local %}
+ {%- do entry_classes.append('version-entry-local') %}
{%- endif %}
- <li class="{{ entry_classes }}">
+ {%- if info.is_orphan %}
+ {%- do entry_classes.append('version-entry-orphan') %}
+ {%- endif %}
+ <li class="{{ entry_classes|join(' ') }}">
{%-
set href = url_for(
'.show_package_version',
diff --git a/src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja b/src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja
index 1b46da7..9943521 100644
--- a/src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja
+++ b/src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja
@@ -19,12 +19,9 @@ I, Wojtek Kosior, thereby promise not to sue for violation of this
file's licenses. Although I request that you do not make use this code
in a proprietary work, I am not going to enforce this in court.
#}
-{% extends "base.html.jinja" %}
+{% extends "packages/show_single.html.jinja" %}
{% block title %} {{ _('web_ui.packages.single_version.title') }} {% endblock %}
-{% block style %}
- {{ super() }}
-{% endblock %}
-{% block main %}
+{% block main_info %}
{%- if uninstall_disallowed is defined %}
<aside class="error-note">
{{ _('web_ui.err.uninstall_disallowed') }}
@@ -86,4 +83,7 @@ in a proprietary work, I am not going to enforce this in court.
</form>
</div>
{%- endif %}
-{%- endblock %}
+{%- endblock main_info %}
+{% block version_list_heading %}
+ {{ _('web_ui.packages.single_version.version_list_heading') }}
+{% endblock %}