diff options
author | Wojtek Kosior <koszko@koszko.org> | 2022-08-25 12:43:29 +0200 |
---|---|---|
committer | Wojtek Kosior <koszko@koszko.org> | 2022-09-28 12:54:53 +0200 |
commit | 503e546b2b0c9dba505a4e7940f257d41ad95f67 (patch) | |
tree | c17f245f8a826d4d385923557681ad372fb58b03 | |
parent | 4dbbb2aec204a5cccc713e2e2098d6e0a47f8cf6 (diff) | |
download | haketilo-hydrilla-503e546b2b0c9dba505a4e7940f257d41ad95f67.tar.gz haketilo-hydrilla-503e546b2b0c9dba505a4e7940f257d41ad95f67.zip |
[proxy] properly flag failed package installations in sqlite db
7 files changed, 59 insertions, 10 deletions
diff --git a/src/hydrilla/proxy/state_impl/_operations/pull_missing_files.py b/src/hydrilla/proxy/state_impl/_operations/pull_missing_files.py index 04a2910..f1e0414 100644 --- a/src/hydrilla/proxy/state_impl/_operations/pull_missing_files.py +++ b/src/hydrilla/proxy/state_impl/_operations/pull_missing_files.py @@ -81,17 +81,16 @@ def pull_missing_files( try: url = urljoin(repo_url, f'file/sha256/{sha256}') response = requests.get(url) - except: - raise state.RepoCommunicationError() - if not response.ok: + assert response.ok + + file_bytes = response.content + except: raise state.FileMissingError( repo_id = str(repo_id), sha256 = sha256 ) - file_bytes = response.content - computed_sha256 = hashlib.sha256(file_bytes).digest().hex() if computed_sha256 != sha256: raise state.FileIntegrityError( diff --git a/src/hydrilla/proxy/state_impl/base.py b/src/hydrilla/proxy/state_impl/base.py index 25fd4c5..a889e71 100644 --- a/src/hydrilla/proxy/state_impl/base.py +++ b/src/hydrilla/proxy/state_impl/base.py @@ -78,6 +78,34 @@ class PolicyTree(pattern_tree.PatternTree[policies.PolicyFactory]): return policy_tree +def mark_failed_file_installs( + cursor: sqlite3.Cursor, + file_sha256: str, + repo_id: int +) -> None: + cursor.execute( + ''' + WITH failed_items AS ( + SELECT DISTINCT + item_version_id + FROM + files AS f + JOIN file_uses AS fu USING (file_id) + JOIN item_versions_extra AS ive USING (item_version_id) + WHERE + f.sha256 = ? AND f.data IS NULL AND ive.repo_id = ? + ) + UPDATE + item_versions + SET + installed = 'F' + WHERE + item_version_id IN failed_items; + ''', + (file_sha256, repo_id) + ) + + PayloadsData = t.Mapping[st.PayloadRef, st.PayloadData] # mypy needs to be corrected: @@ -123,6 +151,15 @@ class HaketiloStateWithFields(st.HaketiloState): if start_transaction: self.current_cursor.execute('ROLLBACK TRANSACTION;') raise + except st.FileInstallationError as ex: + if start_transaction: + assert self.current_cursor is not None + mark_failed_file_installs( + cursor = self.current_cursor, + file_sha256 = ex.sha256, + repo_id = int(ex.repo_id) + ) + raise finally: self.current_cursor = None diff --git a/src/hydrilla/proxy/tables.sql b/src/hydrilla/proxy/tables.sql index 54fe3ee..2483c96 100644 --- a/src/hydrilla/proxy/tables.sql +++ b/src/hydrilla/proxy/tables.sql @@ -245,8 +245,8 @@ SELECT iv.repo_iteration_id, iv.definition, iv.active, - r.name AS repo, - ri.iteration AS repo_iteration, + r.repo_id, r.name AS repo, + ri.repo_iteration_id, 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 diff --git a/src/hydrilla/proxy/web_ui/packages.py b/src/hydrilla/proxy/web_ui/packages.py index 5172a07..1edddc0 100644 --- a/src/hydrilla/proxy/web_ui/packages.py +++ b/src/hydrilla/proxy/web_ui/packages.py @@ -179,6 +179,11 @@ def alter_package_version(mapping_version_id: str) -> werkzeug.Response: return flask.redirect(flask.url_for('.packages')) else: raise ValueError() + except st.FileInstallationError: + return show_package_version( + mapping_version_id, + {'file_installation_error': True} + ) except st.ImpossibleSituation: return show_package_version( mapping_version_id, diff --git a/src/hydrilla/proxy/web_ui/repos.py b/src/hydrilla/proxy/web_ui/repos.py index 5aa5a21..c31a0a4 100644 --- a/src/hydrilla/proxy/web_ui/repos.py +++ b/src/hydrilla/proxy/web_ui/repos.py @@ -130,9 +130,7 @@ def alter_repo(repo_id: str) -> werkzeug.Response: except st.RepoCommunicationError: return show_repo(repo_id, {'repo_communication_error': True}) except st.FileInstallationError: - # We'll add the ability to present more meaningful errors later. For now - # let's treat file errors the same as repo communication errors. - return show_repo(repo_id, {'repo_communication_error': True}) + return show_repo(repo_id, {'file_installation_error': True}) except st.RepoApiVersionUnsupported: return show_repo(repo_id, {'repo_api_version_unsupported': True}) except st.MissingItemError: 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 aa01272..4d4f1d5 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 @@ -22,6 +22,11 @@ in a proprietary work, I am not going to enforce this in court. {% extends "packages/show_single.html.jinja" %} {% block title %} {{ _('web_ui.packages.single_version.title') }} {% endblock %} {% block main_info %} + {% if file_installation_error is defined %} + <aside class="error-note"> + {{ _('web_ui.err.file_installation_error') }} + </aside> + {% endif %} {% if uninstall_disallowed is defined %} <aside class="error-note"> {{ _('web_ui.err.uninstall_disallowed') }} diff --git a/src/hydrilla/proxy/web_ui/templates/repos/show_single.html.jinja b/src/hydrilla/proxy/web_ui/templates/repos/show_single.html.jinja index b032765..baecfea 100644 --- a/src/hydrilla/proxy/web_ui/templates/repos/show_single.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/repos/show_single.html.jinja @@ -27,6 +27,11 @@ in a proprietary work, I am not going to enforce this in court. {% include 'include/checkbox_tricks_style.css.jinja' %} {% endblock %} {% block main %} + {% if file_installation_error is defined %} + <aside class="error-note"> + {{ _('web_ui.err.file_installation_error') }} + </aside> + {% endif %} {% if repo_communication_error is defined %} <aside class="error-note"> {{ _('web_ui.err.repo_communication_error') }} |