## Logging stuff
- def get_log(self, limit=None):
+ @property
+ def events(self):
res = self.db.query("""
WITH events AS (
-- Build creation times
SELECT
- builds.id AS build_id,
+ builds.id AS build,
builds.created_at AS t,
- 'created'::text AS event,
- builds.owner_id AS by_user_id
+ 'build-created'::text AS type,
+ builds.owner_id AS by_user
FROM
builds
UNION ALL
SELECT
- builds.id AS build_id,
+ builds.id AS build,
builds.finished_at AS t,
CASE
WHEN builds.failed IS TRUE
- THEN 'failed'::text
- ELSE 'finished'::text
- END AS event,
- NULL AS by_user_id
+ THEN 'build-failed'::text
+ ELSE 'build-finished'::text
+ END AS type,
+ NULL AS by_user
FROM
builds
WHERE
FROM
events
WHERE
- build_id = %s
+ build = %s
ORDER BY
t DESC""",
self.id,
)
- return res # XXX automatically expand all those IDs
+ return self.backend.events.expand(res)
def get_log(self, comments=True, repo=True, limit=None):
entries = []
--- /dev/null
+#!/usr/bin/python3
+###############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2022 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+import logging
+
+from . import base
+
+log = logging.getLogger("pakfire.events")
+
+from .decorators import *
+
+class Events(base.Object):
+ @lazy_property
+ def map(self):
+ return {
+ # Builds
+ "build" : self.backend.builds.get_by_id,
+
+ # Users
+ "by_user" : self.backend.users.get_by_id,
+ }
+
+ def expand(self, events):
+ """
+ Expands any log events
+ """
+ cache = {}
+
+ for event in events:
+ # Replace any mappable attributes
+ for attribute in event:
+ # Check if we are dealing with a mapped attribute
+ try:
+ expand = self.map[attribute]
+ except KeyError as e:
+ log.debug("Could not map attribute '%s'" % attribute)
+ continue
+
+ # Fetch attribute value
+ key = event[attribute]
+
+ # Skip everything that is None
+ if key is None:
+ continue
+
+ # Lookup the cache
+ try:
+ value = cache[attribute][key]
+
+ # Call the expand function on cache miss
+ except KeyError:
+ value = expand(key)
+
+ # Store the expanded value
+ try:
+ cache[attribute][key] = value
+ except KeyError:
+ cache[attribute] = { key : value }
+
+ # Replace original value with the expanded one
+ event[attribute] = value
+
+ yield Event(self.backend, event)
+
+
+class Event(base.Object):
+ def init(self, data):
+ self.data = data
+
+ # Read some useful attributes
+ try:
+ self.type = self.data.type
+ self.t = self.data.t
+ except AttributeError as e:
+ log.error("Could not read event: %s" % e)
+ raise e
+
+ def __repr__(self):
+ return "<%s %s>" % (self.__class__.__name__, self.type)