return builds
+ def get_changelog(self, name, public=None, limit=5, offset=0):
+ query = "SELECT builds.* FROM builds \
+ JOIN packages ON builds.pkg_id = packages.id \
+ WHERE \
+ builds.type = %s \
+ AND \
+ packages.name = %s"
+ args = ["release", name,]
+
+ if public == True:
+ query += " AND builds.public = %s"
+ args.append("Y")
+ elif public == False:
+ query += " AND builds.public = %s"
+ args.append("N")
+
+ query += " ORDER BY builds.time_created DESC"
+
+ if limit:
+ if offset:
+ query += " LIMIT %s,%s"
+ args += [offset, limit]
+ else:
+ query += " LIMIT %s"
+ args.append(limit)
+
+ builds = []
+ for b in self.db.query(query, *args):
+ b = Build(self.pakfire, b.id, b)
+ builds.append(b)
+
+ builds.sort(reverse=True)
+
+ return builds
+
class Build(base.Object):
def __init__(self, pakfire, id, data=None):
def message(self):
return self.data.body.strip()
+ @property
+ def message_full(self):
+ msg = [self.subject, ""] + self.message.splitlines()
+
+ return "\n".join(msg)
+
@property
def date(self):
return self.data.date
--- /dev/null
+<li class="media">
+ <div class="media-body">
+ <h4>
+ <a href="/build/{{ build.uuid }}">{{ build.name }}</a>
+
+ <small>
+ {{ locale.format_date(build.created) }}
+
+ {% if build.repo %}
+ {% if build.repo.type == "stable" %}
+ <span class="text-success pull-right">{{ _("Stable") }}</span>
+ {% elif build.repo.type == "unstable" %}
+ <span class="text-warning pull-right">{{ _("Unstable") }}</span>
+ {% elif build.repo.type == "testing" %}
+ <span class="text-error pull-right">{{ _("Testing") }}</span>
+ {% end %}
+ {% end %}
+ </small>
+ </h4>
+
+ {% if build.commit %}
+ {% module Text(build.commit.message_full) %}
+
+ <p class="muted pull-right">
+ {{ _("Author") }} {% module Maintainer(build.commit.author) %}
+ ‐
+ {{ _("Commit") }} <a href="/distro/{{ build.distro.identifier }}/source/{{ build.pkg.commit.source.identifier }}/{{ build.pkg.commit.revision }}">{{ build.pkg.commit.revision[:7] }}</a>
+ </p>
+ {% else %}
+ <p class="muted">
+ {{ _("No commit message.") }}
+ </p>
+ {% end %}
+ </div>
+</li>
--- /dev/null
+<ul class="media-list">
+ {% for b in builds %}
+ {% module ChangelogEntry(b) %}
+ {% end %}
+</ul>
</div>
</div>
- <div class="row">
- <div class="span12">
- <hr />
- </div>
- </div>
+ <hr>
<div class="row">
<div class="span8">
+ <h3>{{ _("Changelog") }}</h3>
+
+ {% module Changelog(name=name, limit=5) %}
+
+ <hr>
+ <p class="ac">
+ <a href="/package/{{ name }}/changelog">{{ _("Full changelog") }}</a>
+ </p>
+ </div>
+
+ <div class="span4">
<h3>{{ _("Open bugs") }}</h3>
{% if bugs %}
{% module BugsTable(pkg, bugs) %}
{% else %}
<blockquote>
- {{ _("There are currently no open bugs for <em>%s</em>.") % pkg.name }}
+ {{ _("There are currently no open bugs for %s.") % pkg.name }}
</blockquote>
{% end %}
- <div class="btn-toolbar pull-right">
- <div class="btn-group">
- <a class="btn" href="{{ bugtracker.enter_url(pkg.name) }}" target="_blank">
- {{ _("File a new bug") }}
- </a>
- <a class="btn" href="{{ bugtracker.buglist_url(pkg.name) }}" target="_blank">
- {{ _("Show all bugs") }}
- </a>
+ <div class="ac">
+ <div class="btn-toolbar">
+ <div class="btn-group">
+ <a class="btn" href="{{ bugtracker.enter_url(pkg.name) }}" target="_blank">
+ {{ _("File new bug") }}
+ </a>
+ <a class="btn" href="{{ bugtracker.buglist_url(pkg.name) }}" target="_blank">
+ {{ _("Show all bugs") }}
+ </a>
+ </div>
</div>
</div>
- </div>
- <div class="span4">
{% if build_times %}
+ <hr>
+
<h3>{{ _("Build times") }}</h3>
<table class="table table-striped table-hover">
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Changelog of %s") % name }}{% end block %}
+
+{% block body %}
+ <ul class="breadcrumb">
+ <li>
+ <a href="/">{{ _("Home") }}</a>
+ <span class="divider">/</span>
+ </li>
+ <li>
+ <a href="/packages">{{ _("Packages") }}</a>
+ <span class="divider">/</span>
+ </li>
+ <li>
+ <a href="/package/{{ name }}">{{ name }}</a>
+ <span class="divider">/</span>
+ </li>
+ <li class="active">
+ <a href="/package/{{ name }}/changelog">{{ _("Changelog") }}</a>
+ </li>
+ </ul>
+
+ <div class="page-header">
+ <h2>
+ {{ name }} <small>{{ _("Changelog") }}</small>
+ </h2>
+ </div>
+
+ {% module Changelog(builds=builds) %}
+
+ <ul class="pager">
+ {% if have_prev %}
+ <li class="previous">
+ <a href="?offset={{ offset - limit }}&limit={{ limit }}">← {{ _("Older") }}</a>
+ </li>
+ {% else %}
+ <li class="previous disabled">
+ <a href="#">← {{ _("Older") }}</a>
+ </li>
+ {% end %}
+
+ {% if have_next %}
+ <li class="next">
+ <a href="?offset={{ offset + limit }}&limit={{ limit }}">{{ _("Newer") }} →</a>
+ </li>
+ {% else %}
+ <li class="next disabled">
+ <a href="#">{{ _("Newer") }} →</a>
+ </li>
+ {% end %}
+ </ul>
+{% end block %}
"BuildLog" : BuildLogModule,
"BuildOffset" : BuildOffsetModule,
"BuildTable" : BuildTableModule,
+
+ # Changelog
+ "Changelog" : ChangelogModule,
+ "ChangelogEntry" : ChangelogEntryModule,
+
"CommitsTable" : CommitsTableModule,
"JobsTable" : JobsTableModule,
"JobsList" : JobsListModule,
(r"/package/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", PackageDetailHandler),
(r"/package/([\w\-\+]+)/properties", PackagePropertiesHandler),
(r"/package/([\w\-\+]+)", PackageNameHandler),
+ (r"/package/([\w\-\+]+)/changelog", PackageChangelogHandler),
# Files
(r"/file/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", FileDetailHandler),
"scratch_builds" : builds["scratch"],
}
- self.render("package-detail-list.html", builds=builds,
+ self.render("package-detail-list.html", builds=builds, name=name,
latest_build=latest_build, pkg=latest_build.pkg,
build_times=build_times, bugs=bugs, **kwargs)
+class PackageChangelogHandler(BaseHandler):
+ def get(self, name):
+ limit = self.get_argument("limit", 10)
+ try:
+ limit = int(limit)
+ except ValueError:
+ limit = 10
+
+ offset = self.get_argument("offset", 0)
+ try:
+ offset = int(offset)
+ except ValueError:
+ offset = 0
+
+ # Get one more build than requested to find out if there are more items
+ # to display (next button).
+ builds = self.pakfire.builds.get_changelog(name, limit=limit + 1, offset=offset)
+
+ if len(builds) >= limit:
+ have_next = True
+ else:
+ have_next = False
+
+ if offset < limit:
+ have_prev = False
+ else:
+ have_prev = True
+
+ # Clip list to limit.
+ builds = builds[:limit]
+
+ self.render("packages/changelog.html", name=name, builds=builds,
+ limit=limit, offset=offset, have_prev=have_prev, have_next=have_next)
+
+
class PackageDetailHandler(BaseHandler):
def get(self, uuid):
pkg = self.pakfire.packages.get_by_uuid(uuid)
pkg=pkg, bugs=bugs)
+class ChangelogModule(UIModule):
+ def render(self, name=None, builds=None, *args, **kwargs):
+ if not builds:
+ builds = self.pakfire.builds.get_changelog(name, *args, **kwargs)
+
+ return self.render_string("modules/changelog/index.html", builds=builds)
+
+
+class ChangelogEntryModule(UIModule):
+ def render(self, build):
+ return self.render_string("modules/changelog/entry.html", build=build)
+
+
class CommitsTableModule(UIModule):
def render(self, distro, source, commits, full_format=True):
return self.render_string("modules/commits-table.html",