]> git.ipfire.org Git - pbs.git/commitdiff
sources: Add a page to show sources
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 20 May 2023 12:52:19 +0000 (12:52 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 20 May 2023 12:52:19 +0000 (12:52 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/buildservice/distribution.py
src/buildservice/repository.py
src/buildservice/sources.py
src/templates/distros/show.html
src/templates/sources/modules/list.html [new file with mode: 0644]
src/templates/sources/show.html [new file with mode: 0644]
src/web/__init__.py
src/web/sources.py [new file with mode: 0644]

index e7c9a2416d81f564917e7cbddbb7e030453f20fc..21220fd87074a755a1646a51f4a5ff1d2952fb21 100644 (file)
@@ -138,6 +138,7 @@ web_PYTHON = \
        src/web/packages.py \
        src/web/repos.py \
        src/web/search.py \
+       src/web/sources.py \
        src/web/ui_modules.py \
        src/web/uploads.py \
        src/web/users.py
@@ -301,6 +302,16 @@ dist_templates_repos_modules_DATA = \
 
 templates_repos_modulesdir = $(templates_reposdir)/modules
 
+dist_templates_sources_DATA = \
+       src/templates/sources/show.html
+
+templates_sourcesdir = $(templatesdir)/sources
+
+dist_templates_sources_modules_DATA = \
+       src/templates/sources/modules/list.html
+
+templates_sources_modulesdir = $(templates_sourcesdir)/modules
+
 dist_templates_packages_DATA = \
        src/templates/packages/index.html \
        src/templates/packages/name.html \
index 7f98eef7d68480f037d2d82d51cd30396b5fc931..9d2150dfb4f7dc435e06234f6cb736d24cec9fbe 100644 (file)
@@ -309,19 +309,56 @@ class Distribution(base.DataObject):
 
                return repo
 
-       @lazy_property
-       def sources(self):
-               _sources = []
+       # Builds
 
-               for source in self.db.query("SELECT id FROM sources WHERE distro_id = %s", self.id):
-                       source = sources.Source(self.pakfire, source.id)
-                       _sources.append(source)
+       def get_builds_by_name(self, name, limit=None):
+               """
+                       Returns all builds that match the name
+               """
+               builds = self.backend.builds._get_builds("""
+                       SELECT
+                               builds.*
+                       FROM
+                               repositories
+                       LEFT JOIN
+                               repository_builds ON repositories.id = repository_builds.repo_id
+                       LEFT JOIN
+                               builds ON repository_builds.build_id = builds.id
+                       LEFT JOIN
+                               packages ON builds.pkg_id = packages.id
+                       WHERE
+                               repositories.deleted IS TRUE
+                       AND
+                               repositories.distro_id = %s
+                       AND
+                               repository_builds.removed_at IS NULL
+                       AND
+                               builds.deleted_at IS NULL
+                       AND
+                               packages.name = %s
+                       ORDER BY
+                               created_at DESC
+                       LIMIT
+                               %s
+                       """, self.id, name, limit,
+               )
 
-               return sorted(_sources)
+               return builds
 
-       def get_source(self, identifier):
-               for source in self.sources:
-                       if not source.identifier == identifier:
-                               continue
+       @lazy_property
+       def sources(self):
+               sources = self.backend.sources._get_sources("""
+                       SELECT
+                               sources.*
+                       FROM
+                               sources
+                       LEFT JOIN
+                               repositories ON sources.repo_id = repositories.id
+                       WHERE
+                               repositories.distro_id = %s
+                       ORDER BY
+                               sources.name, sources.url
+                       """, self.id,
+               )
 
-                       return source
+               return list(sources)
index fbf58b1837842cb0be64ab736e2630b627be6947..e9037dc6aa4d13910b99d932dfbadc8dcf90747a 100644 (file)
@@ -499,6 +499,24 @@ class Repository(base.DataObject):
 
                return list(sources)
 
+       def get_source_by_slug(self, slug):
+               return self.backend.sources._get_source("""
+                       SELECT
+                               *
+                       FROM
+                               sources
+                       WHERE
+                               deleted_at IS NULL
+                       AND
+                               repo_id = %s
+                       AND
+                               slug = %s
+                       """, self.id, slug,
+
+                       # Prefill cache
+                       repo=self,
+               )
+
        async def fetch_sources(self):
                """
                        Fetches all sources for this repository
index ca8caff09d6aea9846d9c7b7528bf3884c62c785..d026670ef70e9e5916ef5294fc9fa011a4cd356f 100644 (file)
@@ -36,17 +36,11 @@ VALID_TAGS = (
 )
 
 class Sources(base.Object):
-       def _get_sources(self, query, *args):
-               res = self.db.query(query, *args)
-
-               for row in res:
-                       yield Source(self.backend, row.id, data=row)
-
-       def _get_source(self, query, *args):
-               res = self.db.get(query, *args)
+       def _get_sources(self, query, *args, **kwargs):
+               return self.db.fetch_many(Source, query, *args, **kwargs)
 
-               if res:
-                       return Source(self.backend, res.id, data=res)
+       def _get_source(self, query, *args, **kwargs):
+               return self.db.fetch_one(Source, query, *args, **kwargs)
 
        def get_by_id(self, id):
                return self._get_source("""
@@ -155,6 +149,10 @@ class Source(base.DataObject):
        def slug(self):
                return self.data.slug
 
+       @property
+       def distro(self):
+               return self.repo.distro
+
        # Repo
 
        @lazy_property
index 220690f54d9bdfdd253d6b62f875d5be32c1029d..34bb23956dfe51be873e3d0445de7226796522ad 100644 (file)
                        </div>
                </section>
        {% end %}
+
+       {# Sources #}
+
+       {% if distro.sources %}
+               <section class="section">
+                       <div class="container">
+                               <h4 class="title is-4">{{ _("Sources") }}</h4>
+
+                               {% module SourcesList(distro.sources) %}
+                       </div>
+               </section>
+       {% end %}
 {% end block %}
diff --git a/src/templates/sources/modules/list.html b/src/templates/sources/modules/list.html
new file mode 100644 (file)
index 0000000..f160051
--- /dev/null
@@ -0,0 +1,11 @@
+<div class="block">
+       <nav class="panel is-link">
+               {% for source in sources %}
+                       <a class="panel-block is-justify-content-space-between p-4" href="{{ source.repo.url }}/sources/{{ source.slug }}">
+                               <h5 class="title is-5">
+                                       {{ source }}
+                               </h5>
+                       </a>
+               {% end %}
+       </nav>
+</div>
diff --git a/src/templates/sources/show.html b/src/templates/sources/show.html
new file mode 100644 (file)
index 0000000..1b95d50
--- /dev/null
@@ -0,0 +1,51 @@
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Source") }} - {{ source }}{% end block %}
+
+{% block body %}
+       <section class="hero is-light">
+               <div class="hero-body">
+                       <div class="container">
+                               <nav class="breadcrumb" aria-label="breadcrumbs">
+                                       <ul>
+                                               {% if source.repo.owner %}
+                                                       <li>
+                                                               <a href="/users">{{ _("Users") }}</a>
+                                                       </li>
+                                                       <li>
+                                                               <a href="/users/{{ source.repo.owner.name }}">{{ source.repo.owner }}</a>
+                                                       </li>
+                                                       <li>
+                                                               <a href="#" disabled>{{ _("Distributions") }}</a>
+                                                       </li>
+                                                       <li>
+                                                               <a href="#" disabled>{{ source.distro }}</a>
+                                                       </li>
+                                               {% else %}
+                                                       <li>
+                                                               <a href="/distros">{{ _("Distributions") }}</a>
+                                                       </li>
+                                                       <li>
+                                                               <a href="/distros/{{ source.distro.slug }}">{{ source.distro }}</a>
+                                                       </li>
+                                               {% end %}
+                                               <li>
+                                                       <a href="#" disabled>{{ _("Repositories") }}</a>
+                                               </li>
+                                               <li>
+                                                       <a href="{{ source.repo.url }}" aria-current="page">{{ source.repo }}</a>
+                                               </li>
+                                               <li>
+                                                       <a href="#" disabled>{{ _("Sources") }}</a>
+                                               </li>
+                                               <li class="is-active">
+                                                       <a href="#" aria-current="page">{{ source }}</a>
+                                               </li>
+                                       </ul>
+                               </nav>
+
+                               <h1 class="title is-1">{{ source }}</h1>
+                       </div>
+               </div>
+       </section>
+{% end block %}
index 2d9cc0dff765a1f8fc9f27e1322474a1d13762ab..ce9168c9c5bf47d8702c7576da45bf782dd03fac 100644 (file)
@@ -25,6 +25,7 @@ from . import mirrors
 from . import packages
 from . import repos
 from . import search
+from . import sources
 from . import uploads
 from . import users
 from .handlers import *
@@ -77,6 +78,9 @@ class Application(tornado.web.Application):
                                # Repositories
                                "ReposList"          : repos.ListModule,
 
+                               # Sources
+                               "SourcesList"        : sources.ListModule,
+
                                # Users
                                "UsersList"          : users.ListModule,
                                "UserPushSubscribeButton" : users.PushSubscribeButton,
@@ -126,6 +130,8 @@ class Application(tornado.web.Application):
                                repos.EditHandler),
                        (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)/mirrorlist",
                                repos.MirrorlistHandler),
+                       (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)/sources/(?P<source_slug>[A-Za-z0-9\-]+)",
+                               sources.ShowHandler),
 
                        # Packages
                        (r"/packages", packages.IndexHandler),
@@ -188,6 +194,8 @@ class Application(tornado.web.Application):
                                repos.EditHandler),
                        (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/mirrorlist",
                                repos.MirrorlistHandler),
+                       (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/sources/(?P<source_slug>[A-Za-z0-9\-]+)",
+                               sources.ShowHandler),
 
                        # Mirrors
                        (r"/mirrors",                                    mirrors.IndexHandler),
diff --git a/src/web/sources.py b/src/web/sources.py
new file mode 100644 (file)
index 0000000..73c6eae
--- /dev/null
@@ -0,0 +1,62 @@
+###############################################################################
+#                                                                             #
+# 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/>.       #
+#                                                                             #
+###############################################################################
+
+from . import base
+from . import ui_modules
+
+class ShowHandler(base.BaseHandler):
+       def _get_source(self, distro_slug, repo_slug, source_slug, user_slug=None):
+               user = None
+
+               # Find the user
+               if user_slug:
+                       user = self.backend.users.get_by_name(user_slug)
+                       if not user:
+                               raise tornado.web.HTTPError(404, "Could not find user: %s" % user_slug)
+
+               # Find the distribution
+               distro = self.backend.distros.get_by_slug(distro_slug)
+               if not distro:
+                       raise tornado.web.HTTPError(404, "Could not find distro: %s" % distro_slug)
+
+               # Find the repository
+               if user:
+                       repo = user.get_repo(distro, repo_slug)
+               else:
+                       repo = distro.get_repo(repo_slug)
+               if not repo:
+                       raise tornado.web.HTTPError(404, "Could not find repo: %s" % repo_slug)
+
+               # Find the source
+               source = repo.get_source_by_slug(source_slug)
+               if not source:
+                       raise tornado.web.HTTPError(404, "Could not find source: %s" % source_slug)
+
+               return source
+
+       def get(self, **kwargs):
+               source = self._get_source(**kwargs)
+
+               self.render("sources/show.html", source=source)
+
+
+class ListModule(ui_modules.UIModule):
+       def render(self, sources):
+               return self.render_string("sources/modules/list.html", sources=sources)