jinja templates support

This commit is contained in:
Evgenii Alekseev 2021-03-08 15:47:05 +03:00
parent 026c896fb7
commit b3345c4184
8 changed files with 85 additions and 23 deletions

View File

@ -50,8 +50,9 @@ Report generation settings:
Group name must refer to architecture, e.g. it should be `html_x86_64` for x86_64 architecture.
* `path` - path to html report file, string, required.
* `css_path` - path to CSS to include in HTML, string, optional.
* `homepage` - link to homepage, string, optional.
* `link_path` - prefix for HTML links, string, required.
* `template_path` - path to Jinja2 template, string, required.
## `upload` group

View File

@ -10,13 +10,18 @@ license=('GPL3')
depends=('devtools' 'expac' 'git' 'python-aur' 'python-srcinfo')
makedepends=('python-pip')
optdepends=('aws-cli: sync to s3'
'breezy: -bzr packages support'
'darcs: -darcs packages support'
'gnupg: package and repository sign'
'rsync: sync by using rsync')
'mercurial: -hg packages support'
'python-jinja: html report generation'
'rsync: sync by using rsync'
'subversion: -svn packages support')
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver-src.tar.xz"
'ahriman.sudoers'
'ahriman.sysusers'
'ahriman.tmpfiles')
sha512sums=('67a6b6432ca8985491e398b8f2b374cf7cfd40bb69ad844913d9d45d3b510fba2910dfc21fd33a4faf4f2035bb005909cf815523180436c3a30e512757c268e7'
sha512sums=('f77b434f5174b2e7a8817bdcc1883e9ded3bd57c30be09b438ec55b65aa83bcd1326f1241ad9ca86552b5fb71f9a15637af7997b37636db9d9ee61c24d235c5c'
'8c9b5b63ac3f7b4d9debaf801a1e9c060877c33d3ecafe18010fcca778e5fa2f2e46909d3d0ff1b229ff8aa978445d8243fd36e1fc104117ed678d5e21901167'
'13718afec2c6786a18f0b223ef8e58dccf0688bca4cdbe203f14071f5031ed20120eb0ce38b52c76cfd6e8b6581a9c9eaa2743eb11abbaca637451a84c33f075'
'55b20f6da3d66e7bbf2add5d95a3b60632df121717d25a993e56e737d14f51fe063eb6f1b38bd81cc32e05db01c0c1d80aaa720c45cde87f238d8b46cdb8cbc4')

View File

@ -25,8 +25,9 @@ target =
[html_x86_64]
path =
css_path =
homepage =
link_path =
template_path = /usr/share/ahriman/index.jinja2
[upload]
target =

View File

@ -0,0 +1,31 @@
<!doctype html>
<html lang="en">
<head>
<title>{{ repository|e }}</title>
</head>
<body>
<h1>{{ repository|e }} ArchLinux custom repository</h1>
{% if pgp_key is not none %}
<p>All packages are signed with <a href="http://keys.gnupg.net/pks/lookup?search=0x{{ pgp_key|e }}" title="key search">{{ pgp_key|e }}</a>.</p>
{% endif %}
<code>
$ cat /etc/pacman.conf<br>
[{{ repository|e }}]<br>
Server = {{ link_path|e }}
</code>
<p>Packages:</p>
<ul>
{% for package, package_url in packages.items() %}
<li><a href="{{ package_url|e }}" title="{{ package|e }}">{{ package|e }}</a></li>
{% endfor %}
</ul>
{% if homepage is not none %}
<footer><a href="{{ homepage|e }}" title="homepage">Homepage</a></footer>
{% endif %}
</body>
</html>

View File

@ -17,7 +17,7 @@ setup(
author='arcanis',
author_email='',
url='',
url='https://github.com/arcan1s/ahriman',
license='GPL3',
@ -39,7 +39,7 @@ setup(
include_package_data=True,
scripts=[
'package/bin/ahriman'
'package/bin/ahriman',
],
data_files=[
('/etc', ['package/etc/ahriman.ini']),
@ -47,10 +47,12 @@ setup(
('lib/systemd/system', [
'package/lib/systemd/system/ahriman.service',
'package/lib/systemd/system/ahriman.timer'
])
]),
('share/ahriman', ['package/share/ahriman/index.jinja2']),
],
extras_require={
'html-templates': ['Jinja2'],
'test': ['coverage', 'pytest'],
},
)

View File

@ -17,10 +17,15 @@
# 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 jinja2
import os
from typing import Dict
from ahriman.core.configuration import Configuration
from ahriman.core.report.report import Report
from ahriman.core.util import package_like
from ahriman.models.sign_settings import SignSettings
class HTML(Report):
@ -29,25 +34,37 @@ class HTML(Report):
Report.__init__(self, architecture, config)
section = self.config.get_section_name('html', self.architecture)
self.report_path = config.get(section, 'path')
self.css_path = config.get(section, 'css_path')
self.link_path = config.get(section, 'link_path')
self.title = config.get('repository', 'name')
self.template_path = config.get(section, 'template_path')
# base template vars
if SignSettings.from_option(config.get('sign', 'enabled')) != SignSettings.Disabled:
self.pgp_key = config.get('sign', 'key')
else:
self.pgp_key = None
self.homepage = config.get(section, 'homepage', fallback=None)
self.repository = config.get('repository', 'name')
def generate(self, path: str) -> None:
# lets not use libraries here
html = f'''<html lang="en"><head><title>{self.title}</title>'''
if self.css_path:
html += f'''<link rel="stylesheet" type="text/css" href="{self.css_path}">'''
html += '''</head><body>'''
# idea comes from https://stackoverflow.com/a/38642558
templates_dir, template_name = os.path.split(self.template_path)
loader = jinja2.FileSystemLoader(searchpath=templates_dir)
environment = jinja2.Environment(loader=loader)
template = environment.get_template(template_name)
html += '''<ul>'''
for package in sorted(os.listdir(path)):
if '.pkg.' not in package:
packages: Dict[str, str] = {}
for fn in sorted(os.listdir(path)):
if not package_like(fn):
continue
html += f'''<li><a href="{self.link_path}/{package}">{package}</a></li>'''
html += '''</ul>'''
packages[fn] = f'{self.link_path}/{fn}'
html += '''</body></html>'''
html = template.render(
homepage=self.homepage,
link_path=self.link_path,
packages=packages,
pgp_key=self.pgp_key,
repository=self.repository)
with open(self.report_path, 'w') as out:
out.write(html)

View File

@ -29,6 +29,7 @@ from ahriman.core.repo.repo_wrapper import RepoWrapper
from ahriman.core.report.report import Report
from ahriman.core.sign.gpg_wrapper import GPGWrapper
from ahriman.core.upload.uploader import Uploader
from ahriman.core.util import package_like
from ahriman.models.package import Package
from ahriman.models.repository_paths import RepositoryPaths
@ -64,7 +65,7 @@ class Repository:
def packages(self) -> List[Package]:
result: Dict[str, Package] = {}
for fn in os.listdir(self.paths.repository):
if '.pkg.' not in fn:
if not package_like(fn):
continue
full_path = os.path.join(self.paths.repository, fn)
try:
@ -101,7 +102,7 @@ class Repository:
def process_remove(self, packages: List[str]) -> str:
for fn in os.listdir(self.paths.repository):
if '.pkg.' not in fn:
if not package_like(fn):
continue
full_path = os.path.join(self.paths.repository, fn)
@ -146,7 +147,7 @@ class Repository:
self.config.get_section_name('build', self.architecture), 'ignore_packages')
for fn in os.listdir(self.paths.repository):
if '.pkg.' not in fn:
if not package_like(fn):
continue
try:

View File

@ -37,3 +37,7 @@ def check_output(*args: str, exception: Optional[Exception],
logger.debug(line)
raise exception or e
return result
def package_like(filename: str) -> bool:
return '.pkg.' in filename and not filename.endswith('.sig')