#4346 port kojiweb to jinja2
Merged 9 days ago by tkopecek. Opened 2 months ago by mikem.
mikem/koji jinja2  into  master

file added
+3
@@ -0,0 +1,3 @@ 

+ markupsafe_xss:

+     allowed_calls:

+         - _MarkTrustedValue

file modified
+2 -2
@@ -20,8 +20,8 @@ 

  indent_style = tab

  tab_width = 8

  

- # CHTML: 2-space indents

- [**/*.chtml]

+ # jinja html: 2-space indents

+ [**/*.html.j2]

  indent_style = space

  indent_size = 2

  

@@ -0,0 +1,190 @@ 

+ #!/usr/bin/python3

+ 

+ import os.path

+ import re

+ import sys

+ import tempfile

+ from optparse import OptionParser

+ 

+ 

+ """

+ Poorly convert some cheetah template code to jinja

+ 

+ This is NOT a full or accurate conversion, it is a set of simple

+ tranformations that reduce some of the manual work.

+ 

+ Always review the changes.

+ Always review the changes.

+ """

+ 

+ 

+ def main():

+     global subs

+     global options

+     parser = OptionParser(usage="%prog <filename>")

+     parser.add_option('-w', '--write', action='store_true', help='write changes to file')

+     options, args = parser.parse_args()

+     options.args = args

+ 

+     if len(args) != 1:

+         error('Please specify one template')

+     fn = args[0]

+     handle_file(fn)

+ 

+ 

+ def handle_file(fn):

+     outp = None

+     if options.write:

+         dirname = os.path.dirname(fn)

+         basename = os.path.basename(fn)

+         outfile = tempfile.NamedTemporaryFile(dir=dirname, mode='wt', prefix=f'_{basename}', delete=False)

+         with outfile as outp:

+             _handle_file(fn, outp)

+         os.replace(outfile.name, fn)

+         print(f'Wrote {fn}')

+     else:

+         _handle_file(fn, outp)

+ 

+ 

+ def _handle_file(fn, outp):

+     with open(fn, 'rt') as fp:

+         for lineno, line in enumerate(fp):

+             line = handle_line(lineno, line, outp)

+             if line is not None and outp is not None:

+                 outp.write(line)

+ 

+ 

+ def handle_line(lineno, line, outp):

+     orig = line

+     matches = 0

+     skip = False

+     rules = list(SUBS)

+     while rules:

+         prog, repl = rules.pop(0)

+         last = line

+         if repl == SKIP:

+             m = prog.search(line)

+             if m:

+                 print(f'{lineno}: Matched skip pattern {prog.pattern!r}')

+                 print(line, end='')

+                 skip = True

+                 line = orig

+                 break

+             continue

+         elif repl == DROP:

+             m = prog.search(line)

+             if m:

+                 print(f'{lineno}: Matched DROP pattern {prog.pattern!r}')

+                 print(line, end='')

+                 return None

+         elif repl == BREAK:

+             m = prog.search(line)

+             if m:

+                 print(f'{lineno}: Matched BREAK pattern {prog.pattern!r}')

+                 print(line, end='')

+                 break

+         elif isinstance(repl, Jump):

+             # forget remaing rules and use target rules from here

+             m = prog.search(line)

+             if m:

+                 rules = list(repl.target)

+         else:

+             line, n = prog.subn(repl, line)

+             if n:

+                 matches += n

+                 print(f'{lineno}: Matched {prog.pattern!r} (count: {n})')

+     if matches:

+         print(f'Made {matches} substitutions for line {lineno}')

+         print(f'ORIG: {orig}', end='')

+         print(f' NEW: {line}')

+     return collapse(line)

+ 

+ 

+ def rules(subs):

+     # compile subs

+     return [(re.compile(pat, flags), repl) for pat, repl, flags in subs]

+ 

+ 

+ class Jump:

+     # jump to new set of substitutions

+     def __init__(self, target):

+         self.target = target

+ 

+ 

+ SKIP = ('skip subs for this line',)

+ DROP = ('drop line',)

+ BREAK = ('stop subs checks for this line',)

+ STATE = rules([

+     # subrules for some line statements

+     [r'[$]', '', 0],

+     [r'len\(([\w.$]+)\)', r'(\1 |length)', 0 ],

+ ])

+ SUBS = rules([

+     # [pattern, replacement, flags]

+     [r'util.(toggleOrder|rowToggle|sortImage|passthrough_except|passthrough|authToken)\b', r'util.\g<1>2', 0],

+     [r'(#include .*)header.chtml', r'\1header2.chtml', 0],

+     [r'(#include .*)footer.chtml', r'\1footer2.chtml', 0],

+     [r'^#import', DROP, 0],

+     [r'^#from .* import', DROP, 0],

+     [r'^\s*#(if|for|elif|set)', Jump(STATE), 0],

+     [r'#end if', r'#endif', 0],

+     [r'#end for', r'#endfor', 0],

+     [r'[(][$]self, ', r'(', 0 ],

+     [r'\([$]self\)', r'()', 0 ],

+     [r'len\(([\w.$]+)\)', r'(\1 |length)', 0 ],

+     [r'[$](([\w.]+)[(][^()]*[)])', r'{{ \1 }}', 0 ],

+     [r'${\s*([^{}]+)\s*}', r'{{ \1 }}', 0 ],

+     [r'#echo ([^#]+)#', r'{{ \1 }}', 0 ],

+     [r'#if ([^#]+) then ([^#]+) else ([^#]+)\s*#', r'{{ \2 if \1 else \3 }}', 0 ],

+     [r'''[$]([\w.]+)\['(\w+)'\]''', r'{{ \1.\2 }}', 0],

+     [r'''[$]([\w.]+)\["(\w+)"\]''', r'{{ \1.\2 }}', 0],

+     [r'[$]([\w.]+)[([]', SKIP, 0],

+     [r'^(\s*)#attr ', r'\1#set ', 0],

+     [r'^\s*#', BREAK, 0],

+     [r'[$]([\w.]+)', r'{{ \1 }}', 0],

+ ])

+ 

+ 

+ def error(msg):

+     print(msg)

+     sys.exit(1)

+ 

+ 

+ BRACES = re.compile(r'({{ | }})')

+ 

+ def collapse(line):

+     """Collapse nested double braces"""

+     tokens = BRACES.split(line)

+ 

+     depth = 0

+     tokens2 = []

+     for tok in tokens:

+         if tok == '{{ ':

+             # only keep braces at the outer layer

+             if depth == 0:

+                 tokens2.append(tok)

+             depth += 1

+         elif tok == ' }}':

+             depth -= 1

+             if depth < 0:

+                 warning("Brace  mismatch. Can't collapse")

+                 break

+             elif depth == 0:

+                 # only keep braces at the outer layer

+                 tokens2.append(tok)

+         else:

+             # keep everything else

+             tokens2.append(tok)

+ 

+     if depth < 0:

+         warning('Unexpected }}')

+         return line

+     elif depth > 0:

+         warning('Missing }}')

+         return line

+     else:

+         return ''.join(tokens2)

+ 

+ 

+ if __name__ == '__main__':

+     main()

file modified
+79
@@ -2,9 +2,11 @@ 

  

  from __future__ import absolute_import, print_function

  

+ import ast

  import mimetypes

  import os

  import os.path

+ import optparse

  import pprint

  import sys

  from urllib.parse import quote
@@ -17,6 +19,7 @@ 

  sys.path.insert(1, os.path.join(CWD, 'www/lib'))

  sys.path.insert(1, os.path.join(CWD, 'www/kojiweb'))

  import wsgi_publisher

+ import index as kojiweb_handlers

  

  

  def get_url(environ):
@@ -122,11 +125,87 @@ 

      return wsgi_publisher.application(environ, start_response)

  

  

+ def nice_literal(value):

+     try:

+         return ast.literal_eval(value)

+     except (ValueError, SyntaxError):

+         return value

+ 

+ 

+ def get_options():

+     parser = optparse.OptionParser(usage='%prog [options]')

+     # parser.add_option('--pdb', action='store_true',

+     #                   help='drop into pdb on error')

+     parser.add_option('--user', '-u', help='fake login as user')

+     parser.add_option('--time', '-t', type="float", help='mock time as value')

+     parser.add_option('-o', '--config-option', help='override config option',

+                       action='append', metavar='NAME=VALUE')

+     opts, args = parser.parse_args()

+ 

+     if args:

+         parser.error('This command takes no args, just options')

+ 

+     if opts.config_option:

+         overrides = {}

+         for s in opts.config_option:

+             k, v = s.split('=', 1)

+             v = nice_literal(v)

+             overrides[k] = v

+         opts.config_option = overrides

+ 

+     return opts

+ 

+ 

+ def override_load_config(opts):

+     original_load_config = wsgi_publisher.Dispatcher.load_config

+ 

+     def my_load_config(_self, environ):

+         oldopts = original_load_config(_self, environ)

+         oldopts.update(opts)

+         _self.options = oldopts

+         return oldopts

+ 

+     wsgi_publisher.Dispatcher.load_config = my_load_config

+ 

+ 

+ def fake_login(user):

+     original_assertLogin = kojiweb_handlers._assertLogin

+     original_getServer = kojiweb_handlers._getServer

+ 

+     def my_assertLogin(environ):

+         pass

+ 

+     def my_getServer(environ):

+         session = original_getServer(environ)

+         environ['koji.currentUser'] = session.getUser(user)

+         return session

+ 

+     kojiweb_handlers._assertLogin = my_assertLogin

+     kojiweb_handlers._getServer = my_getServer

+ 

+ 

  def main():

+     options = get_options()

+     if options.config_option:

+         override_load_config(options.config_option)

+     if options.user:

+         fake_login(options.user)

+     if options.time:

+         from unittest import mock

+         import datetime

+         dt = datetime.datetime.fromtimestamp(options.time)

+         mock.patch('time.time', return_value=options.time).start()

+         # mocking datetime is tricky, can't mock the c object directly

+         # and can't mock the datetime class globally without breaking other code

+         # so we just mock the handlers import of it

+         my_datetime = mock.patch.object(kojiweb_handlers.kojiweb.util, 'datetime', wraps=datetime).start()

+         my_datetime.datetime.now.return_value = dt

+ 

      # koji.add_file_logger('koji', 'fakeweb.log')

      httpd = make_server('', 8000, application)

      print("Serving kojiweb on http://localhost:8000 ...")

      httpd.serve_forever()

  

+ 

  if __name__ == '__main__':

      main()

file modified
+1 -1
@@ -199,7 +199,7 @@ 

     koji-hub via XML-RPC.

  

  -  **koji-web** is a set of scripts that run in mod\_wsgi and use the

-    Cheetah templating engine to provide an web interface to Koji.

+    Jinja templating engine to provide an web interface to Koji.

     koji-web exposes a lot of information and also provides a means for

     certain operations, such as cancelling builds.

  -  **koji** is a CLI written in Python that provides many hooks into Koji.

file modified
+1 -1
@@ -123,7 +123,7 @@ 

  

  Koji-Web

  --------

- koji-web is a set of scripts that run in mod_wsgi and use the Cheetah

+ koji-web is a set of scripts that run in mod_wsgi and use the Jinja

  templating engine to provide a web interface to Koji. It acts as a client to

  koji-hub providing a visual interface to perform a limited amount of

  administration. koji-web exposes a lot of information and also provides a means

file modified
+1 -1
@@ -895,7 +895,7 @@ 

  Koji Web - Interface for the Masses

  ===================================

  

- Koji-web is a set of scripts that run in mod_wsgi and use the Cheetah

+ Koji-web is a set of scripts that run in mod_wsgi and use the Jinja

  templating engine to provide an web interface to Koji. koji-web exposes a lot

  of information and also provides a means for certain operations, such as

  cancelling builds.

@@ -565,16 +565,16 @@ 

  Koji-Web

  --------

  

- koji-web is a set of scripts that run in mod\_wsgi and use the Cheetah

+ koji-web is a set of scripts that run in mod\_wsgi and use the Jinja

  templating engine to provide a web interface to Koji. It acts as a

  client to koji-hub providing a visual interface to perform a limited

  amount of administration. koji-web exposes a lot of information and also

  provides a means for certain operations, such as cancelling builds.

  

- The web pages are derived from Cheetah templates, the syntax of which

+ The web pages are derived from Jinja templates, the syntax of which

  you can read up on

- `here <http://cheetahtemplate.org/users_guide/>`__. These

- templates are the ``chtml`` files sitting in ``www/kojiweb``. You'll

+ `here <https://jinja.palletsprojects.com/>`__. These

+ templates are the ``html.j2`` files sitting in ``www/kojiweb``. You'll

  notice quickly that these templates are referencing variables, but where

  do they come from?

  
@@ -582,26 +582,12 @@ 

  functions named after the templates they support, and in each one a

  dictionary called ``values`` is populated. This is how data is gathered

  about the task, build, archive, or whatever the page is about. Take your

- time with ``taskinfo.chtml`` in particular, as the conditionals there

+ time with ``taskinfo.html.j2`` in particular, as the conditionals there

  have gotten quite long. If you are adding a new task to Koji, you will

  need to extend this at a minimum. A new type of build task would require

  this, and possibly another that is specific to viewing the archived

  information about the build. (taskinfo vs. buildinfo)

  

- If your web page needs to display the contents of a list or dictionary,

- use the ``$printMap`` function to help with that. It is often sensible

- to define a function that easily prints options and values in a

- dictionary. An example of this is in taskinfo.chtml.

- 

- ::

- 

-     #def printOpts($opts)

-       #if $opts

-       <strong>Options:</strong><br/>

-       $printMap($opts, '&nbsp;&nbsp;')

-       #end if

-     #end def

- 

  Finally, if you need to expand the drop-down menus of "method" types

  when searching for tasks in the WebUI, you will need to add them to the

  ``_TASKS`` list in ``www/kojiweb/index.py``. Add values where

file modified
+2 -1
@@ -289,6 +289,7 @@ 

  Requires: python%{python3_pkgversion}-librepo

  Requires: python%{python3_pkgversion}-multilib

  Requires: python%{python3_pkgversion}-cheetah

+ # cheetah required for backwards compatibility in wrapperRPM task

  %else

  Requires: python2-%{name} = %{version}-%{release}

  Requires: python2-multilib
@@ -359,7 +360,7 @@ 

  Requires: python%{python3_pkgversion}-mod_wsgi

  Requires: mod_auth_gssapi

  Requires: python%{python3_pkgversion}-psycopg2

- Requires: python%{python3_pkgversion}-cheetah

+ Requires: python%{python3_pkgversion}-jinja2

  Requires: python%{python3_pkgversion}-%{name} = %{version}-%{release}

  Provides: %{name}-web-code = %{version}-%{release}

  

file modified
+38 -2
@@ -3,9 +3,10 @@ 

      from unittest import mock

  except ImportError:

      import mock

+ import json

  import koji

  

- from koji.xmlrpcplus import Fault

+ from koji.xmlrpcplus import Fault, DateTime

  

  

  class BaseFakeClientSession(koji.ClientSession):
@@ -22,9 +23,11 @@ 

          self._calls = []

          for call in calls:

              method = call['methodName']

-             args, kwargs = koji.decode_args(call['params'])

+             args, kwargs = koji.decode_args(*call['params'])

              try:

                  result = self._callMethod(method, args, kwargs)

+                 # multicall wraps non-fault results in a singleton

+                 result = (result,)

                  ret.append(result)

              except Fault as fault:

                  if strict:
@@ -58,6 +61,12 @@ 

              key = self._munge([call['method'], call['args'], call['kwargs']])

              self._calldata.setdefault(key, []).append(call)

  

+     def load(self, filename):

+         # load from json file

+         with open(filename, 'rt') as fp:

+             data = json.load(fp, object_hook=decode_data)

+         self.load_calls(data)

+ 

      def _callMethod(self, name, args, kwargs=None, retry=True):

          if self.multicall:

              return super(FakeClientSession, self)._callMethod(name, args,
@@ -103,6 +112,12 @@ 

      def get_calls(self):

          return self._calldata

  

+     def dump(self, filename):

+         with open(filename, 'wt') as fp:

+             # json.dump(self._calldata, fp, indent=4, sort_keys=True)

+             json.dump(self._calldata, fp, indent=4, sort_keys=True, default=encode_data)

+         self._calldata = []

+ 

      def _callMethod(self, name, args, kwargs=None, retry=True):

          if self.multicall:

              return super(RecordingClientSession, self)._callMethod(name, args,
@@ -128,3 +143,24 @@ 

                     'faultString': str(e)}

              call['fault'] = err

              raise

+ 

+ 

+ def encode_data(value):

+     """Encode data for json"""

+     if isinstance(value, DateTime):

+         return {'__type': 'DateTime', 'value': value.value}

+     else:

+         raise TypeError('Unknown type for json encoding')

+ 

+ 

+ def decode_data(value):

+     """Decode data encoded for json"""

+     if isinstance(value, dict):

+         _type = value.get('__type')

+         if _type == 'DateTime':

+             return DateTime(value['value'])

+     #else

+     return value

+ 

+ 

+ # the end

The added file is too large to be shown here, see it at: tests/test_www/data/pages_calls.json
@@ -0,0 +1,207 @@ 

+ from __future__ import absolute_import

+ import inspect

+ import json

+ try:

+     from unittest import mock

+ except ImportError:

+     import mock

+ import os

+ import six

+ import sys

+ import unittest

+ 

+ from six.moves import StringIO

+ 

+ import koji

+ from koji_cli.lib import watch_tasks

+ from koji_cli.commands import anon_handle_watch_task

+ from koji.util import dslice

+ from ..test_cli.fakeclient import FakeClientSession, RecordingClientSession, encode_data

+ from .loadwebindex import webidx

+ from kojiweb.util import FieldStorageCompat

+ 

+ 

+ class TestPages(unittest.TestCase):

+ 

+     @classmethod

+     def setUpClass(cls):

+         # recording session used across tests in recording mode

+         cls.cfile = os.path.dirname(__file__) + f'/data/pages_calls.json'

+         cls.recording = False

+         cls.rsession = RecordingClientSession('http://localhost/kojihub', {})

+ 

+     @classmethod

+     def tearDownClass(cls):

+         if cls.recording:

+             # save recorded calls

+             cls.rsession.dump(cls.cfile)

+ 

+     def setUp(self):

+         self.environ = {

+             'koji.options': {

+                 'SiteName': 'test',

+                 'KojiFilesURL': 'http://server.local/files',

+                 'KojiHubURL': 'http://server.local/kojihub',

+                 'KojiGreeting': 'Welcome to Koji Web',

+                 'LoginDisabled': True,

+                 'Tasks': [],

+                 'ToplevelTasks': [],

+                 'ParentTasks': [],

+                 'MBS_WEB_URL': None,

+             },

+             'koji.currentUser': None,

+             'SCRIPT_FILENAME': webidx.__file__,  # close enough

+             'SCRIPT_NAME': '',

+             'SERVER_PORT': '80',

+             'SERVER_NAME': 'server.local',

+             'wsgi.url_scheme': 'http',

+             'koji.headers': [],

+         }

+         self.get_server = mock.patch.object(webidx, "_getServer").start()

+         self._assertLogin = mock.patch.object(webidx, "_assertLogin").start()

+         self.server = None  # set up setup_server

+ 

+         # mock time so that call args are reproduced

+         self.time = mock.patch('time.time').start()

+         self.time.return_value = 1735707600.0

+ 

+         def __get_server(env):

+             return self.server

+ 

+         self.get_server.side_effect = __get_server

+         self.setup_server()

+ 

+     def setup_server(self):

+         if self.recording:

+             self.server = self.rsession

+         else:

+             self.server = FakeClientSession('SERVER', {})

+             self.server.load(self.cfile)

+         return self.server

+ 

+     def tearDown(self):

+         mock.patch.stopall()

+ 

+     # Show long diffs in error output...

+     maxDiff = None

+ 

+     CALLS = [

+         ['index', ''],

+         ['packages', ''],

+         ['packages', 'prefix=m&order=package_name&inherited=1&blocked=1'],

+         ['packages', 'start=50&order=package_name&inherited=1&blocked=1'],

+         ['builds', ''],

+         ['builds', 'start=50&order=-build_id'],

+         ['builds', 'prefix=d&order=-build_id'],

+         ['builds', 'state=4&prefix=d&order=-build_id'],

+         ['builds', 'type=image&prefix=d&order=-build_id'],

+         ['tasks', ''],

+         ['tasks', 'state=all&view=tree&order=-id&method=all'],

+         ['tasks', 'state=failed&view=tree&order=-id&method=all'],

+         ['tasks', 'view=flat&state=failed&order=-id&method=all'],

+         ['tasks', 'method=buildArch&view=flat&state=failed&order=-id'],

+         ['tasks', 'owner=mikem&view=flat&state=failed&order=-id&method=buildArch'],

+         ['tags', ''],

+         ['tags', 'start=50&order=name'],

+         ['buildtargets', ''],

+         ['buildtargets', 'order=-id'],

+         ['users', ''],

+         ['users', 'prefix=m&order=name'],

+         ['hosts', ''],

+         ['hosts', 'ready=yes&channel=all&state=all&order=name&arch=all'],

+         ['hosts', 'channel=appliance&ready=all&state=all&order=name&arch=all'],

+         ['hosts', 'arch=x86_64&channel=appliance&ready=all&state=all&order=name'],

+         ['reports', ''],

+         ['packagesbyuser', ''],

+         ['buildsbyuser', ''],

+         ['rpmsbyhost', ''],

+         ['tasksbyuser', ''],

+         ['tasksbyhost', ''],

+         ['buildsbystatus', ''],

+         ['buildsbytarget', ''],

+         ['clusterhealth', ''],

+         ['search', ''],

+         ['search', 'terms=k*&type=package&match=glob'],

+         ['api', ''],

+         ['userinfo', 'userID=1'],

+         ['activesession', ''],

+         ['archiveinfo', 'archiveID=202'],

+         ['buildinfo', 'buildID=628'],

+         ['rpminfo', 'rpmID=6608'],

+         ['buildrootinfo', 'buildrootID=966'],

+         ['buildinfo', 'buildID=574'],

+         ['buildrootinfo', 'buildrootID=934'],

+         ['repoinfo', 'repoID=2580'],

+         ['buildroots', 'repoID=2580'],

+         ['buildroots', 'state=3&repoID=2580&order=id'],

+         ['buildtargetedit', 'targetID=107&a='],

+         ['buildtargetinfo', 'targetID=107'],

+         ['taskinfo', 'taskID=14330'],

+         ['channelinfo', 'channelID=1'],

+         #['channelinfo', 'channelID=MISSING'],

+         ['taginfo', 'tagID=798'],

+         ['externalrepoinfo', 'extrepoID=1'],

+         ['fileinfo', 'rpmID=6608&filename=/etc/koji.conf'],

+         ['hostinfo', 'hostID=1'],

+         ['hostedit', 'hostID=1&a='],

+         ['notificationcreate', 'a='],

+         ['notificationedit', 'notificationID=1&a='],

+         ['packageinfo', 'packageID=306'],

+         ['recentbuilds', ''],

+         ['recentbuilds', 'package=1'],

+         ['repoinfo', 'repoID=88'],

+         ['rpminfo', 'rpmID=6608'],

+         ['rpmlist', 'buildrootID=657&type=component'],

+         ['taginfo', 'tagID=2'],

+         ['tagedit', 'tagID=2&a='],

+         ['tagparent', 'tagID=2&parentID=1&action=edit&a='],

+         ['taginfo', 'tagID=2090'],

+         ['userinfo', 'userID=1'],

+         ['taskinfo', 'taskID=1'],

+         ['archivelist', 'buildrootID=363&type=built'],

+         ['buildinfo', 'buildID=422'],

+         ['archiveinfo', 'archiveID=130'],

+         ['archivelist', 'buildrootID=345&type=built'],

+         ['buildinfo', 'buildID=612'],

+         ['buildroots', ''],

+         ['buildroots', 'start=50&order=id'],

+         #['builds', 'start=50&order=id'],

+     ]

+ 

+     def prep_handler(self, method, query):

+         """Takes method name and query string, returns handler and data"""

+         # based loosely on publisher prep_handler

+         self.environ['QUERY_STRING'] = query

+         self.environ['koji.method'] = method

+         self.environ['SCRIPT_NAME'] = method

+         handler = getattr(webidx, method)

+         fs = FieldStorageCompat(self.environ)

+         self.environ['koji.form'] = fs

+         # even though we have curated urls, we need to filter args for some cases, e.g. search

+         args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \

+             inspect.getfullargspec(handler)

+         if not varkw:

+             data = dslice(fs.data, args, strict=False)

+         else:

+             data = fs.data.copy()

+         return handler, data

+ 

+     def test_web_handlers(self):

+         """Test a bunch of web handlers"""

+         for method, query in self.CALLS:

+             handler, data = self.prep_handler(method, query)

+ 

+             result = handler(self.environ, **data)

+ 

+             # result should be a string containing the rendered template

+             self.assertIsInstance(result, str)

+             # none of these should return the error template

+             self.assertNotIn(r'<h4>Error</h4>', result)

+             # all except recentbuilds (rss) should render the header and footer

+             if method != 'recentbuilds':

+                 self.assertIn(r'<div id="header">', result)

+                 self.assertIn(r'<div id="mainNav">', result)

+                 self.assertIn(r'<p id="footer">', result)

+ 

+ 

+ # the end

@@ -1,6 +1,7 @@ 

  from unittest import mock

  import unittest

  

+ import koji

  from .loadwebindex import webidx

  

  
@@ -26,7 +27,8 @@ 

          self.get_server.return_value = self.server

  

          self.server.repoInfo.return_value = {'dist': True, 'id': int(self.repo_id),

-                                              'tag_name': 'test-tag'}

+                                              'tag_name': 'test-tag', 'state': koji.REPO_READY,

+                                              'create_ts': 1735707600.0}

          self.server.listBuildroots.return_value = []

  

          webidx.repoinfo(self.environ, self.repo_id)
@@ -38,7 +40,8 @@ 

          self.get_server.return_value = self.server

  

          self.server.repoInfo.return_value = {'dist': False, 'id': int(self.repo_id),

-                                              'tag_name': 'test-tag'}

+                                              'tag_name': 'test-tag', 'state': koji.REPO_READY,

+                                              'create_ts': 1735707600.0}

          self.server.listBuildroots.return_value = [{'id': 1, 'repo_id': int(self.repo_id)}]

  

          webidx.repoinfo(self.environ, self.repo_id)

file modified
+1 -1
@@ -91,7 +91,7 @@ 

      bandit

  allowlist_externals = bandit

  commands =

-     bandit -ll -s B108,B608 -r \

+     bandit -c .bandit.yaml -ll -s B108,B608 -r \

          builder cli kojihub koji plugins util vm www \

          builder/kojid \

          cli/koji \

file modified
+2 -2
@@ -1,7 +1,7 @@ 

- SUBDIRS = includes

+ SUBDIRS = templates

  

  SERVERDIR = /usr/share/koji-web/scripts

- FILES = $(wildcard *.py *.chtml)

+ FILES = $(wildcard *.py *.html.j2)

  

  _default:

  	@echo "nothing to make.  try make install"

@@ -1,28 +0,0 @@ 

- #include "includes/header.chtml"

- #import koji

- #from kojiweb import util

- 

- #attr _PASSTHROUGH = ['userID']

- 

- <h4>Active sessions for $loggedInUser.name user</h4>

- <br>

-   <table class="data-list">

-      <tr class="list-header">

-       <th><a href="activesession?order=$util.toggleOrder($self, 'id')$util.passthrough_except($self, 'order')">Session ID</a> $util.sortImage($self, 'id')</th>

-       <th><a href="activesession?order=$util.toggleOrder($self, 'hostip')$util.passthrough_except($self, 'order')">Client IP</a> $util.sortImage($self, 'hostip')</th>

-       <th><a href="activesession?order=$util.toggleOrder($self, 'authtype')$util.passthrough_except($self, 'order')">Auth type</a> $util.sortImage($self, 'authtype')</th>

-       <th><a href="activesession?order=$util.toggleOrder($self, 'start_time')$util.passthrough_except($self, 'order')">Session start time</a> $util.sortImage($self, 'start_time')</th>

-       <th><a href="activesession?order=$util.toggleOrder($self, 'start_time')$util.passthrough_except($self, 'order')">Length session</a> $util.sortImage($self, 'start_time')</th>

-       <th><a href="activesession?order=$util.toggleOrder($self, 'id')$util.passthrough_except($self, 'order')">Logout?</a> $util.sortImage($self, 'id')</th>

-    </tr>

-     #for $act in $activesess

-     <tr class="$util.rowToggle($self)">

-       <td>$act.id</td>

-       <td>$act.hostip</td>

-       <td>$act.authtype</td>

-       <td>$util.formatTimeLong($act.start_time)</td>

-       <td>$act.lengthSession days</td>

-       <td><a href="activesessiondelete?sessionID=$act.id$util.authToken($self)">Logout</a></td>

-     </tr>

-     #end for

-   </table>

@@ -1,163 +0,0 @@ 

- #import koji

- #from kojiweb import util

- #from pprint import pformat

- #from urllib.parse import quote

- 

- #attr _PASSTHROUGH = ['archiveID', 'fileOrder', 'fileStart', 'buildrootOrder', 'buildrootStart']

- 

- #include "includes/header.chtml"

-   <h4>Information for archive <a href="archiveinfo?archiveID=$archive.id">$archive.filename</a></h4>

- 

-   <table>

-     <tr>

-       <th>ID</th><td>$archive.id</td>

-     </tr>

-     <tr>

-     #if $wininfo

-       <th>File Name</th><td>$koji.pathinfo.winfile($archive)</td>

-     #else

-       <th>File Name</th><td>$archive.filename</td>

-     #end if

-     </tr>

-     #if $archive.metadata_only

-     <tr>

-       <th>Metadata only</th><td>True (file not imported)</td>

-     </tr>

-     #end if

-     <tr>

-       <th>File Type</th><td>$archive_type.description</td>

-     </tr>

-     <tr>

-       <th>Build</th><td><a href="buildinfo?buildID=$build.id">$koji.buildLabel($build)</a></td>

-     </tr>

-     #if $maveninfo

-     <tr>

-       <th>Maven groupId</th><td>$archive.group_id</td>

-     </tr>

-     <tr>

-       <th>Maven artifactId</th><td>$archive.artifact_id</td>

-     </tr>

-     <tr>

-       <th>Maven version</th><td>$archive.version</td>

-     </tr>

-     #end if

-     <tr>

-       <th>Size</th><td><span title="$util.formatThousands($archive.size)">$util.formatNatural($archive.size)</span></td>

-     </tr>

-     <tr>

-       <th>Checksum</th><td>$archive.checksum</td>

-     </tr>

-     #if $wininfo

-     <tr>

-       <th>Platforms</th><td>$archive.platforms</td>

-     </tr>

-     <tr>

-       <th>Flags</th><td>$archive.flags</td>

-     </tr>

-     #end if

-     #if $builtInRoot

-     <tr>

-       <th>Buildroot</th><td><a href="buildrootinfo?buildrootID=$builtInRoot.id">$util.brLabel($builtInRoot)</a></td>

-     </tr>

-     #end if

-     #if $archive.get('extra')

-     <tr>

-       <th>Extra</th><td class="usertext">$pformat($archive.extra)</td>

-     </tr>

-     #end if

-     #if $files

-     <tr>

-       <th id="filelist">Files</th>

-       <td class="container">

-         <table class="nested data-list">

-           <tr>

-             <td class="paginate" colspan="2">

-               #if $len($filePages) > 1

-               <form class="pageJump">

-                 Page:

-                 <select onchange="javascript: window.location = 'archiveinfo?fileStart=' + this.value * $fileRange + '$util.passthrough_except($self, 'fileStart')#filelist';">

-                   #for $pageNum in $filePages

-                   <option value="$pageNum"#if $pageNum == $fileCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-                   #end for

-                 </select>

-               </form>

-               #end if

-               #if $fileStart > 0

-               <a href="archiveinfo?fileStart=#echo $fileStart - $fileRange#$util.passthrough_except($self, 'fileStart')#filelist">&lt;&lt;&lt;</a>

-               #end if

-               <strong>#echo $fileStart + 1 # through #echo $fileStart + $fileCount # of $totalFiles</strong>

-               #if $fileStart + $fileCount < $totalFiles

-               <a href="archiveinfo?fileStart=#echo $fileStart + $fileRange#$util.passthrough_except($self, 'fileStart')#filelist">&gt;&gt;&gt;</a>

-               #end if

-             </td>

-           </tr>

-           <tr class="list-header">

-             <th><a href="archiveinfo?fileOrder=$util.toggleOrder($self, 'name', 'fileOrder')$util.passthrough_except($self, 'fileOrder', 'fileStart')#filelist">Name</a> $util.sortImage($self, 'name', 'fileOrder')</th>

-             <th><a href="archiveinfo?fileOrder=$util.toggleOrder($self, 'size', 'fileOrder')$util.passthrough_except($self, 'fileOrder', 'fileStart')#filelist">Size</a> $util.sortImage($self, 'size', 'fileOrder')</th>

-           </tr>

-           #for $file in $files

-           <tr class="$util.rowToggle($self)">

-             <td><a href="fileinfo?archiveID=$archive.id&filename=$quote($file.name)">$file.name</a></td><td><span title="$util.formatThousands($file.size)">$util.formatNatural($file.size)</span></td>

-           </tr>

-           #end for

-         </table>

-       </td>

-     </tr>

-     #end if

-     <tr>

-       <th id="buildrootlist">Component&nbsp;of</th>

-       <td class="container">

-         #if $len($buildroots) > 0

-         <table class="nested data-list">

-           <tr>

-             <td class="paginate" colspan="3">

-               #if $len($buildrootPages) > 1

-               <form class="pageJump" action="">

-                 Page:

-                 <select onchange="javascript: window.location = 'archiveinfo?buildrootStart=' + this.value * $buildrootRange + '$util.passthrough_except($self, 'buildrootStart')#buildrootlist';">

-                   #for $pageNum in $buildrootPages

-                   <option value="$pageNum"#if $pageNum == $buildrootCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-                   #end for

-                 </select>

-               </form>

-               #end if

-               #if $buildrootStart > 0

-               <a href="archiveinfo?buildrootStart=#echo $buildrootStart - $buildrootRange #$util.passthrough_except($self, 'buildrootStart')#buildrootlist">&lt;&lt;&lt;</a>

-               #end if

-               <strong>#echo $buildrootStart + 1 # through #echo $buildrootStart + $buildrootCount # of $totalBuildroots</strong>

-               #if $buildrootStart + $buildrootCount < $totalBuildroots

-               <a href="archiveinfo?buildrootStart=#echo $buildrootStart + $buildrootRange#$util.passthrough_except($self, 'buildrootStart')#buildrootlist">&gt;&gt;&gt;</a>

-               #end if

-             </td>

-           </tr>

-           <tr class="list-header">

-             <th><a href="archiveinfo?buildrootOrder=$util.toggleOrder($self, 'id', 'buildrootOrder')$util.passthrough_except($self, 'buildrootOrder', 'buildrootStart')#buildrootlist">Buildroot</a> $util.sortImage($self, 'id', 'buildrootOrder')</th>

-             <th><a href="archiveinfo?buildrootOrder=$util.toggleOrder($self, 'create_event_time', 'buildrootOrder')$util.passthrough_except($self, 'buildrootOrder', 'buildrootStart')#buildrootlist">Created</a> $util.sortImage($self, 'create_event_time', 'buildrootOrder')</th>

-             <th><a href="archiveinfo?buildrootOrder=$util.toggleOrder($self, 'state', 'buildrootOrder')$util.passthrough_except($self, 'buildrootOrder', 'buildrootStart')#buildrootlist">State</a> $util.sortImage($self, 'state', 'buildrootOrder')</th>

-           </tr>

-           #for $buildroot in $buildroots

-           <tr class="$util.rowToggle($self)">

-             <td><a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></td>

-             <td>$util.formatTime($buildroot.create_event_time)</td>

-             <td>$util.imageTag($util.brStateName($buildroot.state))</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No buildroots

-         #end if

-       </td>

-     </tr>

-     #if $show_rpm_components

-     <tr>

-       <th colspan="2"><a href="rpmlist?imageID=$archive.id&amp;type=image" title="RPM components that are part of this archive">RPM components</a></th>

-     </tr>

-     #end if

-     #if $show_archive_components

-     <tr>

-       <th colspan="2"><a href="archivelist?imageID=$archive.id&amp;type=image" title="Archive components that are part of this archive">Archive components</a></th>

-     </tr>

-     #end if

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,94 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

- #@util.safe_return

- #def getID()

-   #if $type == 'image'

- imageID=$image.id #slurp

-   #else

- buildrootID=$buildroot.id #slurp

-   #end if

- #end def

- 

-   #if $type == 'component'

-   <h4>Component Archives of buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>

-   #elif $type == 'image'

-   <h4>Archives installed in <a href="archiveinfo?archiveID=$image.id">$image.filename</a></h4>

-   #else

-   <h4>Archives built in buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>

-   #end if

- 

-   <table class="data-list">

-     <tr>

-       <td class="paginate" colspan="#if $type == 'component' then '3' else '2'#">

-         #if $len($archivePages) > 1

-         <form class="pageJump">

-           Page:

-           <select onchange="javascript: window.location = 'archivelist?$getID()&start=' + this.value * $archiveRange + '$util.passthrough($self, 'order', 'type')';">

-             #for $pageNum in $archivePages

-             <option value="$pageNum"#if $pageNum == $archiveCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $archiveStart > 0

-         <a href="archivelist?$getID()&start=#echo $archiveStart - $archiveRange #$util.passthrough($self, 'order', 'type')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalArchives != 0

-         <strong>Archives #echo $archiveStart + 1 # through #echo $archiveStart + $archiveCount # of $totalArchives</strong>

-         #end if

-         #if $archiveStart + $archiveCount < $totalArchives

-         <a href="archivelist?$getID()&start=#echo $archiveStart + $archiveRange#$util.passthrough($self, 'order', 'type')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="archivelist?$getID()&order=$util.toggleOrder($self, 'filename')$util.passthrough($self, 'type')">Filename</a> $util.sortImage($self, 'filename')</th>

-       <th><a href="archivelist?$getID()&order=$util.toggleOrder($self, 'type_name')$util.passthrough($self, 'type')">Type</a> $util.sortImage($self, 'type_name')</th>

-       #if $type == 'component'

-       <th><a href="archivelist?$getID()&order=$util.toggleOrder($self, 'project')$util.passthrough($self, 'type')">Build Dependency?</a> $util.sortImage($self, 'project')</th>

-       #end if

-     </tr>

-     #if $len($archives) > 0

-     #for $archive in $archives

-     <tr class="$util.rowToggle($self)">

-       <td><a href="archiveinfo?archiveID=$archive.id">$archive.filename</a></td>

-       <td>$archive.type_name</td>

-       #if $type == 'component'

-       #set $project = $archive.project and 'yes' or 'no'

-       <td class="$project">$util.imageTag($project)</td>

-       #end if

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td colspan="#if $type == 'component' then '3' else '2'#">No Archives</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="#if $type == 'component' then '3' else '2'#">

-         #if $len($archivePages) > 1

-         <form class="pageJump">

-           Page:

-           <select onchange="javascript: window.location = 'archivelist?$getID()&start=' + this.value * $archiveRange + '$util.passthrough($self, 'order', 'type')';">

-             #for $pageNum in $archivePages

-             <option value="$pageNum"#if $pageNum == $archiveCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $archiveStart > 0

-         <a href="archivelist?$getID()&start=#echo $archiveStart - $archiveRange #$util.passthrough($self, 'order', 'type')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalArchives != 0

-         <strong>Archives #echo $archiveStart + 1 # through #echo $archiveStart + $archiveCount # of $totalArchives</strong>

-         #end if

-         #if $archiveStart + $archiveCount < $totalArchives

-         <a href="archivelist?$getID()&start=#echo $archiveStart + $archiveRange#$util.passthrough($self, 'order', 'type')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,269 +0,0 @@ 

- #import koji

- #import koji.util

- #from pprint import pformat

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- #set $nvrpath = $pathinfo.build($build)

- 

-   <h4>Information for build <a href="buildinfo?buildID=$build.id">$koji.buildLabel($build)</a></h4>

- 

-   <table>

-     <tr>

-       <th>ID</th><td>$build.id</td>

-     </tr>

-     <tr>

-       <th>Package Name</th><td><a href="packageinfo?packageID=$build.package_id">$build.package_name</a></td>

-     </tr>

-     <tr>

-       <th>Version</th><td>$build.version</td>

-     </tr>

-     <tr>

-       <th>Release</th><td>$build.release</td>

-     </tr>

-     <tr>

-       <th>Epoch</th><td>$build.epoch</td>

-     </tr>

-     #if $build.draft

-       <th>Draft</th><td>True</td>

-     #else

-       <th>Draft</th><td>False</td>

-     #end if

-     #if $build.get('source')

-     <tr>

-       <th>Source</th><td>$build['source']</td>

-     </tr>

-     #end if

-     #if 'maven' in $typeinfo

-     <tr>

-       <th>Maven&nbsp;groupId</th><td>$typeinfo.maven.group_id</td>

-     </tr>

-     <tr>

-       <th>Maven&nbsp;artifactId</th><td>$typeinfo.maven.artifact_id</td>

-     </tr>

-     <tr>

-       <th>Maven&nbsp;version</th><td>$typeinfo.maven.version</td>

-     </tr>

-     #end if

-     #if 'module' in $typeinfo

-     #if $module_id

-     <tr>

-       <th>Module&nbsp;ID</th>

-     #if $mbs_web_url

-       <td><a href="$mbs_web_url/module/$module_id">$module_id</a></td>

-     #else

-       <td>$module_id</td>

-     #end if

-     </tr>

-     #end if

-     #if $module_tag

-     <tr>

-       <th>Module&nbsp;Tag</th><td><a href="taginfo?tagID=$module_tag.id">$module_tag.name</a></td>

-     </tr>

-     #end if

-     #end if

-     #if $summary

-     <tr>

-       <th>Summary</th><td class="rpmheader">$summary</td>

-     </tr>

-     #end if

-     #if $description

-     <tr>

-       <th>Description</th><td class="rpmheader">$description</td>

-     </tr>

-     #end if

-     #if $vcs

-     <tr>

-         <th><label title="Package source code VCS location">VCS</label></th><td>$util.formatLink($vcs)</td>

-     </tr>

-     #end if

-     #if $disturl

-     <tr>

-         <th>DistURL</th><td>$util.formatLink($disturl)</td>

-     </tr>

-     #end if

-     <tr>

-       <th>Built by</th><td><a href="userinfo?userID=$build.owner_id">$build.owner_name</a></td>

-     </tr>

-     <tr>

-       #set $stateName = $util.stateName($build.state)

-       <th>State</th>

-       <td class="$stateName">$stateName

-       #if $build.state == $koji.BUILD_STATES.BUILDING

-       #if $currentUser and ('admin' in $perms or $build.owner_id == $currentUser.id)

-       <span class="adminLink">(<a href="cancelbuild?buildID=$build.id$util.authToken($self)">cancel</a>)</span>

-       #end if

-       #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Volume</th>

-       <td>$build.volume_name</td>

-     </tr>

-     <tr>

-       <th>Started</th><td>$util.formatTimeLong($start_ts)</td>

-     </tr>

-     #if $build.state == $koji.BUILD_STATES.BUILDING

-     #if $estCompletion

-     <tr>

-       <th>Est. Completion</th><td>$util.formatTimeLong($estCompletion)</td>

-     </tr>

-     #end if

-     #else

-     <tr>

-       <th>Completed</th><td>$util.formatTimeLong($build.completion_ts)</td>

-     </tr>

-     #end if

-     #if $build.promotion_ts

-     <tr>

-       <th>Promoted</th><td>$util.formatTimeLong($build.promotion_ts)</td>

-     </tr>

-     <tr>

-       <th>Promoted by</th><td><a href="userinfo?userID=$build.promoter_id">$build.promoter_name</a></td>

-     </tr>

-     #end if

-     #if $build.cg_id

-     <tr>

-       <th>Content generator</th><td>$build.cg_name</td>

-     </tr>

-     #end if

-     #if $task

-     <tr>

-       <th>Task</th><td><a href="taskinfo?taskID=$task.id" class="task$util.taskState($task.state)">$koji.taskLabel($task)</a></td>

-     </tr>

-     #end if

-     #if $build.get('extra')

-     <tr>

-       <th>Extra</th><td class="usertext">$pformat($build.extra)</td>

-     </tr>

-     #end if

-     <tr>

-       <th>Tags</th>

-       <td class="container">

-         #if $len($tags) > 0

-         <table class="nested">

-           #for $tag in $tags

-           <tr>

-             <td><a href="taginfo?tagID=$tag.id">$tag.name</a></td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No tags

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>RPMs</th>

-       <td class="container">

-         #if $len($rpmsByArch) > 0

-         <table class="nested">

-           #if 'src' in $rpmsByArch

-           <tr><th>src</th><th></th></tr>

-           #for $rpm in $rpmsByArch['src']

-           #set $rpmfile = '%(name)s-%(version)s-%(release)s.%(arch)s.rpm' % $rpm

-           #set $rpmpath = $pathinfo.rpm($rpm)

-           <tr>

-             <td></td>

-             #if $rpm.metadata_only

-             <td>$rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>) (metadata only)</td>

-             #elif $build.state == $koji.BUILD_STATES.DELETED

-             <td>$rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>)

-             #else

-             <td>$rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>) (<a href="$nvrpath/$rpmpath">download</a>)</td>

-             #end if

-           </tr>

-           #end for

-           #end if

-           #set $arches = $rpmsByArch.keys()

-           #for $arch in sorted($arches)

-           #if $arch == 'src'

-           #silent continue

-           #end if

-           <tr>

-             <th>$arch</th>

-           </tr>

-           #for $rpm in $rpmsByArch[$arch]

-           <tr>

-             #set $rpmfile = '%(name)s-%(version)s-%(release)s.%(arch)s.rpm' % $rpm

-             #set $rpmpath = $pathinfo.rpm($rpm)

-             <td></td>

-             <td>

-               #if $build.state != $koji.BUILD_STATES.DELETED

-               $rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>) (<a href="$nvrpath/$rpmpath">download</a>)

-               #else

-               $rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>)

-               #end if

-             </td>

-           </tr>

-           #end for

-           #end for

-         </table>

-         #else

-         No RPMs

-         #end if

-       </td>

-     </tr>

-     #for btype in $archiveIndex

-     #set $archivesByExt = $archiveIndex[btype]

-     #if not $archivesByExt

-     #continue

-     #end if

-     <tr>

-       <th>$btype.capitalize() Archives</th>

-       <td class="container">

-         <table class="nested">

-           #set $exts = $archivesByExt.keys()

-           #for ext in $exts

-           <tr>

-             <th>$ext</th>

-           </tr>

-           #for $archive in $archivesByExt[$ext]

-           <tr>

-             <td/>

-             <td>

-             #if $archive.metadata_only or $build.state == $koji.BUILD_STATES.DELETED

-             $archive.display (<a href="archiveinfo?archiveID=$archive.id">info</a>)

-             #else

-             $archive.display (<a href="archiveinfo?archiveID=$archive.id">info</a>) (<a href="$archive.dl_url">download</a>)

-             #end if

-             </td>

-           </tr>

-           #end for

-           #end for

-         </table>

-       </td>

-     </tr>

-     #end for

-     #if $logs_by_dir

-     <tr>

-       <th>Logs</th>

-       <td class="container">

-         <table class="nested">

-           #set $logdirs = $logs_by_dir.keys()

-           #for logdir in $logdirs

-           <tr>

-             <th>$logdir</th>

-           </tr>

-           #for loginfo in $logs_by_dir[$logdir]

-           <tr>

-             <td/>

-             <td>

-             <a href="$loginfo.dl_url">$loginfo.name</a>

-             </td>

-           </tr>

-           #end for

-           #end for

-         </table>

-       </td>

-     </tr>

-     #end if

-     #if $changelog

-     <tr>

-       <th>Changelog</th>

-       <td class="changelog">$koji.util.formatChangelog($changelog)</td>

-     </tr>

-     #end if

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,62 +0,0 @@ 

- #import koji

- #from kojiweb import util

- #from pprint import pformat

- 

- #include "includes/header.chtml"

- 

-   <h4>Information for buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>

- 

-   <table>

-     <tr>

-       <th>Host</th><td><a href="hostinfo?hostID=$buildroot.host_id">$buildroot.host_name</a></td>

-     </tr>

-     <tr>

-       <th>Arch</th><td>$buildroot.arch</td>

-     </tr>

-     <tr>

-       <th>ID</th><td>$buildroot.id</td>

-     </tr>

-     <tr>

-       <th>Task</th><td><a href="taskinfo?taskID=$task.id" class="task$util.taskState($task.state)">$koji.taskLabel($task)</a></td>

-     </tr>

-     <tr>

-       <th>State</th><td>$util.imageTag($util.brStateName($buildroot.state))</td>

-     </tr>

-     <tr>

-       <th>Created</th><td>$util.formatTimeLong($buildroot.create_event_time)</td>

-     </tr>

-     <tr>

-       <th>Retired</th><td>$util.formatTimeLong($buildroot.retire_event_time)</td>

-     </tr>

-     <tr>

-       <th>Repo ID</th><td><a href="repoinfo?repoID=$buildroot.repo_id">$buildroot.repo_id</a></td>

-     </tr>

-     <tr>

-       <th>Repo Tag</th><td><a href="taginfo?tagID=$buildroot.tag_id">$buildroot.tag_name</a></td>

-     </tr>

-     <tr>

-       <th>Repo State</th><td>$util.imageTag($util.repoStateName($buildroot.repo_state))</td>

-     </tr>

-     <tr>

-       <th>Repo Created</th><td>$util.formatTimeLong($buildroot.repo_create_event_time)</td>

-     </tr>

-     #if $buildroot.get('extra')

-     <tr>

-       <th>Extra</th><td class="usertext">$pformat($buildroot.extra)</td>

-     </tr>

-     #end if

-     <tr>

-       <th colspan="2"><a href="rpmlist?buildrootID=$buildroot.id&amp;type=component" title="RPMs that are installed into this buildroot when building packages">Component RPMs</a></th>

-     </tr>

-     <tr>

-       <th colspan="2"><a href="rpmlist?buildrootID=$buildroot.id&amp;type=built" title="RPMs that have been built in this buildroot">Built RPMs</a></th>

-     </tr>

-     <tr>

-       <th colspan="2"><a href="archivelist?buildrootID=$buildroot.id&type=component" title="Archives that are installed into this buildroot when building packages">Component Archives</a></th>

-     </tr>

-     <tr>

-       <th colspan="2"><a href="archivelist?buildrootID=$buildroot.id&type=built" title="Archives that have been built in this buildroot">Built Archives</a></th>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,47 +0,0 @@ 

- #import koji

- #from kojiweb import util

- #from pprint import pformat

- 

- #include "includes/header.chtml"

- 

-   <h4>Information for external buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>

- 

-   <table>

-     <tr>

-       <th>ID</th><td>$buildroot.id</td>

-     </tr>

-     <tr>

-       <th>Host OS</th><td>$buildroot.host_os</td>

-     </tr>

-     <tr>

-       <th>Host Arch</th><td>$buildroot.host_arch</td>

-     </tr>

-     <tr>

-       <th>Content Generator</th><td>$buildroot.cg_name ($buildroot.cg_version)</td>

-     </tr>

-     <tr>

-       <th>Container Type</th><td>$buildroot.container_type</td>

-     </tr>

-     <tr>

-       <th>Container Arch</th><td>$buildroot.container_arch</td>

-     </tr>

-     #if $buildroot.get('extra')

-     <tr>

-       <th>Extra</th><td class="usertext">$pformat($buildroot.extra)</td>

-     </tr>

-     #end if

-     <tr>

-       <th colspan="2"><a href="rpmlist?buildrootID=$buildroot.id&amp;type=component" title="RPMs that are installed into this buildroot when building packages">Component RPMs</a></th>

-     </tr>

-     <tr>

-       <th colspan="2"><a href="rpmlist?buildrootID=$buildroot.id&amp;type=built" title="RPMs that have been built in this buildroot">Built RPMs</a></th>

-     </tr>

-     <tr>

-       <th colspan="2"><a href="archivelist?buildrootID=$buildroot.id&type=component" title="Archives that are installed into this buildroot when building packages">Component Archives</a></th>

-     </tr>

-     <tr>

-       <th colspan="2"><a href="archivelist?buildrootID=$buildroot.id&type=built" title="Archives that have been built in this buildroot">Built Archives</a></th>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,97 +0,0 @@ 

- #import koji

- #from kojiweb import util

- 

- #attr _PASSTHROUGH = ['repoID', 'order', 'state']

- 

- #include "includes/header.chtml"

- 

-   <h4>Buildroots in repo <a href="repoinfo?repoID=$repoID">$repoID</a></h4>

- 

-   <table class="data-list">

-   <tr>

-       <td colspan="5">

-         <table class="nested">

-         <tr><td>

-         <strong>State</strong>:

-         </td><td>

-         <select name="state" class="filterlist" onchange="javascript: window.location = 'buildroots?state=' + this.value + '$util.passthrough_except($self, 'state')';">

-           <option value="all">all</option>

-           #for $stateOpt in ['INIT', 'WAITING', 'BUILDING', 'EXPIRED']

-           <option value="$koji.BR_STATES[$stateOpt]" #if $state == $koji.BR_STATES[$stateOpt] then 'selected' else ''#>$stateOpt.lower()</option>

-           #end for

-         </select>

-         </table>

-         </td>

-        </tr>

-       <tr>

-       <td class="paginate" colspan="5">

-         #if $len($buildrootPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'builds?start=' + this.value * $buildrootRange + '$util.passthrough_except($self)';">

-             #for $pageNum in $buildrootPages

-             <option value="$pageNum"#if $pageNum == $buildrootCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $buildrootStart > 0

-         <a href="builds?start=#echo $buildrootStart - $buildrootRange #$util.passthrough_except($self)">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalBuildroots != 0

-         <strong>Buildroots #echo $buildrootStart + 1 # through #echo $buildrootStart + $buildrootCount # of $totalBuildroots</strong>

-         #end if

-         #if $buildrootStart + $buildrootCount < $totalBuildroots

-         <a href="builds?start=#echo $buildrootStart + $buildrootRange#$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="buildroots?order=$util.toggleOrder($self, 'id')$util.passthrough_except($self, 'order')">BuildrootID</a> $util.sortImage($self, 'id')</th>

-       <th><a href="buildroots?order=$util.toggleOrder($self, 'repo_id')$util.passthrough_except($self, 'order')">Repo ID</a> $util.sortImage($self, 'repo_id')</th>

-       <th><a href="buildroots?order=$util.toggleOrder($self, 'task_id')$util.passthrough_except($self, 'order')">Task ID</a> $util.sortImage($self, 'task_id')</th>

-       <th><a href="buildroots?order=$util.toggleOrder($self, 'tag_name')$util.passthrough_except($self, 'order')">Tag name</a> $util.sortImage($self, 'tag_name')</th>

-       <th><a href="buildroots?order=$util.toggleOrder($self, 'state')$util.passthrough_except($self, 'order')">State</a> $util.sortImage($self, 'state')</th>

-     </tr>

-     #if $len($buildroots) > 0

-       #for $buildroot in $buildroots

-         <tr class="$util.rowToggle($self)">

-           <td><a href="buildrootinfo?buildrootID=$buildroot.id">$buildroot.id</a></td>

-           <td><a href="repoinfo?repoID=$buildroot.repo_id">$buildroot.repo_id</a></td>

-           <td><a href="taskinfo?taskID=$buildroot.task_id">$buildroot.task_id</a></td>

-           <td><a href="taginfo?tagID=$buildroot.tag_id">$buildroot.tag_name</a></td>

-           #set $stateName = $util.brStateName($buildroot.state)

-           <td class="$stateName">$util.brStateImage($buildroot.state)</td>

-         </tr>

-       #end for

-     #else

-       <tr class="row-odd">

-         <td colspan="5">No buildroots</td>

-       </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="5">

-         #if $len($buildrootPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'builds?start=' + this.value * $buildrootRange + '$util.passthrough_except($self)';">

-             #for $pageNum in $buildrootPages

-             <option value="$pageNum"#if $pageNum == $buildrootCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $buildrootStart > 0

-         <a href="builds?start=#echo $buildrootStart - $buildrootRange #$util.passthrough_except($self)">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalBuildroots != 0

-         <strong>Buildroots #echo $buildrootStart + 1 # through #echo $buildrootStart + $buildrootCount # of $totalBuildroots</strong>

-         #end if

-         #if $buildrootStart + $buildrootCount < $totalBuildroots

-         <a href="builds?start=#echo $buildrootStart + $buildrootRange#$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

file removed
-190
@@ -1,190 +0,0 @@ 

- #import koji

- #from kojiweb import util

- 

- #attr _PASSTHROUGH = ['userID', 'tagID', 'packageID', 'order', 'prefix', 'state', 'inherited', 'latest', 'type']

- 

- #include "includes/header.chtml"

- 

- #@util.safe_return

- #def getDescription()

- #if $latest

- Latest

- #elif $state != None

- $util.stateName($state).capitalize()

- #end if

- #if $type

- $type.capitalize()

- #end if

- Builds

- #if $package

- of <a href="packageinfo?packageID=$package.id">$package.name</a>

- #end if

- #if $user

- by <a href="userinfo?userID=$user.id">$user.name</a>

- #end if

- #if $prefix

- starting with &quot;$prefix&quot;

- #end if

- #if $tag

- in tag <a href="taginfo?tagID=$tag.id">$tag.name</a>

- #end if

- #end def

- 

-   <h4>$getDescription()</h4>

- 

-   <table class="data-list">

-     <tr>

-       <td colspan="#if $tag then '6' else '5'#">

-         <table class="nested">

-         <tr><td>

-         #if $tag

-         <strong>Latest</strong>:

-         </td><td>

-         <select name="latest" class="filterlist" onchange="javascript: window.location = 'builds?latest=' + this.value + '$util.passthrough_except($self, 'latest')';">

-           <option value="1" #if $latest then 'selected' else ''#>yes</option>

-           <option value="0" #if not $latest then 'selected' else ''#>no</option>

-         </select>

-         #else

-         <strong>State</strong>:

-         </td><td>

-         <select name="state" class="filterlist" onchange="javascript: window.location = 'builds?state=' + this.value + '$util.passthrough_except($self, 'state')';">

-           <option value="all">all</option>

-           #for $stateOpt in ['BUILDING', 'COMPLETE', 'FAILED', 'CANCELED']

-           <option value="$koji.BUILD_STATES[$stateOpt]" #if $state == $koji.BUILD_STATES[$stateOpt] then 'selected' else ''#>$stateOpt.lower()</option>

-           #end for

-         </select>

-         #end if

-         </td><td>

-         <strong>Built by</strong>:

-         </td><td>

-         <select name="userID" class="filterlist" onchange="javascript: window.location = 'builds?userID=' + this.value + '$util.passthrough_except($self, 'userID')';">

-           <option value="" #if not $user then 'selected' else ''#>everyone</option>

-           #if $loggedInUser

-           <option value="$loggedInUser.name">me</option>

-           #end if

-           #for $userOption in $users

-           <option value="$userOption.name" #if $userOption.name == ($user and $user.name or None) then 'selected' else ''#>$userOption.name</option>

-           #end for

-         </select>

-         </td></tr>

-         <tr>

-         <td>

-         <strong>Type</strong>:

-         </td>

-         <td>

-         <select name="type" class="filterlist" onchange="javascript: window.location='builds?type=' + this.value + '$util.passthrough_except($self, 'type')';">

-           <option value="all" #if not $type then 'selected' else ''#>all</option>

-           #for $btype in $btypes

-           <option value="$btype" #if $type == $btype then 'selected' else ''#>$btype</option>

-           #end for

-         </select>

-         </td>

-         #if $tag

-         <td>

-         <strong>Inherited</strong>:

-         </td><td>

-         <select name="inherited" class="filterlist" onchange="javascript: window.location = 'builds?inherited=' + this.value + '$util.passthrough_except($self, 'inherited')';">

-           <option value="1" #if $inherited then 'selected' else ''#>yes</option>

-           <option value="0" #if not $inherited then 'selected' else ''#>no</option>

-         </select>

-         </td>

-         #end if

-         </tr>

-         </table>

-       </td>

-     </tr>

-     <tr>

-       <td class="charlist" colspan="#if $tag then '6' else '5'#">

-         #for $char in $chars

-         #if $prefix == $char

-         <strong>$char</strong>

-         #else

-         <a href="builds?prefix=$char$util.passthrough_except($self, 'prefix')">$char</a>

-         #end if

-         | 

-         #end for

-         #if $prefix

-         <a href="builds?${util.passthrough_except($self, 'prefix', prefix='')}">all</a>

-         #else

-         <strong>all</strong>

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <td class="paginate" colspan="#if $tag then '6' else '5'#">

-         #if $len($buildPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'builds?start=' + this.value * $buildRange + '$util.passthrough_except($self)';">

-             #for $pageNum in $buildPages

-             <option value="$pageNum"#if $pageNum == $buildCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $buildStart > 0

-         <a href="builds?start=#echo $buildStart - $buildRange #$util.passthrough_except($self)">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalBuilds != 0

-         <strong>Builds #echo $buildStart + 1 # through #echo $buildStart + $buildCount # of $totalBuilds</strong>

-         #end if

-         #if $buildStart + $buildCount < $totalBuilds

-         <a href="builds?start=#echo $buildStart + $buildRange#$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="builds?order=$util.toggleOrder($self, 'build_id')$util.passthrough_except($self, 'order')">ID</a> $util.sortImage($self, 'build_id')</th>

-       <th><a href="builds?order=$util.toggleOrder($self, 'nvr')$util.passthrough_except($self, 'order')">NVR</a> $util.sortImage($self, 'nvr')</th>

-       #if $tag

-       <th><a href="builds?order=$util.toggleOrder($self, 'tag_name')$util.passthrough_except($self, 'order')">Tag</a> $util.sortImage($self, 'tag_name')</th>

-       #end if

-       <th><a href="builds?order=$util.toggleOrder($self, 'owner_name')$util.passthrough_except($self, 'order')">Built by</a> $util.sortImage($self, 'owner_name')</th>

-       <th><a href="builds?order=$util.toggleOrder($self, 'completion_time')$util.passthrough_except($self, 'order')">Finished</a> $util.sortImage($self, 'completion_time')</th>

-       <th><a href="builds?order=$util.toggleOrder($self, 'state')$util.passthrough_except($self, 'order')">State</a> $util.sortImage($self, 'state')</th>

-     </tr>

-     #if $len($builds) > 0

-       #for $build in $builds

-         <tr class="$util.rowToggle($self)">

-           <td>$build.build_id</td>

-           <td><a href="buildinfo?buildID=$build.build_id">$koji.buildLabel($build)</a></td>

-           #if $tag

-           <td><a href="taginfo?tagID=$build.tag_id">$build.tag_name</a></td>

-           #end if

-           <td class="user-$build.owner_name"><a href="userinfo?userID=$build.owner_id">$build.owner_name</a></td>

-           <td>$util.formatTime($build.completion_time)</td>

-           #set $stateName = $util.stateName($build.state)

-           <td class="$stateName">$util.stateImage($build.state)</td>

-         </tr>

-       #end for

-     #else

-       <tr class="row-odd">

-         <td colspan="#if $tag then '6' else '5'#">No builds</td>

-       </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="#if $tag then '6' else '5'#">

-         #if $len($buildPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'builds?start=' + this.value * $buildRange + '$util.passthrough_except($self)';">

-             #for $pageNum in $buildPages

-             <option value="$pageNum"#if $pageNum == $buildCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $buildStart > 0

-         <a href="builds?start=#echo $buildStart - $buildRange #$util.passthrough_except($self)">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalBuilds != 0

-         <strong>Builds #echo $buildStart + 1 # through #echo $buildStart + $buildCount # of $totalBuilds</strong>

-         #end if

-         #if $buildStart + $buildCount < $totalBuilds

-         <a href="builds?start=#echo $buildStart + $buildRange#$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,65 +0,0 @@ 

- #from kojiweb import util

- 

- #@util.safe_return

- #def printOption(value, label=None)

- #if not $label

- #set $label = $value

- #end if

- <option value="$value"#if $value == $days then ' selected' else ''#>$label</option>

- #end def

- 

- #set $numTotal = $numSucceeded + $numFailed + $numCanceled

- 

- #include "includes/header.chtml"

- 

-   <h4>Succeeded/Failed/Canceled Builds#if $days != -1 then ' in the last %i days' % $days else ''#</h4>

-   <table class="data-list">

-     <tr style="text-align: left">

-       <td colspan="3">

-         <form action="">

-           Show last

-           <select onchange="javascript: window.location = 'buildsbystatus?days=' + this.value;">

-             $printOption(1)

-             $printOption(3)

-             $printOption(5)

-             $printOption(7)

-             $printOption(14)

-             $printOption(30)

-             $printOption(60)

-             $printOption(90)

-             $printOption(120)

-             $printOption(180)

-             $printOption(365)

-             $printOption(-1, 'all')

-           </select> days

-         </form>

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th>Type</th>

-       <th>Builds</th>

-       <th>&nbsp;</th>

-     </tr>

-     <tr class="row-odd taskclosed">

-       <td>Succeeded</td>

-       <td width="#echo $graphWidth + 5#"><img src="$util.themePath('images/1px.gif')" width="#echo $increment * $numSucceeded#" height="15" class="graphrow" alt="graph row"/></td>

-       <td>$numSucceeded</td>

-     </tr>

-     <tr class="row-even taskfailed">

-       <td>Failed</td>

-       <td width="#echo $graphWidth + 5#"><img src="$util.themePath('images/1px.gif')" width="#echo $increment * $numFailed#" height="15" class="graphrow" alt="graph row"/></td>

-       <td>$numFailed</td>

-     </tr>

-     <tr class="row-odd taskcanceled">

-       <td>Canceled</td>

-       <td width="#echo $graphWidth + 5#"><img src="$util.themePath('images/1px.gif')" width="#echo $increment * $numCanceled#" height="15" class="graphrow" alt="graph row"/></td>

-       <td>$numCanceled</td>

-     </tr>

-     <tr class="row-even">

-       <td>Total</td>

-       <td></td>

-       <td>$numTotal</td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,101 +0,0 @@ 

- #from kojiweb import util

- #from urllib.parse import quote

- 

- #@util.safe_return

- #def printOption(value, label=None)

- #if not $label

- #set $label = $value

- #end if

- <option value="$value"#if $value == $days then ' selected' else ''#>$label</option>

- #end def

- 

- #include "includes/header.chtml"

- 

-   <h4>Builds by Target#if $days != -1 then ' in the last %i days' % $days else ''#</h4>

-   <table class="data-list">

-     <tr style="text-align: left">

-       <td colspan="3">

-         <form action="">

-           Show last

-           <select onchange="javascript: window.location = 'buildsbytarget?days=' + this.value + '$util.passthrough($self, 'order')';">

-             $printOption(1)

-             $printOption(3)

-             $printOption(5)

-             $printOption(7)

-             $printOption(14)

-             $printOption(30)

-             $printOption(60)

-             $printOption(90)

-             $printOption(120)

-             $printOption(-1, 'all')

-           </select> days

-         </form>

-       </td>

-     </tr>

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($targetPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'buildsbytarget?start=' + this.value * $targetRange + '$util.passthrough($self, 'days', 'order')';">

-             #for $pageNum in $targetPages

-             <option value="$pageNum"#if $pageNum == $targetCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $targetStart > 0

-         <a href="buildsbytarget?start=#echo $targetStart - $targetRange #$util.passthrough($self, 'days', 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalTargets != 0

-         <strong>Build Targets #echo $targetStart + 1 # through #echo $targetStart + $targetCount # of $totalTargets</strong>

-         #end if

-         #if $targetStart + $targetCount < $totalTargets

-         <a href="buildsbytarget?start=#echo $targetStart + $targetRange#$util.passthrough($self, 'days', 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="buildsbytarget?order=$util.toggleOrder($self, 'name')$util.passthrough($self, 'days')">Name</a> $util.sortImage($self, 'name')</th>

-       <th><a href="buildsbytarget?order=$util.toggleOrder($self, 'builds')$util.passthrough($self, 'days')">Builds</a> $util.sortImage($self, 'builds')</th>

-       <th>&nbsp;</th>

-     </tr>

-     #if $len($targets) > 0

-     #for $target in $targets

-     <tr class="$util.rowToggle($self)">

-       <td><a href="buildtargetinfo?name=$quote($target.name)">$target.name</a></td>

-       <td width="#echo $graphWidth + 5#"><img src=$util.themePath('images/1px.gif') width="#echo $increment * $target.builds#" height="15" class="graphrow" alt="graph row"/></td>

-       <td>$target.builds</td>

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td colspan="3">No builds</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($targetPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'buildsbytarget?start=' + this.value * $targetRange + '$util.passthrough($self, 'days', 'order')';">

-             #for $pageNum in $targetPages

-             <option value="$pageNum"#if $pageNum == $targetCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $targetStart > 0

-         <a href="buildsbytarget?start=#echo $targetStart - $targetRange #$util.passthrough($self, 'days', 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalTargets != 0

-         <strong>Build Targets #echo $targetStart + 1 # through #echo $targetStart + $targetCount # of $totalTargets</strong>

-         #end if

-         #if $targetStart + $targetCount < $totalTargets

-         <a href="buildsbytarget?start=#echo $targetStart + $targetRange#$util.passthrough($self, 'days', 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,73 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <h4>Builds by User</h4>

-   <table class="data-list">

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($userBuildPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'buildsbyuser?start=' + this.value * $userBuildRange + '$util.passthrough($self, 'order')';">

-             #for $pageNum in $userBuildPages

-             <option value="$pageNum"#if $pageNum == $userBuildCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $userBuildStart > 0

-         <a href="buildsbyuser?start=#echo $userBuildStart - $userBuildRange #$util.passthrough($self, 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalUserBuilds != 0

-         <strong>Users #echo $userBuildStart + 1 # through #echo $userBuildStart + $userBuildCount # of $totalUserBuilds</strong>

-         #end if

-         #if $userBuildStart + $userBuildCount < $totalUserBuilds

-         <a href="buildsbyuser?start=#echo $userBuildStart + $userBuildRange#$util.passthrough($self, 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="buildsbyuser?order=$util.toggleOrder($self, 'name')">Name</a> $util.sortImage($self, 'name')</th>

-       <th><a href="buildsbyuser?order=$util.toggleOrder($self, 'builds')">Builds</a> $util.sortImage($self, 'builds')</th>

-       <th>&nbsp;</th>

-     </tr>

-     #if $len($userBuilds) > 0

-     #for $userBuild in $userBuilds

-     <tr class="$util.rowToggle($self)">

-       <td><a href="userinfo?userID=$userBuild.id">$userBuild.name</a></td>

-       <td width="#echo $graphWidth + 5#"><img src="$util.themePath('images/1px.gif')" width="#echo $increment * $userBuild.builds#" height="15" class="graphrow" alt="graph row"/></td>

-       <td>$userBuild.builds</td>

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td colspan="3">No users</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($userBuildPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'buildsbyuser?start=' + this.value * $userBuildRange + '$util.passthrough($self, 'order')';">

-             #for $pageNum in $userBuildPages

-             <option value="$pageNum"#if $pageNum == $userBuildCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $userBuildStart > 0

-         <a href="buildsbyuser?start=#echo $userBuildStart - $userBuildRange #$util.passthrough($self, 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalUserBuilds != 0

-         <strong>Users #echo $userBuildStart + 1 # through #echo $userBuildStart + $userBuildCount # of $totalUserBuilds</strong>

-         #end if

-         #if $userBuildStart + $userBuildCount < $totalUserBuilds

-         <a href="buildsbyuser?start=#echo $userBuildStart + $userBuildRange#$util.passthrough($self, 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,30 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <h4>Information for target <a href="buildtargetinfo?targetID=$target.id">$target.name</a></h4>

- 

-   <table>

-     <tr>

-       <th>Name</th><td>$target.name</td>

-     </tr>

-     <tr>

-       <th>ID</th><td>$target.id</td>

-     </tr>

-     <tr>

-       <th>Build Tag</th><td><a href="taginfo?tagID=$buildTag.id">$buildTag.name</a></td>

-     </tr>

-     <tr>

-       <th>Destination Tag</th><td><a href="taginfo?tagID=$destTag.id">$destTag.name</a></td>

-     </tr>

-     #if 'admin' in $perms

-     <tr>

-       <td colspan="2"><a href="buildtargetedit?targetID=$target.id$util.authToken($self)">Edit</a></td>

-     </tr>

-     <tr>

-       <td colspan="2"><a href="buildtargetdelete?targetID=$target.id$util.authToken($self)">Delete</a></td>

-     </tr>

-     #end if

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,76 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <h4>Build Targets</h4>

-   <table class="data-list">

-     <tr>

-       <td class="paginate" colspan="2">

-         #if $len($targetPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'buildtargets?start=' + this.value * $targetRange + '$util.passthrough($self, 'order')';">

-             #for $pageNum in $targetPages

-             <option value="$pageNum"#if $pageNum == $targetCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $targetStart > 0

-         <a href="buildtargets?start=#echo $targetStart - $targetRange #$util.passthrough($self, 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalTargets != 0

-         <strong>Targets #echo $targetStart + 1 # through #echo $targetStart + $targetCount # of $totalTargets</strong>

-         #end if

-         #if $targetStart + $targetCount < $totalTargets

-         <a href="buildtargets?start=#echo $targetStart + $targetRange#$util.passthrough($self, 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="buildtargets?order=$util.toggleOrder($self, 'id')">ID</a> $util.sortImage($self, 'id')</th>

-       <th><a href="buildtargets?order=$util.toggleOrder($self, 'name')">Name</a> $util.sortImage($self, 'name')</th>

-     </tr>

-     #if $len($targets) > 0

-     #for $target in $targets

-     <tr class="$util.rowToggle($self)">

-       <td>$target.id</td>

-       <td><a href="buildtargetinfo?targetID=$target.id">$target.name</a></td>

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td colspan="2">No build targets</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="2">

-         #if $len($targetPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'buildtargets?start=' + this.value * $targetRange + '$util.passthrough($self, 'order')';">

-             #for $pageNum in $targetPages

-             <option value="$pageNum"#if $pageNum == $targetCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $targetStart > 0

-         <a href="buildtargets?start=#echo $targetStart - $targetRange #$util.passthrough($self, 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalTargets != 0

-         <strong>Targets #echo $targetStart + 1 # through #echo $targetStart + $targetCount # of $totalTargets</strong>

-         #end if

-         #if $targetStart + $targetCount < $totalTargets

-         <a href="buildtargets?start=#echo $targetStart + $targetRange#$util.passthrough($self, 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

-   

-   #if 'admin' in $perms

-   <br/>

-   <a href="buildtargetcreate$util.authToken($self, first=True)">Create new Build Target</a>

-   #end if

- 

- #include "includes/footer.chtml"

@@ -1,64 +0,0 @@ 

- #import datetime

- #from kojiweb import util

- #from urllib.parse import quote

- 

- #include "includes/header.chtml"

-   #if $rpm

-   <h4>Information for file <a href="fileinfo?rpmID=$rpm.id&amp;filename=$quote($file.name)">$file.name</a></h4>

-   #elif $archive

-   <h4>Information for file <a href="fileinfo?archiveID=$archive.id&amp;filename=$quote($file.name)">$file.name</a></h4>

-   #end if

- 

-   <table>

-     <tr>

-       <th>Name</th><td>$file.name</td>

-     </tr>

-     #if $rpm

-     <tr>

-       <th>Digest ($file.digest_algo)</th><td>$file.digest</td>

-     </tr>

-     #end if

-     <tr>

-       <th>Size</th><td><span title="$util.formatThousands($file.size)">$util.formatNatural($file.size)</span></td>

-     </tr>

-     #if 'mtime' in $file and $file.mtime

-     <tr>

-       <th>Modification time</th><td>$util.formatTimeLong($file.mtime)</td>

-     </tr>

-     #end if

-     #if 'user' in $file and $file.user

-     <tr>

-       <th>User</th><td>$file.user</td>

-     </tr>

-     #end if

-     #if 'group' in $file and $file.group

-     <tr>

-       <th>Group</th><td>$file.group</td>

-     </tr>

-     #end if

-     #if 'mode' in $file and $file.mode

-     <tr>

-       <th>Mode</th><td class="rpmheader">$util.formatMode($file.mode)</td>

-     </tr>

-     #end if

-     #if $rpm

-     <tr>

-       <th>Flags</th>

-       <td>

-         #for flag in $util.formatFileFlags($file.flags)

-         $flag<br/>

-         #end for

-       </td>

-     </tr>

-     <tr>

-       #set $epoch = ($rpm.epoch != None and $str($rpm.epoch) + ':' or '')

-       <th>RPM</th><td><a href="rpminfo?rpmID=$rpm.id">$rpm.name-$epoch$rpm.version-$rpm.release.${rpm.arch}.rpm</a></td>

-     </tr>

-     #elif $archive

-     <tr>

-       <th>Archive</th><td><a href="archiveinfo?archiveID=$archive.id">$archive.filename</a></td>

-     </tr>

-     #end if

-   </table>

- 

- #include "includes/footer.chtml"

file removed
-173
@@ -1,173 +0,0 @@ 

- #from kojiweb import util

- 

- #@util.safe_return

- #def headerState($state)

-   #if $state == 'enabled'

- Enabled hosts

-   #elif $state == 'disabled'

- Disabled hosts

-   #else

- Hosts

-   #end if

- #end def

- 

- #@util.safe_return

- #def headerReady($ready)

-   #if $ready == 'ready'

- which are ready

-   #elif $ready == 'notready'

- which are not ready

-   #end if

- #end def

- 

- #@util.safe_return

- #def headerArch($arch)

-   #if $arch == 'all'

- on all arches

-   #else

- on $arch arch

-   #end if

- #end def

- 

- #@util.safe_return

- #def headerChannel($channel)

-   #if $channel == 'all'

- in all channels

-   #else

- in $channel channel

-   #end if

- #end def

- 

- #attr _PASSTHROUGH = ['state', 'order', 'ready', 'channel', 'arch']

- 

- #include "includes/header.chtml"

- 

-   <h4>$headerState($state) $headerReady($ready) $headerArch($arch) $headerChannel($channel)</h4>

-   <table class="data-list">

-     <tr>

-       <td colspan="9">

-         <table class="nested">

-           <tr><td>

-               <strong>State</strong>:

-           </td><td>

-               <select name="state" class="filterlist" onchange="javascript: window.location = 'hosts?state=' + this.value + '$util.passthrough_except($self, 'state')';">

-                 <option value="enabled" #if $state == 'enabled' then 'selected' else ''#>enabled</option>

-                 <option value="disabled" #if $state == 'disabled' then 'selected' else ''#>disabled</option>

-                 <option value="all" #if $state == 'all' then 'selected' else ''#>all</option>

-               </select>

-           </td>

-           <td>

-               <strong>Channels</strong>:

-           </td><td>

-               <select name="channel" class="filterlist" onchange="javascript: window.location = 'hosts?channel=' + this.value + '$util.passthrough_except($self, 'channel')';">

-                 <option value="all" #if not $channel then 'selected' else ''#>all</option>

-                 #for $chan in $channels

-                 <option value="$chan.name" #if $chan.name == $channel then 'selected' else ''#>$chan.name</option>

-                 #end for

-               </select>

-           </td>

-           </tr>

-           <tr><td>

-               <strong>Ready</strong>:

-           </td><td>

-               <select name="ready" class="filterlist" onchange="javascript: window.location = 'hosts?ready=' + this.value + '$util.passthrough_except($self, 'ready')';">

-                 <option value="yes" #if $ready == 'yes' then 'selected' else ''#>yes</option>

-                 <option value="no" #if $ready == 'no' then 'selected' else ''#>no</option>

-                 <option value="all" #if $ready== 'all' then 'selected' else ''#>all</option>

-               </select>

-           </td><td>

-               <strong>Arches</strong>:

-           </td><td>

-               <select name="arch" class="filterlist" onchange="javascript: window.location = 'hosts?arch=' + this.value + '$util.passthrough_except($self, 'arch')';">

-                 <option value="all" #if not $arch then 'selected' else ''#>all</option>

-                 #for $arch_item in $arches

-                 <option value="$arch_item" #if $arch_item == $arch then 'selected' else ''#>$arch_item</option>

-                 #end for

-               </select>

-           </td></tr>

-         </table>

-       </td>

-     </tr>

-     <tr>

-       <td class="paginate" colspan="9">

-         #if $len($hostPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'hosts?start=' + this.value * $hostRange + '$util.passthrough_except($self)';">

-             #for $pageNum in $hostPages

-             <option value="$pageNum"#if $pageNum == $hostCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $hostStart > 0

-         <a href="hosts?start=#echo $hostStart - $hostRange #$util.passthrough_except($self)">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalHosts != 0

-         <strong>Hosts #echo $hostStart + 1 # through #echo $hostStart + $hostCount # of $totalHosts</strong>

-         #end if

-         #if $hostStart + $hostCount < $totalHosts

-         <a href="hosts?start=#echo $hostStart + $hostRange#$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="hosts?order=$util.toggleOrder($self, 'id')$util.passthrough_except($self, 'order')">ID</a> $util.sortImage($self, 'id')</th>

-       <th><a href="hosts?order=$util.toggleOrder($self, 'name')$util.passthrough_except($self, 'order')">Name</a> $util.sortImage($self, 'name')</th>

-       <th><a href="hosts?order=$util.toggleOrder($self, 'arches')$util.passthrough_except($self, 'order')">Arches</a> $util.sortImage($self, 'arches')</th>

-       <th><a href="hosts?order=$util.toggleOrder($self, 'channels')$util.passthrough_except($self, 'order')">Channels</a> $util.sortImage($self, 'channels')</th>

-       <th><a href="hosts?order=$util.toggleOrder($self, 'enabled')$util.passthrough_except($self, 'order')">Enabled?</a> $util.sortImage($self, 'enabled')</th>

-       <th><a href="hosts?order=$util.toggleOrder($self, 'ready')$util.passthrough_except($self, 'order')">Ready?</a> $util.sortImage($self, 'ready')</th>

-       <th><a href="hosts?order=$util.toggleOrder($self, 'task_load')$util.passthrough_except($self, 'order')">Load</a> $util.sortImage($self, 'task_load')</th>

-       <th><a href="hosts?order=$util.toggleOrder($self, 'capacity')$util.passthrough_except($self, 'order')">Cap.</a> $util.sortImage($self, 'capacity')</th>

-       <th><a href="hosts?order=$util.toggleOrder($self, 'last_update')$util.passthrough_except($self, 'order')">Last Update</a> $util.sortImage($self, 'last_update')</th>

-     </tr>

-     #if $len($hosts) > 0

-       #for $host in $hosts

-         <tr class="$util.rowToggle($self)">

-           <td>$host.id</td>

-           <td><a href="hostinfo?hostID=$host.id">$host.name</a></td>

-           <td>$host.arches</td>

-           <td>

-               #for $channame, $chan_id, $chan_enabled in zip($host.channels, $host.channels_id, $host.channels_enabled)

-                 <a href="channelinfo?channelID=$chan_id" class="$chan_enabled">$channame</a>

-               #end for

-           </td>

-           <td class="$str($bool($host.enabled)).lower()">#if $host.enabled then $util.imageTag('yes') else $util.imageTag('no')#</td>

-           <td class="$str($bool($host.ready)).lower()">#if $host.ready then $util.imageTag('yes') else $util.imageTag('no')#</td>

-           <td>#echo '%.2f' % $host.task_load#</td>

-           <td>$host.capacity</td>

-           <td>$util.formatTime($host.last_update)</td>

-         </tr>

-       #end for

-     #else

-       <tr class="row-odd">

-         <td colspan="9">No hosts</td>

-       </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="9">

-         #if $len($hostPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'hosts?start=' + this.value * $hostRange + '$util.passthrough_except($self)';">

-             #for $pageNum in $hostPages

-             <option value="$pageNum"#if $pageNum == $hostCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $hostStart > 0

-         <a href="hosts?start=#echo $hostStart - $hostRange #$util.passthrough_except($self)">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalHosts != 0

-         <strong>Hosts #echo $hostStart + 1 # through #echo $hostStart + $hostCount # of $totalHosts</strong>

-         #end if

-         #if $hostStart + $hostCount < $totalHosts

-         <a href="hosts?start=#echo $hostStart + $hostRange#$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,60 +0,0 @@ 

- #import koji

- #import koji.util

- #from os.path import basename

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

- <h4>Information for image <a href="imageinfo?imageID=$image.id">$image.filename</a></h4>

- 

- <table>

-   <tr>

-     <th>ID</th><td>$image.id</td>

-   </tr>

-   <tr>

-     <th>File Name</th><td>$image.filename</a></td>

-   </tr>

-   <tr>

-     <th>File Size</th><td><span title="$util.formatThousands($image.filesize)">$util.formatNatural($image.filesize)</span></td>

-   </tr>

-   <tr>

-     <th>Arch</th><td>$image.arch</td>

-   </tr>

-   <tr>

-     <th>Media Type</th><td>$image.mediatype</td>

-   </tr>

-   <tr>

-     #if $len($image.hash) == 32

-       <th>Digest (md5)</th><td>$image.hash</td>

-     #elif $len($image.hash) == 40

-       <th>Digest (sha1)</th><td>$image.hash</td>

-     #elif $len($image.hash) == 64

-       <th>Digest (sha256)</th><td>$image.hash</td>

-     #elif $len($image.hash) == 96

-       <th>Digest (sha384)</th><td>$image.hash</td>

-     #elif $len($image.hash) == 128

-       <th>Digest (sha512)</th><td>$image.hash</td>

-     #else

-       <th>Hash </th><td>$image.hash</td>

-     #end if

-   </tr>

-   <tr>

-     <th>Task</th><td><a href="taskinfo?taskID=$task.id" class="task$util.taskState($task.state)">$koji.taskLabel($task)</a></td>

-   </tr>

-   <tr>

-     <th>Buildroot</th><td><a href="buildrootinfo?buildrootID=$buildroot.id">/var/lib/mock/$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a></td>

-   </tr>

-   <tr>

-     <th colspan="2"><a href="rpmlist?imageID=$image.id&amp;type=image" title="RPMs that where installed into the LiveCD">Included RPMs</a></th>

-   </tr>

-   <tr>

-     <th colspan="2"><a href="$imageBase/$image.filename">Download Image</a> (<a href="$imageBase/data/logs/$image.arch/">build logs</a>)</th>

-   </tr>

-   #if $image.get('xmlfile', None)

-   <tr>

-     <th colspan="2"><a href="$imageBase/$image.xmlfile">Download XML Description</a></th>

-   </tr>

-   #end if

- </table>

- 

- #include "includes/footer.chtml"

@@ -1,27 +0,0 @@ 

- #from kojiweb import util

-         </div>

- 

-         <p id="footer">

-           Copyright &copy; 2006-2016 Red Hat, Inc.

-           <a href="https://pagure.io/koji/"><img src="$util.themePath('images/powered-by-koji.png')" alt="Powered By Koji" id="PoweredByKojiLogo"/></a>

-         </p>

- 

- #set $localfooterpath=$util.themePath("extra-footer.html", local=True)

- #if os.path.exists($localfooterpath)

- #if $literalFooter

- #set $localfooter=$util.SafeValue("".join(open($localfooterpath, 'rt', encoding='utf-8').readlines()))

- $localfooter

- #else

- #include $localfooterpath

- #end if

- #end if

- 

-       </div>

-     </div>

- #set $localbottompath=$util.themePath("extra-bottom.html", local=True)

- #if os.path.exists($localbottompath)

- #set $localbottom=$util.SafeValue("".join(open($localbottompath, 'rt', encoding='utf-8').readlines()))

- $localbottom

- #end if

-   </body>

- </html>

file removed
-161
@@ -1,161 +0,0 @@ 

- #import koji

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <div class="pageHeader">$welcomeMessage</div>

- 

-   <div class="dataHeader noPaginate" id="buildlist">#if $user then 'Your ' else ''#Recent Builds</div>

-   <table class="data-list">

-     <tr class="list-header">

-       <th>ID $util.sortImage(self, 'id')</th>

-       <th>NVR</th>

-       #if not $user

-       <th>Built by</th>

-       #end if

-       <th>Finished</th>

-       <th>State</th>

-     </tr>

-     #for $build in $builds

-     <tr class="$util.rowToggle($self)">

-       #set $stateName = $util.stateName($build.state)

-       <td>$build.build_id</td>

-       <td><a href="buildinfo?buildID=$build.build_id">$build.nvr</a></td>

-       #if not $user

-       <td class="user-$build.owner_name"><a href="userinfo?userID=$build.owner_id">$build.owner_name</a></td>

-       #end if

-       <td>$util.formatTime($build.completion_ts)</td>

-       <td class="$stateName">$util.stateImage($build.state)</td>

-     </tr>

-     #end for

-     #if not $builds

-     <tr class="row-odd">

-       <td colspan="3">No builds</td>

-     </tr>

-     #end if

-   </table>

- 

-   <br/>

- 

-   <div class="dataHeader noPaginate" id="tasklist">#if $user then 'Your ' else ''#Recent Tasks</div>

-   <table class="data-list">

-     <tr class="list-header">

-       <th>ID $util.sortImage($self, 'id')</th>

-       <th>Type</th>

-       #if not $user

-       <th>Owner</th>

-       #end if

-       <th>Arch</th>

-       <th>Finished</th>

-       <th>State</th>

-     </tr>

-     #for $task in $tasks

-     #set $scratch = $util.taskScratchClass($task)

-     <tr class="$util.rowToggle($self) $scratch">

-       #set $state = $util.taskState($task.state)

-       <td>$task.id</td>

-       <td><a href="taskinfo?taskID=$task.id" class="task$state" title="$state">$koji.taskLabel($task)</a></td>

-       #if not $user

-       <td class="user-$task.owner_name">

-         #if $task.owner_type == $koji.USERTYPES['HOST']

-         <a href="hostinfo?userID=$task.owner">$task.owner_name</a>

-         #else

-         <a href="userinfo?userID=$task.owner">$task.owner_name</a>

-         #end if

-       </td>

-       #end if

-       <td>$task.arch</td>

-       <td>$util.formatTime($task.completion_ts)</td>

-       <td class="task$state">$util.imageTag($state)</td>

-     </tr>

-     #end for

-     #if not $tasks

-       <tr class="row-odd">

-         <td colspan="5">No tasks</td>

-       </tr>

-     #end if

-   </table>

- 

-   #if $user

-   <br/>

- 

-   <div class="dataHeader" id="packagelist">Your Packages</div>

-   <table class="data-list">

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($packagePages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'index?packageStart=' + this.value * $packageRange + '$util.passthrough($self, 'packageOrder', 'buildOrder', 'buildStart', 'taskOrder', 'taskStart')#packagelist';">

-             #for $pageNum in $packagePages

-             <option value="$pageNum"#if $pageNum == $packageCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $packageStart > 0

-         <a href="index?packageStart=#echo $packageStart - $packageRange #$util.passthrough($self, 'packageOrder', 'buildOrder', 'buildStart', 'taskOrder', 'taskStart')#packagelist">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalPackages != 0

-         <strong>Package #echo $packageStart + 1 # through #echo $packageStart + $packageCount # of $totalPackages</strong>

-         #end if

-         #if $packageStart + $packageCount < $totalPackages

-         <a href="index?packageStart=#echo $packageStart + $packageRange#$util.passthrough($self, 'packageOrder', 'buildOrder', 'buildStart', 'taskOrder', 'taskStart')#packagelist">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="index?packageOrder=$util.toggleOrder($self, 'package_name', 'packageOrder')$util.passthrough($self, 'buildOrder', 'buildStart', 'taskOrder', 'taskStart')#packagelist">Name</a> $util.sortImage($self, 'package_name', 'packageOrder')</th>

-       <th><a href="index?packageOrder=$util.toggleOrder($self, 'tag_name', 'packageOrder')$util.passthrough($self, 'buildOrder', 'buildStart', 'taskOrder', 'taskStart')#packagelist">Tag</a> $util.sortImage($self, 'tag_name', 'packageOrder')</th>

-       <th><a href="index?packageOrder=$util.toggleOrder($self, 'blocked', 'packageOrder')$util.passthrough($self, 'buildOrder', 'buildStart', 'taskOrder', 'taskStart')#packagelist">Included?</a> $util.sortImage($self, 'blocked', 'packageOrder')</th>

-     </tr>

-     #for $package in $packages

-     <tr class="$util.rowToggle($self)">

-       <td><a href="packageinfo?packageID=$package.package_id">$package.package_name</a></td>

-       <td><a href="taginfo?tagID=$package.tag_id">$package.tag_name</a></td>

-       #set $included = $package.blocked and 'no' or 'yes'

-       <td>$util.imageTag($included)</td>

-     </tr>

-     #end for

-     #if $totalPackages == 0

-     <tr class="row-odd">

-       <td colspan="3">No packages</td>

-     </tr>

-     #end if

-   </table>

-   

-   <br/>

-   

-   <div class="dataHeader" id="notificationlist">Your Notifications</div>

-   <table class="data-list">

-     <tr>

-       <td colspan="5"></td>

-     </tr>

-     <tr class="list-header">

-       <th>Package</th>

-       <th>Tag</th>

-       <th>Type</th>

-       <th></th>

-       <th></th>

-     </tr>

-     #for $notif in $notifs

-     <tr class="$util.rowToggle($self)">

-       <td>#if $notif.package then $notif.package.name else 'all'#</td>

-       <td>#if $notif.tag then $notif.tag.name else 'all'#</td>

-       <td>#if $notif.success_only then 'success only' else 'all'#</td>

-       <td><a href="notificationedit?notificationID=$notif.id$util.authToken($self)">edit</a></td>

-       <td><a href="notificationdelete?notificationID=$notif.id$util.authToken($self)">delete</a></td>

-     </tr>

-     #end for

-     #if $len($notifs) == 0

-     <tr class="row-odd">

-       <td colspan="5">No notifications</td>

-     </tr>

-     #end if

-   </table>

- 

-   <br/>

-   <a href="notificationcreate$util.authToken($self, first=True)">Add a Notification</a>

-   #end if

-     

- #include "includes/footer.chtml"

file modified
+81 -54
@@ -384,7 +384,9 @@ 

      values['user'] = user

      values['welcomeMessage'] = environ['koji.options']['KojiGreeting']

  

-     return _genHTML(environ, 'index.chtml')

+     values['koji'] = koji

+ 

+     return _genHTML(environ, 'index.html.j2')

  

  

  def notificationedit(environ, notificationID):
@@ -430,7 +432,7 @@ 

          tags = server.listTags(queryOpts={'order': 'name'})

          values['tags'] = tags

  

-         return _genHTML(environ, 'notificationedit.chtml')

+         return _genHTML(environ, 'notificationedit.html.j2')

  

  

  def notificationcreate(environ):
@@ -475,7 +477,7 @@ 

          tags = server.listTags(queryOpts={'order': 'name'})

          values['tags'] = tags

  

-         return _genHTML(environ, 'notificationedit.chtml')

+         return _genHTML(environ, 'notificationedit.html.j2')

  

  

  def notificationdelete(environ, notificationID):
@@ -635,7 +637,10 @@ 

          for task, [descendents] in zip(tasks, descendentList):

              task['descendents'] = descendents

  

-     return _genHTML(environ, 'tasks.chtml')

+     values['S'] = SafeValue

+     values['koji'] = koji

+ 

+     return _genHTML(environ, 'tasks.html.j2')

  

  

  def taskinfo(environ, taskID):
@@ -792,7 +797,10 @@ 

      else:

          values['perms'] = []

  

-     return _genHTML(environ, 'taskinfo.chtml')

+     values['koji'] = koji

+     values['S'] = SafeValue

+ 

+     return _genHTML(environ, 'taskinfo.html.j2')

  

  

  def taskstatus(environ, taskID):
@@ -929,7 +937,7 @@ 

      else:

          values['childID'] = int(childID)

  

-     return _genHTML(environ, 'tags.chtml')

+     return _genHTML(environ, 'tags.html.j2')

  

  

  _PREFIX_CHARS = [chr(char) for char in list(range(48, 58)) + list(range(97, 123))]
@@ -972,7 +980,7 @@ 

  

      values['chars'] = _PREFIX_CHARS

  

-     return _genHTML(environ, 'packages.chtml')

+     return _genHTML(environ, 'packages.html.j2')

  

  

  def packageinfo(environ, packageID, tagOrder='name', tagStart=None, buildOrder='-completion_time',
@@ -996,7 +1004,7 @@ 

                                  start=buildStart, dataName='builds', prefix='build',

                                  order=buildOrder)

  

-     return _genHTML(environ, 'packageinfo.chtml')

+     return _genHTML(environ, 'packageinfo.html.j2')

  

  

  def taginfo(environ, tagID, all='0', packageOrder='package_name', packageStart=None,
@@ -1012,7 +1020,7 @@ 

      values['tagID'] = tag['id']

      if 'revoke_event' in tag:

          values['delete_ts'] = server.getEvent(tag['revoke_event'])['ts']

-         return _genHTML(environ, 'taginfo_deleted.chtml')

+         return _genHTML(environ, 'taginfo_deleted.html.j2')

  

      all = int(all)

  
@@ -1060,7 +1068,7 @@ 

      allPerms = dict([(perm['id'], perm['name']) for perm in permList])

      values['allPerms'] = allPerms

  

-     return _genHTML(environ, 'taginfo.chtml')

+     return _genHTML(environ, 'taginfo.html.j2')

  

  

  def tagcreate(environ):
@@ -1096,7 +1104,7 @@ 

          values['tag'] = None

          values['permissions'] = server.getAllPerms()

  

-         return _genHTML(environ, 'tagedit.chtml')

+         return _genHTML(environ, 'tagedit.html.j2')

  

  

  def tagedit(environ, tagID):
@@ -1139,7 +1147,7 @@ 

          values['tag'] = tag

          values['permissions'] = server.getAllPerms()

  

-         return _genHTML(environ, 'tagedit.chtml')

+         return _genHTML(environ, 'tagedit.html.j2')

  

  

  def tagdelete(environ, tagID):
@@ -1205,7 +1213,7 @@ 

                      'tag %i has tag %i listed as a parent more than once' %

                      (tag['id'], parent['id']))

  

-             return _genHTML(environ, 'tagparent.chtml')

+             return _genHTML(environ, 'tagparent.html.j2')

      elif action == 'remove':

          data = server.getInheritanceData(tag['id'])

          for datum in data:
@@ -1234,7 +1242,7 @@ 

      values['extRepo'] = extRepo

      values['repoTags'] = repoTags

  

-     return _genHTML(environ, 'externalrepoinfo.chtml')

+     return _genHTML(environ, 'externalrepoinfo.html.j2')

  

  

  def buildinfo(environ, buildID):
@@ -1381,7 +1389,8 @@ 

              values['estCompletion'] = None

  

      values['pathinfo'] = pathinfo

-     return _genHTML(environ, 'buildinfo.chtml')

+     values['koji'] = koji

+     return _genHTML(environ, 'buildinfo.html.j2')

  

  

  def builds(environ, userID=None, tagID=None, packageID=None, state=None, order='-build_id',
@@ -1467,8 +1476,9 @@ 

                                      start=start, dataName='builds', prefix='build', order=order)

  

      values['chars'] = _PREFIX_CHARS

+     values['koji'] = koji

  

-     return _genHTML(environ, 'builds.chtml')

+     return _genHTML(environ, 'builds.html.j2')

  

  

  def users(environ, order='name', start=None, prefix=None):
@@ -1488,7 +1498,7 @@ 

  

      values['chars'] = _PREFIX_CHARS

  

-     return _genHTML(environ, 'users.chtml')

+     return _genHTML(environ, 'users.html.j2')

  

  

  def userinfo(environ, userID, packageOrder='package_name', packageStart=None,
@@ -1516,7 +1526,7 @@ 

                                  start=buildStart, dataName='builds', prefix='build',

                                  order=buildOrder, pageSize=10)

  

-     return _genHTML(environ, 'userinfo.chtml')

+     return _genHTML(environ, 'userinfo.html.j2')

  

  

  # headers shown in rpminfo and buildinfo pages
@@ -1576,7 +1586,10 @@ 

      kojiweb.util.paginateMethod(server, values, 'listRPMFiles', args=[rpm['id']],

                                  start=fileStart, dataName='files', prefix='file', order=fileOrder)

  

-     return _genHTML(environ, 'rpminfo.chtml')

+     values['koji'] = koji

+     values['time'] = time  # TODO rework template so it doesn't need this

+ 

+     return _genHTML(environ, 'rpminfo.html.j2')

  

  

  def archiveinfo(environ, archiveID, fileOrder='name', fileStart=None, buildrootOrder='-id',
@@ -1620,7 +1633,9 @@ 

      values['show_archive_components'] = server.listArchives(imageID=archive['id'],

                                                              queryOpts={'limit': 1})

  

-     return _genHTML(environ, 'archiveinfo.chtml')

+     values['koji'] = koji

+ 

+     return _genHTML(environ, 'archiveinfo.html.j2')

  

  

  def fileinfo(environ, filename, rpmID=None, archiveID=None):
@@ -1655,7 +1670,7 @@ 

  

      values['file'] = file

  

-     return _genHTML(environ, 'fileinfo.chtml')

+     return _genHTML(environ, 'fileinfo.html.j2')

  

  

  def cancelbuild(environ, buildID):
@@ -1737,7 +1752,9 @@ 

      # Paginate after retrieving last update info so we can sort on it

      kojiweb.util.paginateList(values, hosts, start, 'hosts', 'host', order)

  

-     return _genHTML(environ, 'hosts.chtml')

+     values['zip'] = zip  # TODO avoid passing this in

+ 

+     return _genHTML(environ, 'hosts.html.j2')

  

  

  def hostinfo(environ, hostID=None, userID=None):
@@ -1783,7 +1800,7 @@ 

      else:

          values['perms'] = []

  

-     return _genHTML(environ, 'hostinfo.chtml')

+     return _genHTML(environ, 'hostinfo.html.j2')

  

  

  def hostedit(environ, hostID):
@@ -1833,7 +1850,7 @@ 

          values['allChannels'] = allChannels

          values['hostChannels'] = server.listChannels(hostID=host['id'])

  

-         return _genHTML(environ, 'hostedit.chtml')

+         return _genHTML(environ, 'hostedit.html.j2')

  

  

  def disablehost(environ, hostID):
@@ -1883,7 +1900,7 @@ 

      values['enabled_hosts'] = len([h for h in hosts if h['enabled']])

      values['ready_hosts'] = len([h for h in hosts if h['ready']])

  

-     return _genHTML(environ, 'channelinfo.chtml')

+     return _genHTML(environ, 'channelinfo.html.j2')

  

  

  def buildrootinfo(environ, buildrootID):
@@ -1897,15 +1914,16 @@ 

          raise koji.GenericError('unknown buildroot ID: %i' % buildrootID)

  

      elif buildroot['br_type'] == koji.BR_TYPES['STANDARD']:

-         template = 'buildrootinfo.chtml'

+         template = 'buildrootinfo.html.j2'

          values['task'] = server.getTaskInfo(buildroot['task_id'], request=True)

  

      else:

-         template = 'buildrootinfo_cg.chtml'

+         template = 'buildrootinfo_cg.html.j2'

          # TODO - fetch tools and extras info

  

      values['title'] = '%s | Buildroot Info' % kojiweb.util.brLabel(buildroot)

      values['buildroot'] = buildroot

+     values['koji'] = koji

  

      return _genHTML(environ, template)

  
@@ -1962,7 +1980,7 @@ 

      values['type'] = type

      values['order'] = order

  

-     return _genHTML(environ, 'rpmlist.chtml')

+     return _genHTML(environ, 'rpmlist.html.j2')

  

  

  def archivelist(environ, type, buildrootID=None, imageID=None, start=None, order='filename'):
@@ -2009,7 +2027,7 @@ 

      values['type'] = type

      values['order'] = order

  

-     return _genHTML(environ, 'archivelist.chtml')

+     return _genHTML(environ, 'archivelist.html.j2')

  

  

  def buildtargets(environ, start=None, order='name'):
@@ -2025,7 +2043,7 @@ 

      else:

          values['perms'] = []

  

-     return _genHTML(environ, 'buildtargets.chtml')

+     return _genHTML(environ, 'buildtargets.html.j2')

  

  

  def buildtargetinfo(environ, targetID=None, name=None):
@@ -2055,7 +2073,7 @@ 

      else:

          values['perms'] = []

  

-     return _genHTML(environ, 'buildtargetinfo.chtml')

+     return _genHTML(environ, 'buildtargetinfo.html.j2')

  

  

  def buildtargetedit(environ, targetID):
@@ -2095,7 +2113,7 @@ 

          values['target'] = target

          values['tags'] = tags

  

-         return _genHTML(environ, 'buildtargetedit.chtml')

+         return _genHTML(environ, 'buildtargetedit.html.j2')

  

  

  def buildtargetcreate(environ):
@@ -2130,7 +2148,7 @@ 

          values['target'] = None

          values['tags'] = tags

  

-         return _genHTML(environ, 'buildtargetedit.chtml')

+         return _genHTML(environ, 'buildtargetedit.html.j2')

  

  

  def buildtargetdelete(environ, targetID):
@@ -2155,7 +2173,7 @@ 

          values['loggedInUser'] = True

      else:

          values['loggedInUser'] = False

-     return _genHTML(environ, 'reports.chtml')

+     return _genHTML(environ, 'reports.html.j2')

  

  

  def buildsbyuser(environ, start=None, order='-builds'):
@@ -2183,7 +2201,7 @@ 

      values['increment'] = graphWidth / maxBuilds

      kojiweb.util.paginateList(values, users, start, 'userBuilds', 'userBuild', order)

  

-     return _genHTML(environ, 'buildsbyuser.chtml')

+     return _genHTML(environ, 'buildsbyuser.html.j2')

  

  

  def rpmsbyhost(environ, start=None, order=None, hostArch=None, rpmArch=None):
@@ -2228,7 +2246,7 @@ 

      values['increment'] = graphWidth / maxRPMs

      kojiweb.util.paginateList(values, hosts, start, 'hosts', 'host', order)

  

-     return _genHTML(environ, 'rpmsbyhost.chtml')

+     return _genHTML(environ, 'rpmsbyhost.html.j2')

  

  

  def packagesbyuser(environ, start=None, order=None):
@@ -2258,7 +2276,7 @@ 

      values['increment'] = graphWidth / maxPackages

      kojiweb.util.paginateList(values, users, start, 'users', 'user', order)

  

-     return _genHTML(environ, 'packagesbyuser.chtml')

+     return _genHTML(environ, 'packagesbyuser.html.j2')

  

  

  def tasksbyhost(environ, start=None, order='-tasks', hostArch=None):
@@ -2296,7 +2314,7 @@ 

      values['increment'] = graphWidth / maxTasks

      kojiweb.util.paginateList(values, hosts, start, 'hosts', 'host', order)

  

-     return _genHTML(environ, 'tasksbyhost.chtml')

+     return _genHTML(environ, 'tasksbyhost.html.j2')

  

  

  def tasksbyuser(environ, start=None, order='-tasks'):
@@ -2325,7 +2343,7 @@ 

      values['increment'] = graphWidth / maxTasks

      kojiweb.util.paginateList(values, users, start, 'users', 'user', order)

  

-     return _genHTML(environ, 'tasksbyuser.chtml')

+     return _genHTML(environ, 'tasksbyuser.html.j2')

  

  

  def buildsbystatus(environ, days='7'):
@@ -2364,7 +2382,7 @@ 

      values['maxBuilds'] = maxBuilds

      values['increment'] = graphWidth / maxBuilds

  

-     return _genHTML(environ, 'buildsbystatus.chtml')

+     return _genHTML(environ, 'buildsbystatus.html.j2')

  

  

  def buildsbytarget(environ, days='7', start=None, order='-builds'):
@@ -2404,7 +2422,7 @@ 

      values['maxBuilds'] = maxBuilds

      values['increment'] = graphWidth / maxBuilds

  

-     return _genHTML(environ, 'buildsbytarget.chtml')

+     return _genHTML(environ, 'buildsbytarget.html.j2')

  

  

  def _filter_hosts_by_arch(hosts, arch):
@@ -2464,7 +2482,7 @@ 

      values['arches'] = sorted(arches)

      values['graphWidth'] = graphWidth

      values['channels'] = sorted(channels, key=lambda x: x['name'])

-     return _genHTML(environ, 'clusterhealth.chtml')

+     return _genHTML(environ, 'clusterhealth.html.j2')

  

  

  def recentbuilds(environ, user=None, tag=None, package=None):
@@ -2532,8 +2550,10 @@ 

      values['builds'] = builds

      values['weburl'] = _getBaseURL(environ)

  

+     values['koji'] = koji

+ 

      environ['koji.headers'].append(['Content-Type', 'text/xml'])

-     return _genHTML(environ, 'recentbuilds.chtml')

+     return _genHTML(environ, 'recentbuilds.html.j2')

  

  

  _infoURLs = {'package': 'packageinfo?packageID=%(id)i',
@@ -2586,7 +2606,7 @@ 

              except Exception:

                  values['error'] = 'Invalid regular expression'

                  values['terms'] = ''

-                 return _genHTML(environ, 'search.chtml')

+                 return _genHTML(environ, 'search.html.j2')

  

          infoURL = _infoURLs.get(type)

          if not infoURL:
@@ -2610,9 +2630,9 @@ 

              else:

                  typeLabel = '%ss' % type

              values['typeLabel'] = typeLabel

-             return _genHTML(environ, 'search.chtml')

+             return _genHTML(environ, 'search.html.j2')

      else:

-         return _genHTML(environ, 'search.chtml')

+         return _genHTML(environ, 'search.html.j2')

  

  

  def api(environ):
@@ -2621,12 +2641,13 @@ 

  

      values['koji_hub_url'] = environ['koji.options']['KojiHubURL']

      values['methods'] = sorted(server._listapi(), key=lambda x: x['name'])

+     values['web_version'] = koji.__version__

      try:

          values['koji_version'] = server.getKojiVersion()

      except koji.GenericError:

          values['koji_version'] = "Can't determine (older then 1.23)"

  

-     return _genHTML(environ, 'api.chtml')

+     return _genHTML(environ, 'api.html.j2')

  

  

  def watchlogs(environ, taskID):
@@ -2677,7 +2698,9 @@ 

                  pathinfo.repo(repo_info['id'], repo_info['tag_name']), 'repo.json')

      num_buildroots = len(server.listBuildroots(repoID=repoID)) or 0

      values['numBuildroots'] = num_buildroots

-     return _genHTML(environ, 'repoinfo.chtml')

+     values['state_name'] = kojiweb.util.repoState(repo_info['state'])

+     values['create_time'] = kojiweb.util.formatTimeLong(repo_info['create_ts'])

+     return _genHTML(environ, 'repoinfo.html.j2')

  

  

  def activesession(environ, start=None, order=None):
@@ -2687,18 +2710,20 @@ 

      values['loggedInUser'] = environ['koji.currentUser']

  

      values['order'] = order

-     activesess = server.getSessionInfo(details=True, user_id=values['loggedInUser']['id'])

-     if not activesess:

-         activesess = []

-     else:

+     activesess = []

+     if environ['koji.currentUser']:

+         activesess = server.getSessionInfo(details=True, user_id=values['loggedInUser']['id'])

+     if activesess:

          current_timestamp = datetime.datetime.utcnow().timestamp()

          for a in activesess:

              a['lengthSession'] = kojiweb.util.formatTimestampDifference(

                  a['start_time'], current_timestamp, in_days=True)

+     else:

+         activesess = []

  

      kojiweb.util.paginateList(values, activesess, start, 'activesess', order=order)

  

-     return _genHTML(environ, 'activesession.chtml')

+     return _genHTML(environ, 'activesession.html.j2')

  

  

  def activesessiondelete(environ, sessionID):
@@ -2727,4 +2752,6 @@ 

                                  kw={'repoID': repoID, 'state': state}, start=start,

                                  dataName='buildroots', prefix='buildroot', order=order)

  

-     return _genHTML(environ, 'buildroots.chtml')

+     values['koji'] = koji

+ 

+     return _genHTML(environ, 'buildroots.html.j2')

@@ -1,127 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <h4>Information for package <a href="packageinfo?packageID=$package.id">$package.name</a></h4>

- 

-   <table>

-     <tr>

-       <th>Name</th><td>$package.name</td>

-     </tr>

-     <tr>

-       <th>ID</th><td>$package.id</td>

-     </tr>

-     

-     <tr>

-       <th id="buildlist">Builds</th>

-       <td class="container">

-         #if $len($builds) > 0

-         <table class="nested data-list">

-           <tr>

-             <td class="paginate" colspan="4">

-               #if $len($buildPages) > 1

-               <form class="pageJump" action="">

-                 Page:

-                 <select onchange="javascript: window.location = 'packageinfo?buildStart=' + this.value * $buildRange + '$util.passthrough($self, 'packageID', 'buildOrder', 'tagOrder', 'tagStart')#buildlist';">

-                   #for $pageNum in $buildPages

-                   <option value="$pageNum"#if $pageNum == $buildCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-                   #end for

-                 </select>

-               </form>

-               #end if

-               #if $buildStart > 0

-               <a href="packageinfo?buildStart=#echo $buildStart - $buildRange#$util.passthrough($self, 'packageID', 'buildOrder', 'tagOrder', 'tagStart')#buildlist">&lt;&lt;&lt;</a>

-               #end if

-               <strong>#echo $buildStart + 1 # through #echo $buildStart + $buildCount # of $totalBuilds</strong>

-               #if $buildStart + $buildCount < $totalBuilds

-               <a href="packageinfo?buildStart=#echo $buildStart + $buildRange#$util.passthrough($self, 'packageID', 'buildOrder', 'tagOrder', 'tagStart')#buildlist">&gt;&gt;&gt;</a>

-               #end if

-             </td>

-           </tr>

-           <tr class="list-header">

-             <th><a href="packageinfo?buildOrder=$util.toggleOrder($self, 'nvr', 'buildOrder')$util.passthrough($self, 'packageID', 'tagOrder', 'tagStart')#buildlist">NVR</a> $util.sortImage($self, 'nvr', 'buildOrder')</th>

-             <th><a href="packageinfo?buildOrder=$util.toggleOrder($self, 'owner_name', 'buildOrder')$util.passthrough($self, 'packageID', 'tagOrder', 'tagStart')#buildlist">Built by</a> $util.sortImage($self, 'owner_name', 'buildOrder')</th>

-             <th><a href="packageinfo?buildOrder=$util.toggleOrder($self, 'completion_time', 'buildOrder')$util.passthrough($self, 'packageID', 'tagOrder', 'tagStart')#buildlist">Finished</a> $util.sortImage($self, 'completion_time', 'buildOrder')</th>

-             <th><a href="packageinfo?buildOrder=$util.toggleOrder($self, 'state', 'buildOrder')$util.passthrough($self, 'packageID', 'tagOrder', 'tagStart')#buildlist">State</a> $util.sortImage($self, 'state', 'buildOrder')</th>

-           </tr>

-           #for $build in $builds

-           <tr class="$util.rowToggle($self)">

-             <td><a href="buildinfo?buildID=$build.build_id">$build.nvr</a></td>

-             <td class="user-$build.owner_name"><a href="userinfo?userID=$build.owner_id">$build.owner_name</a></td>

-             <td>$util.formatTime($build.completion_ts)</td>

-             #set $stateName = $util.stateName($build.state)

-             <td class="$stateName">$util.stateImage($build.state)</td>

-           </tr>

-           #end for

-         </table>

-         #if $buildStart > 0

-         <a href="packageinfo?buildStart=#echo $buildStart - $buildRange#$util.passthrough($self, 'packageID', 'buildOrder', 'tagOrder', 'tagStart')#buildlist">&lt;&lt;&lt;</a>

-         #end if

-         <strong>Builds #echo $buildStart + 1 # through #echo $buildStart + $buildCount # of $totalBuilds</strong>

-         #if $buildStart + $buildCount < $totalBuilds

-         <a href="packageinfo?buildStart=#echo $buildStart + $buildRange#$util.passthrough($self, 'packageID', 'buildOrder', 'tagOrder', 'tagStart')#buildlist">&gt;&gt;&gt;</a>

-         #end if

-         #else

-         No builds

-         #end if

-       </td>

-     </tr>

-     

-     <tr>

-       <th id="taglist">Tags</th>

-       <td class="container">

-         #if $len($tags) > 0

-         <table class="nested data-list">

-           <tr>

-             <td class="paginate" colspan="4">

-               #if $len($tagPages) > 1

-               <form class="pageJump" action="">

-                 Page:

-                 <select onchange="javascript: window.location = 'packageinfo?tagStart=' + this.value * $tagRange + '$util.passthrough($self, 'packageID', 'tagOrder', 'buildOrder', 'buildStart')#taglist';">

-                   #for $pageNum in $tagPages

-                   <option value="$pageNum"#if $pageNum == $tagCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-                   #end for

-                 </select>

-               </form>

-               #end if

-               #if $tagStart > 0

-               <a href="packageinfo?tagStart=#echo $tagStart - $tagRange#$util.passthrough($self, 'packageID', 'tagOrder', 'buildOrder', 'buildStart')#taglist">&lt;&lt;&lt;</a>

-               #end if

-               <strong>#echo $tagStart + 1 # through #echo $tagStart + $tagCount # of $totalTags</strong>

-               #if $tagStart + $tagCount < $totalTags

-               <a href="packageinfo?tagStart=#echo $tagStart + $tagRange#$util.passthrough($self, 'packageID', 'tagOrder', 'buildOrder', 'buildStart')#taglist">&gt;&gt;&gt;</a>

-               #end if

-             </td>

-           </tr>

-           <tr class="list-header">

-             <th><a href="packageinfo?tagOrder=$util.toggleOrder($self, 'name', 'tagOrder')$util.passthrough($self, 'packageID', 'buildOrder', 'buildStart')#taglist">Name</a> $util.sortImage($self, 'name', 'tagOrder')</th>

-             <th><a href="packageinfo?tagOrder=$util.toggleOrder($self, 'owner_name', 'tagOrder')$util.passthrough($self, 'packageID', 'buildOrder', 'buildStart')#taglist">Owner</a> $util.sortImage($self, 'owner_name', 'tagOrder')</th>

-             <th><a href="packageinfo?tagOrder=$util.toggleOrder($self, 'blocked', 'tagOrder')$util.passthrough($self, 'packageID', 'buildOrder', 'buildStart')#taglist">Included?</a> $util.sortImage($self, 'blocked', 'tagOrder')</th>

-             <th><a href="packageinfo?tagOrder=$util.toggleOrder($self, 'extra_arches', 'tagOrder')$util.passthrough($self, 'packageID', 'buildOrder', 'buildStart')#taglist">Extra Arches</a> $util.sortImage($self, 'extra_arches', 'tagOrder')</th>

-           </tr>

-           #for $tag in $tags

-           <tr class="$util.rowToggle($self)">

-             <td><a href="taginfo?tagID=$tag.id">$tag.name</a></td>

-             <td><a href="userinfo?userID=$tag.owner_id">$tag.owner_name</a></td>

-             #set $included = $tag.blocked and 'no' or 'yes'

-             <td>$util.imageTag($included)</td>

-             <td>$tag.extra_arches</td>

-           </tr>

-           #end for

-         </table>

-         #if $tagStart > 0

-         <a href="packageinfo?tagStart=#echo $tagStart - $tagRange#$util.passthrough($self, 'packageID', 'tagOrder', 'buildOrder', 'buildStart')#taglist">&lt;&lt;&lt;</a>

-         #end if

-         <strong>Tags #echo $tagStart + 1 # through #echo $tagStart + $tagCount # of $totalTags</strong>

-         #if $tagStart + $tagCount < $totalTags

-         <a href="packageinfo?tagStart=#echo $tagStart + $tagRange#$util.passthrough($self, 'packageID', 'tagOrder', 'buildOrder', 'buildStart')#taglist">&gt;&gt;&gt;</a>

-         #end if

-         #else

-         No tags

-         #end if

-       </td>

-     </tr>

-     

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,139 +0,0 @@ 

- #from kojiweb import util

- #from kojiweb.util import safe_return

- 

- #attr _PASSTHROUGH = ['userID', 'tagID', 'order', 'prefix', 'inherited', 'blocked']

- 

- #include "includes/header.chtml"

- 

- #@safe_return

- #def getDescription()

- Packages

- #if $prefix

- starting with $prefix

- #end if

- #if $tag

- in tag <a href="taginfo?tagID=$tag.id">$tag.name</a>

- #end if

- #if $user

- owned by <a href="userinfo?userID=$user.id">$user.name</a>

- #end if

- #end def

- 

-   <h4>$getDescription()</h4>

- 

-   <table class="data-list">

-     #if $tag

-     <tr>

-       <td colspan="5">

-         <table class="nested">

-           <tr><td>

-           <strong>Inherited</strong>:

-           </td><td>

-           <select name="inherited" class="filterlist" onchange="javascript: window.location = 'packages?inherited=' + this.value + '$util.passthrough_except($self, 'inherited')';">

-             <option value="1" #if $inherited then 'selected' else ''#>yes</option>

-             <option value="0" #if not $inherited then 'selected' else ''#>no</option>

-           </select>

-           </td></tr>

-           <tr><td>

-           <strong>With blocked</strong>:

-           </td><td>

-           <select name="blocked" class="filterlist" onchange="javascript: window.location = 'packages?blocked=' + this.value + '$util.passthrough_except($self, 'blocked')';">

-             <option value="1" #if $blocked then 'selected' else ''#>yes</option>

-             <option value="0" #if not $blocked then 'selected' else ''#>no</option>

-           </select>

-           </td></tr>

-         </table>

-     </tr>

-     #end if

-     <tr>

-       <td class="charlist" colspan="#if $tag or $user then '5' else '2'#">

-         #for $char in $chars

-         #if $prefix == $char

-         <strong>$char</strong>

-         #else

-         <a href="packages?prefix=$char$util.passthrough($self, 'userID', 'tagID', 'order', 'inherited', 'blocked')">$char</a>

-         #end if

-         |

-         #end for

-         #if $prefix

-         <a href="packages?${util.passthrough($self, 'userID', 'tagID', 'order', 'inherited', 'blocked', prefix='')}">all</a>

-         #else

-         <strong>all</strong>

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <td class="paginate" colspan="#if $tag or $user then '5' else '2'#">

-         #if $len($packagePages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'packages?start=' + this.value * $packageRange + '$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'blocked')';">

-             #for $pageNum in $packagePages

-             <option value="$pageNum"#if $pageNum == $packageCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $packageStart > 0

-         <a href="packages?start=#echo $packageStart - $packageRange #$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'blocked')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalPackages != 0

-         <strong>Packages #echo $packageStart + 1 # through #echo $packageStart + $packageCount # of $totalPackages</strong>

-         #end if

-         #if $packageStart + $packageCount < $totalPackages

-         <a href="packages?start=#echo $packageStart + $packageRange#$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'blocked')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="packages?order=$util.toggleOrder($self, 'package_id')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'blocked')">ID</a> $util.sortImage($self, 'package_id')</th>

-       <th><a href="packages?order=$util.toggleOrder($self, 'package_name')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'blocked')">Name</a> $util.sortImage($self, 'package_name')</th>

-       #if $tag or $user

-         <th><a href="packages?order=$util.toggleOrder($self, 'tag_name')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'blocked')">Tag</a> $util.sortImage($self, 'tag_name')</th>

-         <th><a href="packages?order=$util.toggleOrder($self, 'owner_name')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'blocked')">Owner</a> $util.sortImage($self, 'owner_name')</th>

-         <th><a href="packages?order=$util.toggleOrder($self, 'blocked')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'blocked')">Included?</a> $util.sortImage($self, 'blocked')</th>

-       #end if

-     </tr>

-     #if $len($packages) > 0

-       #for $package in $packages

-         <tr class="$util.rowToggle($self)">

-           <td>$package.package_id</td>

-           <td><a href="packageinfo?packageID=$package.package_id">$package.package_name</a></td>

-           #if $tag or $user

-           <td><a href="taginfo?tagID=$package.tag_id">$package.tag_name</a></td>

-           <td class="user-$package.owner_name"><a href="userinfo?userID=$package.owner_id">$package.owner_name</a></td>

-           <td class="$str(not $package.blocked).lower()">#if $package.blocked then $util.imageTag('no') else $util.imageTag('yes')#</td>

-           #end if

-         </tr>

-       #end for

-     #else

-       <tr class="row-odd">

-         <td colspan="#if $tag or $user then '5' else '2'#">No packages</td>

-       </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="#if $tag or $user then '5' else '2'#">

-         #if $len($packagePages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'packages?start=' + this.value * $packageRange + '$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'blocked')';">

-             #for $pageNum in $packagePages

-             <option value="$pageNum"#if $pageNum == $packageCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $packageStart > 0

-         <a href="packages?start=#echo $packageStart - $packageRange #$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'blocked')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalPackages != 0

-         <strong>Packages #echo $packageStart + 1 # through #echo $packageStart + $packageCount # of $totalPackages</strong>

-         #end if

-         #if $packageStart + $packageCount < $totalPackages

-         <a href="packages?start=#echo $packageStart + $packageRange#$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'blocked')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,73 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <h4>Packages by User</h4>

-   <table class="data-list">

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($userPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'packagesbyuser?start=' + this.value * $userRange + '$util.passthrough($self, 'order')';">

-             #for $pageNum in $userPages

-             <option value="$pageNum"#if $pageNum == $userCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $userStart > 0

-         <a href="packagesbyuser?start=#echo $userStart - $userRange #$util.passthrough($self, 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalUsers != 0

-         <strong>Users #echo $userStart + 1 # through #echo $userStart + $userCount # of $totalUsers</strong>

-         #end if

-         #if $userStart + $userCount < $totalUsers

-         <a href="packagesbyuser?start=#echo $userStart + $userRange#$util.passthrough($self, 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="packagesbyuser?order=$util.toggleOrder($self, 'name')">Name</a> $util.sortImage($self, 'name')</th>

-       <th><a href="packagesbyuser?order=$util.toggleOrder($self, 'packages')">Packages</a> $util.sortImage($self, 'packages')</th>

-       <th>&nbsp;</th>

-     </tr>

-     #if $len($users) > 0

-     #for $user in $users

-     <tr class="$util.rowToggle($self)">

-       <td><a href="userinfo?userID=$user.id">$user.name</a></td>

-       <td width="#echo $graphWidth + 5#"><img src="$util.themePath('images/1px.gif')" width="#echo $increment * $user.packages#" height="15" class="graphrow" alt="graph row"/></td>

-       <td>$user.packages</td>

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td colspan="3">No users</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($userPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'packagesbyuser?start=' + this.value * $userRange + '$util.passthrough($self, 'order')';">

-             #for $pageNum in $userPages

-             <option value="$pageNum"#if $pageNum == $userCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $userStart > 0

-         <a href="packagesbyuser?start=#echo $userStart - $userRange #$util.passthrough($self, 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalUsers != 0

-         <strong>Users #echo $userStart + 1 # through #echo $userStart + $userCount # of $totalUsers</strong>

-         #end if

-         #if $userStart + $userCount < $totalUsers

-         <a href="packagesbyuser?start=#echo $userStart + $userRange#$util.passthrough($self, 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,55 +0,0 @@ 

- #import koji

- #import koji.util

- #from kojiweb import util

- 

- #@util.safe_return

- #def linkURL()

-   #set $query = []

-   #if $tag

-   #silent $query.append('tagID=%i' % $tag.id)

-   #end if

-   #if $user

-   #silent $query.append('userID=%i' % $user.id)

-   #end if

-   #if $package

-   #silent $query.append('packageID=%i' % $package.id)

-   #end if

-   #if $query

-   #echo '%s/%s?%s' % ($weburl, 'builds', '&amp;'.join($query))

-   #else

-   #echo '%s/%s' % ($weburl, 'builds')

-   #end if

- #end def

- 

- <rss version="2.0">

-   <channel>

-     <title>$siteName: recent builds#if $package then ' of package ' + $package.name else ''##if $tag then ' into tag ' + $tag.name else ''##if $user then ' by user ' + $user.name else ''#</title>

-     <link>$linkURL()</link>

-     <description>

-       A list of the most recent builds

-       #if $package

-       of package $package.name

-       #end if

-       #if $tag

-       into tag $tag.name

-       #end if

-       #if $user

-       by user $user.name

-       #end if

-       in the $siteName Build System.  The list is sorted in reverse chronological order by build completion time.

-     </description>

-     <pubDate>$util.formatTimeRSS($currentDate)</pubDate>

-     #for $build in $builds

-     <item>

-       <title>$koji.BUILD_STATES[$build.state].lower(): $koji.buildLabel($build)#if $build.task then ', target: ' + $build.task.request[1] else ''#</title>

-       <link>$weburl/buildinfo?buildID=$build.build_id</link>

-       #if $build.completion_time

-       <pubDate>$util.formatTimeRSS($build.completion_ts)</pubDate>

-       #end if

-       #if $build.state == $koji.BUILD_STATES['COMPLETE'] and $build.changelog

-       <description>&lt;pre&gt;$koji.util.formatChangelog($build.changelog)&lt;/pre&gt;</description>

-       #end if

-     </item>

-     #end for

-   </channel>

- </rss>

@@ -1,30 +0,0 @@ 

- #import koji

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

- <h4>Information for repo $repo_id</h4>

- 

- #if $repo

- <table>

-   <tr><th>ID</th><td>$repo.id</td><th></tr>

-   <tr><th>Tag</th><td><a href="taginfo?tagID=$repo.tag_id">$repo.tag_name</a></td></tr>

-   #if $repo.task_id

-   <tr><th>Task ID</th><td><a href="taskinfo?taskID=$repo.task_id">$repo.task_id</a></td></tr>

-   #end if

-   #set $state = $util.repoState($repo.state)

-   <tr><th>State</th><td class="repo$state">$state</td></tr>

-   <tr><th>Event</th><td>$repo.create_event ($util.formatTimeLong($repo.create_ts))</td></tr>

-   #if $repo.state != koji.REPO_STATES['DELETED']

-   <tr><th>URL</th><td><a href="$url">repodata</a></td></tr>

-   <tr><th>Repo json</th><td><a href="$repo_json">repo.json</a></td></tr>

-   #end if

-   <tr><th>Dist repo?</th><td class="$str($repo.dist).lower()">#if $repo.dist then 'yes' else 'no'#</td></tr>

-   <tr><th>Number of buildroots: </th><td><a href="buildroots?repoID=$repo.id">$numBuildroots</a></td></tr>

- </table>

- #else

- Repo $repo_id not found.

- #end if

- 

- 

- #include "includes/footer.chtml"

file removed
-320
@@ -1,320 +0,0 @@ 

- #import koji

- #from kojiweb import util

- #from pprint import pformat

- #import time

- #from urllib.parse import quote

- 

- #attr _PASSTHROUGH = ['rpmID', 'fileOrder', 'fileStart', 'buildrootOrder', 'buildrootStart']

- 

- #include "includes/header.chtml"

-   #set $epoch = ($rpm.epoch != None and $str($rpm.epoch) + ':' or '')

-   <h4>Information for RPM <a href="rpminfo?rpmID=$rpm.id">$rpm.name-$epoch$rpm.version-$rpm.release.${rpm.arch}.rpm</a></h4>

- 

-   <table>

-     <tr>

-       <th>ID</th><td>$rpm.id</td>

-     </tr>

-     #if $build

-     <tr>

-       <th>Build</th><td><a href="buildinfo?buildID=$build.id">$koji.buildLabel($build)</a></td>

-     </tr>

-     #end if

-     <tr>

-       #if $build

-       <th>Name</th><td><a href="packageinfo?packageID=$build.package_id">$rpm.name</a></td>

-       #else

-       <th>Name</th><td>$rpm.name</td>

-       #end if

-     </tr>

-     <tr>

-       #if $build

-       <th>Version</th><td><a href="buildinfo?buildID=$build.id">$rpm.version</a></td>

-       #else

-       <th>Version</th><td>$rpm.version</td>

-       #end if

-     </tr>

-     <tr>

-       <th>Release</th><td>$rpm.release</td>

-     </tr>

-     <tr>

-       <th>Epoch</th><td>$rpm.epoch</td>

-     </tr>

-     <tr>

-       <th>Arch</th><td>$rpm.arch</td>

-     </tr>

-     <tr>

-     #if $rpm.draft

-       <th>Draft</th><td>True</td>

-       #else

-       <th>Draft</th><td>False</td>

-     #end if

-     #if $rpm.external_repo_id == 0

-     <tr>

-       <th>Summary</th><td class="rpmheader">$summary</td>

-     </tr>

-     <tr>

-       <th>Description</th><td class="rpmheader">$description</td>

-     </tr>

-     #end if

-     <tr>

-       <th>Build Time</th><td>$time.strftime('%Y-%m-%d %H:%M:%S', $time.gmtime($rpm.buildtime)) GMT</td>

-     </tr>

-     #if $build and $build.state == $koji.BUILD_STATES.DELETED

-     <tr>

-       <th>State</th><td class="deleted">deleted</td>

-     </tr>

-     #end if

-     #if $rpm.external_repo_id

-     <tr>

-       <th>External Repository</th><td><a href="externalrepoinfo?extrepoID=$rpm.external_repo_id">$rpm.external_repo_name</a></td>

-     </tr>

-     #end if

-     <tr>

-       <th>Size</th><td><span title="$util.formatThousands($rpm.size)">$util.formatNatural($rpm.size)</span></td>

-     </tr>

-     <tr>

-       <th><label title="The MD5 digest of the combined header and payload contents. You can query it by `rpmkeys -Kv foo.rpm`">SIGMD5</label></th><td>$rpm.payloadhash</td>

-     </tr>

-     #if $rpm.external_repo_id == 0

-     <tr>

-       <th>License</th><td>$license</td>

-     </tr>

-     #if $vcs

-     <tr>

-         <th><label title="Package source code VCS location">VCS</label></th><td>$util.formatLink($vcs)</td>

-     </tr>

-     #end if

-     #if $disturl

-     <tr>

-         <th>DistURL</th><td>$util.formatLink($disturl)</td>

-     </tr>

-     #end if

-     #end if

-     #if $builtInRoot

-     <tr>

-       <th>Buildroot</th><td><a href="buildrootinfo?buildrootID=$builtInRoot.id">$util.brLabel($builtInRoot)</a></td>

-     </tr>

-     #end if

-     #if $rpm.get('extra')

-     <tr>

-       <th>Extra</th><td class="usertext">$pformat($rpm.extra)</td>

-     </tr>

-     #end if

-     #if $rpm.external_repo_id == 0

-     <tr>

-       <th>Provides</th>

-       <td class="container">

-         #if $len($provides) > 0

-         <table class="nested">

-           #for $dep in $provides

-           <tr>

-             <td>$util.formatDep($dep.name, $dep.version, $dep.flags)</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Provides

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Obsoletes</th>

-       <td class="container">

-         #if $len($obsoletes) > 0

-         <table class="nested">

-           #for $dep in $obsoletes

-           <tr>

-             <td>$util.formatDep($dep.name, $dep.version, $dep.flags)</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Obsoletes

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Conflicts</th>

-       <td class="container">

-         #if $len($conflicts) > 0

-         <table class="nested">

-           #for $dep in $conflicts

-           <tr>

-             <td>$util.formatDep($dep.name, $dep.version, $dep.flags)</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Conflicts

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Requires</th>

-       <td class="container">

-         #if $len($requires) > 0

-         <table class="nested">

-           #for $dep in $requires

-           <tr>

-             <td>$util.formatDep($dep.name, $dep.version, $dep.flags)</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Requires

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Recommends</th>

-       <td class="container">

-         #if $len($recommends) > 0

-         <table class="nested">

-           #for $dep in $recommends

-           <tr>

-             <td>$util.formatDep($dep.name, $dep.version, $dep.flags)</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Recommends

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Suggests</th>

-       <td class="container">

-         #if $len($suggests) > 0

-         <table class="nested">

-           #for $dep in $suggests

-           <tr>

-             <td>$util.formatDep($dep.name, $dep.version, $dep.flags)</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Suggests

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Supplements</th>

-       <td class="container">

-         #if $len($supplements) > 0

-         <table class="nested">

-           #for $dep in $supplements

-           <tr>

-             <td>$util.formatDep($dep.name, $dep.version, $dep.flags)</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Supplements

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Enhances</th>

-       <td class="container">

-         #if $len($enhances) > 0

-         <table class="nested">

-           #for $dep in $enhances

-           <tr>

-             <td>$util.formatDep($dep.name, $dep.version, $dep.flags)</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Enhances

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th id="filelist">Files</th>

-       <td class="container">

-         #if $len($files) > 0

-         <table class="nested data-list">

-           <tr>

-             <td class="paginate" colspan="2">

-               #if $len($filePages) > 1

-               <form class="pageJump" action="">

-                 Page:

-                 <select onchange="javascript: window.location = 'rpminfo?fileStart=' + this.value * $fileRange + '$util.passthrough_except($self, 'fileStart')#filelist';">

-                   #for $pageNum in $filePages

-                   <option value="$pageNum"#if $pageNum == $fileCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-                   #end for

-                 </select>

-               </form>

-               #end if

-               #if $fileStart > 0

-               <a href="rpminfo?fileStart=#echo $fileStart - $fileRange #$util.passthrough_except($self, 'fileStart')#filelist">&lt;&lt;&lt;</a>

-               #end if

-               <strong>#echo $fileStart + 1 # through #echo $fileStart + $fileCount # of $totalFiles</strong>

-               #if $fileStart + $fileCount < $totalFiles

-               <a href="rpminfo?fileStart=#echo $fileStart + $fileRange#$util.passthrough_except($self, 'fileStart')#filelist">&gt;&gt;&gt;</a>

-               #end if

-             </td>

-           </tr>

-           <tr class="list-header">

-             <th><a href="rpminfo?fileOrder=$util.toggleOrder($self, 'name', 'fileOrder')$util.passthrough_except($self, 'fileOrder', 'fileStart')#filelist">Name</a> $util.sortImage($self, 'name', 'fileOrder')</th>

-             <th align="right"><a href="rpminfo?fileOrder=$util.toggleOrder($self, 'size', 'fileOrder')$util.passthrough_except($self, 'fileOrder', 'fileStart')#filelist">Size</a> $util.sortImage($self, 'size', 'fileOrder')</th>

-           </tr>

-           #for $file in $files

-           <tr class="$util.rowToggle($self)">

-             <td><a href="fileinfo?rpmID=$rpm.id&amp;filename=$quote($file.name.encode('utf-8'))">$file.name</a></td><td align="right"><span title="$util.formatThousands($file.size)">$util.formatNatural($file.size)</span></td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Files

-         #end if

-       </td>

-     </tr>

-     #end if

-     <tr>

-       <th id="buildrootlist">Component&nbsp;of</th>

-       <td class="container">

-         #if $len($buildroots) > 0

-         <table class="nested data-list">

-           <tr>

-             <td class="paginate" colspan="3">

-               #if $len($buildrootPages) > 1

-               <form class="pageJump" action="">

-                 Page:

-                 <select onchange="javascript: window.location = 'rpminfo?buildrootStart=' + this.value * $buildrootRange + '$util.passthrough_except($self, 'buildrootStart')#buildrootlist';">

-                   #for $pageNum in $buildrootPages

-                   <option value="$pageNum"#if $pageNum == $buildrootCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-                   #end for

-                 </select>

-               </form>

-               #end if

-               #if $buildrootStart > 0

-               <a href="rpminfo?buildrootStart=#echo $buildrootStart - $buildrootRange #$util.passthrough_except($self, 'buildrootStart')#buildrootlist">&lt;&lt;&lt;</a>

-               #end if

-               <strong>#echo $buildrootStart + 1 # through #echo $buildrootStart + $buildrootCount # of $totalBuildroots</strong>

-               #if $buildrootStart + $buildrootCount < $totalBuildroots

-               <a href="rpminfo?buildrootStart=#echo $buildrootStart + $buildrootRange#$util.passthrough_except($self, 'buildrootStart')#buildrootlist">&gt;&gt;&gt;</a>

-               #end if

-             </td>

-           </tr>

-           <tr class="list-header">

-             <th><a href="rpminfo?buildrootOrder=$util.toggleOrder($self, 'id', 'buildrootOrder')$util.passthrough_except($self, 'buildrootOrder', 'buildrootStart')#buildrootlist">Buildroot</a> $util.sortImage($self, 'id', 'buildrootOrder')</th>

-             <th><a href="rpminfo?buildrootOrder=$util.toggleOrder($self, 'create_event_time', 'buildrootOrder')$util.passthrough_except($self, 'buildrootOrder', 'buildrootStart')#buildrootlist">Created</a> $util.sortImage($self, 'create_event_time', 'buildrootOrder')</th>

-             <th><a href="rpminfo?buildrootOrder=$util.toggleOrder($self, 'state', 'buildrootOrder')$util.passthrough_except($self, 'buildrootOrder', 'buildrootStart')#buildrootlist">State</a> $util.sortImage($self, 'state', 'buildrootOrder')</th>

-           </tr>

-           #for $buildroot in $buildroots

-           <tr class="$util.rowToggle($self)">

-             <td><a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></td>

-             <td>$util.formatTime($buildroot.create_event_time)</td>

-             <td>$util.imageTag($util.brStateName($buildroot.state))</td>

-           </tr>

-           #end for

-         </table>

-         #else

-         No Buildroots

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

file removed
-114
@@ -1,114 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

- #@util.safe_return

- #def getID()

-   #if $type == 'image'

- imageID=$image.id #slurp

-   #else

- buildrootID=$buildroot.id #slurp

-   #end if

- #end def

- 

- #@util.safe_return

- #def getColspan()

-   #if $type == 'component'

- colspan="3" #slurp

-   #elif $type == 'image'

- colspan="2" #slurp

-   #else

-   #pass

-   #end if

- #end def

- 

-   #if $type == 'component'

-   <h4>Component RPMs of buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>

-   #elif $type == 'image'

-   <h4>RPMs installed in <a href="archiveinfo?archiveID=$image.id">$image.filename</a></h4>

-   #else

-   <h4>RPMs built in buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>

-   #end if

- 

-   <table class="data-list">

-     <tr>

-       <td class="paginate" $getColspan()>

-         #if $len($rpmPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'rpmlist?$getID()&start=' + this.value * $rpmRange + '$util.passthrough($self, 'order', 'type')';">

-             #for $pageNum in $rpmPages

-             <option value="$pageNum"#if $pageNum == $rpmCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $rpmStart > 0

-         <a href="rpmlist?$getID()&start=#echo $rpmStart - $rpmRange #$util.passthrough($self, 'order', 'type')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalRpms != 0

-         <strong>RPMs #echo $rpmStart + 1 # through #echo $rpmStart + $rpmCount # of $totalRpms</strong>

-         #end if

-         #if $rpmStart + $rpmCount < $totalRpms

-         <a href="rpmlist?$getID()&start=#echo $rpmStart + $rpmRange#$util.passthrough($self, 'order', 'type')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="rpmlist?$getID()&order=$util.toggleOrder($self, 'nvr')$util.passthrough($self, 'type')">NVR</a> $util.sortImage($self, 'nvr')</th>

-       #if $type in ['component', 'image']

-       <th><a href="rpmlist?$getID()&order=$util.toggleOrder($self, 'external_repo_name')$util.passthrough($self, 'type')">Origin</a> $util.sortImage($self, 'external_repo_name')</th>

-       #end if

-       #if $type == 'component'

-       <th><a href="rpmlist?$getID()&order=$util.toggleOrder($self, 'is_update')$util.passthrough($self, 'type')">Update?</a> $util.sortImage($self, 'is_update')</th>

-       #end if

-     </tr>

-     #if $len($rpms) > 0

-     #for $rpm in $rpms

-     <tr class="$util.rowToggle($self)">

-       #set $epoch = ($rpm.epoch != None and $str($rpm.epoch) + ':' or '')

-       <td>$util.formatRPM($rpm)</td>

-       #if $type in ['component', 'image']

-       #if $rpm.external_repo_id == 0

-       <td>internal</td>

-       #else

-       <td><a href="externalrepoinfo?extrepoID=$rpm.external_repo_id">$rpm.external_repo_name</a></td>

-       #end if

-       #end if

-       #if $type == 'component'

-       #set $update = $rpm.is_update and 'yes' or 'no'

-       <td class="$update">$util.imageTag($update)</td>

-       #end if

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td $getColspan()>No RPMs</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" $getColspan()>

-         #if $len($rpmPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'rpmlist?$getID()&start=' + this.value * $rpmRange + '$util.passthrough($self, 'order', 'type')';">

-             #for $pageNum in $rpmPages

-             <option value="$pageNum"#if $pageNum == $rpmCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $rpmStart > 0

-         <a href="rpmlist?$getID()&start=#echo $rpmStart - $rpmRange #$util.passthrough($self, 'order', 'type')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalRpms != 0

-         <strong>RPMs #echo $rpmStart + 1 # through #echo $rpmStart + $rpmCount # of $totalRpms</strong>

-         #end if

-         #if $rpmStart + $rpmCount < $totalRpms

-         <a href="rpmlist?$getID()&start=#echo $rpmStart + $rpmRange#$util.passthrough($self, 'order', 'type')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,105 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <h4>#if $rpmArch then $rpmArch + ' ' else ''#RPMs by Host#if $hostArch then ' (%s)' % $hostArch else ''#</h4>

-   <table class="data-list">

-     <tr>

-       <td class="archlist" colspan="3">

-         <strong>Host arch:</strong> #for $arch in $hostArchList

-         #if $arch == $hostArch

-         <strong>$arch</strong> |

-         #else

-         <a href="rpmsbyhost?hostArch=$arch$util.passthrough($self, 'order', 'rpmArch')">$arch</a> |

-         #end if

-         #end for

-         #if $hostArch

-         <a href="rpmsbyhost?${util.passthrough($self, 'order', 'rpmArch', prefix='')}">all</a>

-         #else

-         <strong>all</strong>

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <td class="archlist" colspan="3">

-         <strong>RPM arch:</strong> #for $arch in $rpmArchList

-         #if $arch == $rpmArch

-         <strong>$arch</strong> |

-         #else

-         <a href="rpmsbyhost?rpmArch=$arch$util.passthrough($self, 'order', 'hostArch')">$arch</a> |

-         #end if

-         #end for

-         #if $rpmArch

-         <a href="rpmsbyhost?${util.passthrough($self, 'order', 'hostArch', prefix='')}">all</a>

-         #else

-         <strong>all</strong>

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($hostPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'rpmsbyhost?start=' + this.value * $hostRange + '$util.passthrough($self, 'order', 'hostArch', 'rpmArch')';">

-             #for $pageNum in $hostPages

-             <option value="$pageNum"#if $pageNum == $hostCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $hostStart > 0

-         <a href="rpmsbyhost?start=#echo $hostStart - $hostRange #$util.passthrough($self, 'order', 'hostArch', 'rpmArch')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalHosts != 0

-         <strong>Hosts #echo $hostStart + 1 # through #echo $hostStart + $hostCount # of $totalHosts</strong>

-         #end if

-         #if $hostStart + $hostCount < $totalHosts

-         <a href="rpmsbyhost?start=#echo $hostStart + $hostRange#$util.passthrough($self, 'order', 'hostArch', 'rpmArch')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="rpmsbyhost?order=$util.toggleOrder($self, 'name')$util.passthrough($self, 'hostArch', 'rpmArch')">Name</a> $util.sortImage($self, 'name')</th>

-       <th><a href="rpmsbyhost?order=$util.toggleOrder($self, 'rpms')$util.passthrough($self, 'hostArch', 'rpmArch')">RPMs</a> $util.sortImage($self, 'rpms')</th>

-       <th>&nbsp;</th>

-     </tr>

-     #if $len($hosts) > 0

-     #for $host in $hosts

-     <tr class="$util.rowToggle($self)">

-       <td><a href="hostinfo?hostID=$host.id">$host.name</a></td>

-       <td width="#echo $graphWidth + 5#"><img src="$util.themePath('images/1px.gif')" width="#echo $increment * $host.rpms#" height="15" class="graphrow" alt="graph row"/></td>

-       <td>$host.rpms</td>

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td colspan="3">No hosts</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($hostPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'rpmsbyhost?start=' + this.value * $hostRange + '$util.passthrough($self, 'order', 'hostArch', 'rpmArch')';">

-             #for $pageNum in $hostPages

-             <option value="$pageNum"#if $pageNum == $hostCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $hostStart > 0

-         <a href="rpmsbyhost?start=#echo $hostStart - $hostRange #$util.passthrough($self, 'order', 'hostArch', 'rpmArch')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalHosts != 0

-         <strong>Hosts #echo $hostStart + 1 # through #echo $hostStart + $hostCount # of $totalHosts</strong>

-         #end if

-         #if $hostStart + $hostCount < $totalHosts

-         <a href="rpmsbyhost?start=#echo $hostStart + $hostRange#$util.passthrough($self, 'order', 'hostArch', 'rpmArch')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

file removed
-118
@@ -1,118 +0,0 @@ 

- #from kojiweb import util

- #from urllib.parse import quote

- 

- #include "includes/header.chtml"

- 

- 

-   <h4>Search</h4>

-   <form action="search">

-     <table>

-       <tr>

-         #if $error

-         <tr><td colspan="5" class="error">$error</td></tr>

-         #end if

-         <th>Search</th>

-         <td><input type="text" name="terms" value="$terms"/></td>

-         <td>

-           <select name="type">

-             <option $util.toggleSelected($self, $type, "package") value="package">Packages</option>

-             <option $util.toggleSelected($self, $type, "build") value="build">Builds</option>

-             <option $util.toggleSelected($self, $type, "tag") value="tag">Tags</option>

-             <option $util.toggleSelected($self, $type, "target") value="target">Build Targets</option>

-             <option $util.toggleSelected($self, $type, "user") value="user">Users</option>

-             <option $util.toggleSelected($self, $type, "host") value="host">Hosts</option>

-             <option $util.toggleSelected($self, $type, "rpm") value="rpm">RPMs</option>

-             #if $mavenEnabled

-             <option $util.toggleSelected($self, $type, "maven") value="maven">Maven Artifacts</option>

-             #end if

-             #if $winEnabled

-             <option $util.toggleSelected($self, $type, "win") value="win">Windows Artifacts</option>

-             #end if

-           </select>

-         </td>

-         <td>

-           #if not $varExists('match')

-              #set $match='glob'

-           #end if

-           <input type="radio" name="match" value="glob" $util.toggleSelected($self, $match, "glob", True) id="radioglob"/><abbr title="? will match any single character, * will match any sequence of zero or more characters" id="abbrglob">glob</abbr>

-           <input type="radio" name="match" value="regexp" $util.toggleSelected($self, $match, "regexp", True) id="radioregexp"/><abbr title="full POSIX regular expressions" id="abbrregexp">regexp</abbr>

-           <input type="radio" name="match" value="exact" $util.toggleSelected($self, $match, "exact", True) id="radioexact"/><abbr title="exact matches only" id="abbrexact">exact</abbr>

-         </td>

-         <td colspan="2"><input type="submit" value="Search"/></td>

-       </tr>

-       <tr>

-         <td>&nbsp;</td>

-       </tr>

-     </table>

-   </form>

- 

- 

- #if $varExists('results')

- 

-   <table class="data-list">

-     <tr>

-       <td class="paginate" colspan="2">

-         #if $len($resultPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'search?start=' + this.value * $resultRange + '$util.passthrough($self, 'order', 'terms', 'type', 'match')';">

-             #for $pageNum in $resultPages

-             <option value="$pageNum"#if $pageNum == $resultCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $resultStart > 0

-         <a href="search?start=#echo $resultStart - $resultRange #$util.passthrough($self, 'order', 'terms', 'type', 'match')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalResults != 0

-         <strong>Results #echo $resultStart + 1 # through #echo $resultStart + $resultCount # of $totalResults</strong>

-         #end if

-         #if $resultStart + $resultCount < $totalResults

-         <a href="search?start=#echo $resultStart + $resultRange#$util.passthrough($self, 'order', 'terms', 'type', 'match')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="search?order=$util.toggleOrder($self, 'id')$util.passthrough($self, 'terms', 'type', 'match')">ID</a> $util.sortImage($self, 'id')</th>

-       <th><a href="search?order=$util.toggleOrder($self, 'name')$util.passthrough($self, 'terms', 'type', 'match')">Name</a> $util.sortImage($self, 'name')</th>

-     </tr>

-     #if $len($results) > 0

-     #for $result in $results

-     <tr class="$util.rowToggle($self)">

-       <td>$result.id</td>

-       <td><a href="${infoURL % $result}">$result.name</a></td>

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td colspan="2">No search results</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="2">

-         #if $len($resultPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'search?start=' + this.value * $resultRange + '$util.passthrough($self, 'order', 'terms', 'type', 'match')';">

-             #for $pageNum in $resultPages

-             <option value="$pageNum"#if $pageNum == $resultCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $resultStart > 0

-         <a href="search?start=#echo $resultStart - $resultRange #$util.passthrough($self, 'order', 'terms', 'type', 'match')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalResults != 0

-         <strong>Results #echo $resultStart + 1 # through #echo $resultStart + $resultCount # of $totalResults</strong>

-         #end if

-         #if $resultStart + $resultCount < $totalResults

-         <a href="search?start=#echo $resultStart + $resultRange#$util.passthrough($self, 'order', 'terms', 'type', 'match')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- #end if

- 

- #include "includes/footer.chtml"

file removed
-180
@@ -1,180 +0,0 @@ 

- #from kojiweb import util

- #from urllib.parse import quote

- #import pprint

- 

- #include "includes/header.chtml"

- 

-   <h4>Information for tag <a href="taginfo?tagID=$tag.id">$tag.name</a></h4>

- 

-   <table>

-     #if $child and 'admin' in $perms

-     <tr>

-       <th colspan="2"><a href="tagparent?tagID=$child.id&parentID=$tag.id&action=add$util.authToken($self)">Add $tag.name as parent of $child.name</a></th>

-     </tr>

-     #end if

-     <tr>

-       <th>Name</th><td>$tag.name</td>

-     </tr>

-     <tr>

-       <th>ID</th><td>$tag.id</td>

-     </tr>

-     <tr>

-       <th>Arches</th><td>$tag.arches</td>

-     </tr>

-     <tr>

-       <th>Locked</th><td class="$str(not $tag.locked).lower()">#if $tag.locked then 'yes' else 'no'#</td>

-     </tr>

-     <tr>

-       <th>Permission</th><td>#if $tag.perm_id then $allPerms[$tag.perm_id] else 'none'#</td>

-     </tr>

-     #if $mavenEnabled

-     <tr>

-       <th>Maven Support?</th><td class="$str($tag.maven_support).lower()">#if $tag.maven_support then 'yes' else 'no'#</td>

-     </tr>

-     <tr>

-       <th>Include All Maven Builds?</th><td class="$str($tag.maven_include_all).lower()">#if $tag.maven_include_all then 'yes' else 'no'#</td>

-     </tr>

-     #end if

-     <tr>

-       <th>Inheritance</th>

-       <td class="tree">

-         <span class="root">$tag.name</span>

-         #set $numParents = $len($inheritance)

-         #set $iter = 0

-         #set $maxDepth = 0

-         #set $TRUNC_DEPTH = 7

-         <ul>

-           #for $parent in $inheritance

-           #set $iter += 1

-           #set $nextDepth = ($iter < $numParents and $inheritance[$iter].currdepth or 1)

-           #set $depth = $parent.currdepth

-           #if $depth > $maxDepth

-           #set $maxDepth = $depth

-           #end if

-           #if $depth == $TRUNC_DEPTH and not $all

-           <li><span class="treeBranch"><span class="treeToggle treeLabel">...</span></span></li>

-           <li class="hidden">

-           #else if $len($tagsByChild[$parent.child_id]) > 1

-           <li class="sibling">

-           #else

-           <li>

-           #end if

-           #silent $tagsByChild[$parent.child_id].pop()

-             <span class="treeBranch">

-               <span class="treeLabel">

-                 <a href="taginfo?tagID=$parent.parent_id">$parent.name</a>

-                 #if $depth == 1 and 'admin' in $perms

-                 <span class="treeLink">(<a href="tagparent?tagID=$tag.id&parentID=$parent.parent_id&action=edit$util.authToken($self)">edit</a>) (<a href="tagparent?tagID=$tag.id&parentID=$parent.parent_id&action=remove$util.authToken($self)">remove</a>)</span>

-                 #end if

-               </span>

-             </span>

-            #if $nextDepth > $depth

-           <ul>

-           #else

-           </li>

-           #end if

-           #while $nextDepth < $depth

-           </ul>

-           </li>

-           #set $depth -= 1

-           #end while

-           #end for

-         </ul>

-       </td>

-     </tr>

-     #if $maxDepth >= $TRUNC_DEPTH

-     <tr>

-       <td colspan="2">

-         #if $all

-         <a href="taginfo?tagID=$tag.id$util.passthrough($self, 'inherited')">Show abbreviated tree</a>

-         #else

-         <a href="taginfo?tagID=$tag.id$util.passthrough($self, 'inherited')&all=1">Show full tree</a>

-         #end if

-       </td>

-     </tr>

-     #end if

-     #if 'admin' in $perms

-     <tr>

-       <td colspan="2"><a href="tags?childID=$tag.id">Add parent</a></td>

-     </tr>

-     #end if

-     #if $external_repos

-     <tr>

-       <th>External&nbsp;repos</th>

-       <td>

-         #for $external_repo in $external_repos

-         <a href="externalrepoinfo?extrepoID=$external_repo.external_repo_id">$external_repo.external_repo_name</a> [$external_repo.merge_mode]

-         #if $external_repo.tag_id != $tag.id

-         <span class="smaller">(inherited from <a href="taginfo?tagID=$external_repo.tag_id">$external_repo.tag_name</a>)</span>

-         #end if

-         <br/>

-         #end for

-       </td>

-     </tr>

-     #end if

-     <tr>

-       <th>Repo&nbsp;created</th>

-       <td>

-       #if $repo

-         <a href="repoinfo?repoID=$repo.id">$util.formatTimeRSS($repo.create_ts)</a>

-       #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Packages</th>

-       <td><a href="packages?blocked=0&tagID=$tag.id">$numPackages</a></td>

-     </tr>

-     <tr>

-       <th>Packages (blocked packages included)</th>

-       <td><a href="packages?tagID=$tag.id">$numPackagesBlocked</a></td>

-     </tr>

-     <tr>

-       <th>Builds</th>

-       <td><a href="builds?tagID=$tag.id">$numBuilds</a></td>

-     </tr>

-     <tr>

-       <th>Targets building from this tag</th>

-       <td>

-         #if $len($srcTargets)

-         #for $target in $srcTargets

-         <a href="buildtargetinfo?name=$quote($target.name)">$target.name</a><br/>

-         #end for

-         #else

-         No build targets

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Targets building to this tag</th>

-       <td>

-         #if $len($destTargets)

-         #for $target in $destTargets

-         <a href="buildtargetinfo?name=$quote($target.name)">$target.name</a><br/>

-         #end for

-         #else

-         No build targets

-         #end if

-       </td>

-     </tr>

-     #if 'admin' in $perms

-     <tr>

-       <td colspan="2"><a href="tagedit?tagID=$tag.id$util.authToken($self)">Edit tag</a></td>

-     </tr>

-     <tr>

-       <td colspan="2"><a href="tagdelete?tagID=$tag.id$util.authToken($self)">Delete tag</a></td>

-     </tr>

-     #end if

-     #if $tag.get('extra')

-     <tr>

-         <th>Extra options:</th>

-     </tr>

-     #for $key in $tag['extra']

-     <tr>

-         <th>$key</th>

-         <td>$pprint.pformat($tag['extra'][$key])</td>

-     </tr>

-     #end for

-     #end if

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,21 +0,0 @@ 

- #from kojiweb import util

- #from urllib.parse import quote

- #import pprint

- 

- #include "includes/header.chtml"

- 

-   <h4>Information for deleted tag <a href="taginfo?tagID=$tag.id">$tag.name</a></h4>

- 

-   <table>

-     <tr>

-       <th>Name</th><td>$tag.name</td>

-     </tr>

-     <tr>

-       <th>ID</th><td>$tag.id</td>

-     </tr>

-     <tr>

-       <th>Deleted</th><td>$util.formatTimeLong($delete_ts)</td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

file removed
-76
@@ -1,76 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <h4>Tags</h4>

-   <table class="data-list">

-     <tr>

-       <td class="paginate" colspan="2">

-         #if $len($tagPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tags?start=' + this.value * $tagRange + '$util.passthrough($self, 'userID', 'tagID', 'order', 'childID')';">

-             #for $pageNum in $tagPages

-             <option value="$pageNum"#if $pageNum == $tagCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $tagStart > 0

-         <a href="tags?start=#echo $tagStart - $tagRange #$util.passthrough($self, 'userID', 'tagID', 'order', 'childID')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalTags != 0

-         <strong>Tags #echo $tagStart + 1 # through #echo $tagStart + $tagCount # of $totalTags</strong>

-         #end if

-         #if $tagStart + $tagCount < $totalTags

-         <a href="tags?start=#echo $tagStart + $tagRange#$util.passthrough($self, 'userID', 'tagID', 'order', 'childID')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="tags?order=$util.toggleOrder($self, 'id')">ID</a> $util.sortImage($self, 'id')</th>

-       <th><a href="tags?order=$util.toggleOrder($self, 'name')">Name</a> $util.sortImage($self, 'name')</th>

-     </tr>

-     #if $len($tags) > 0

-       #for $tag in $tags

-         <tr class="$util.rowToggle($self)">

-           <td>$tag.id</td>

-           <td><a href="taginfo?tagID=$tag.id$util.passthrough($self, 'childID')">$tag.name</a></td>

-         </tr>

-       #end for

-     #else

-       <tr class="row-odd">

-         <td colspan="2">No tags</td>

-       </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="2">

-         #if $len($tagPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tags?start=' + this.value * $tagRange + '$util.passthrough($self, 'userID', 'tagID', 'order', 'childID')';">

-             #for $pageNum in $tagPages

-             <option value="$pageNum"#if $pageNum == $tagCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $tagStart > 0

-         <a href="tags?start=#echo $tagStart - $tagRange #$util.passthrough($self, 'userID', 'tagID', 'order', 'childID')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalTags != 0

-         <strong>Tags #echo $tagStart + 1 # through #echo $tagStart + $tagCount # of $totalTags</strong>

-         #end if

-         #if $tagStart + $tagCount < $totalTags

-         <a href="tags?start=#echo $tagStart + $tagRange#$util.passthrough($self, 'userID', 'tagID', 'order', 'childID')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

-   #if 'admin' in $perms

-   <br/>

-   <a href="tagcreate$util.authToken($self, first=True)">Create new Tag</a>

-   #end if

- 

- #include "includes/footer.chtml"

@@ -1,321 +0,0 @@ 

- #import koji

- #import koji.util as kojiutil

- #from kojiweb import util

- #from urllib.parse import quote

- #import datetime

- 

- #@util.safe_return

- #def printChildren($taskID, $childMap)

-   #set $iter = 0

-   #set $children = $childMap[$str($taskID)]

-   #if $children

-   <ul>

-     #for $child in $children

-     #set $iter += 1

-     #if $iter < $len($children)

-     <li class="sibling">

-     #else

-     <li>

-     #end if

-       #set $childState = $util.taskState($child.state)

-       <span class="treeBranch">

-         <span class="treeLabel">

-           <span class="task$childState">$util.imageTag($childState)</span>

-           <a href="taskinfo?taskID=$child.id" class="task$childState" title="$childState">$koji.taskLabel($child)</a>

-         </span>

-       </span>

-     $printChildren($child.id, $childMap)

-     </li>

-     #end for

-   </ul>

-   #end if

- #end def

- 

- #@util.safe_return

- #def printMap($vals, $prefix='')

-   #for $key, $value in $vals.items()

-   #if $key == 'properties'

-   ${prefix}properties&nbsp;=&nbsp;$printProperties($value)<br/>

-   #elif $key != '__starstar'

-   $prefix$key&nbsp;=&nbsp;$printValue($key, $value)<br/>

-   #end if

-   #end for

- #end def

- 

- #@util.safe_return

- #def printOpts($opts)

-   #if $opts

-   <strong>Options:</strong><br/>

-   $printMap($opts, '&nbsp;&nbsp;')

-   #end if

- #end def

- 

- #@util.safe_return

- #def printValue($key, $value, $sep=', ')

-   #if $value is None

- None

-   #elif $key == 'user'

- <a href="userinfo?userID=$value['id']">$value['name']</a>

-   #elif $key == 'task'

- <a href="taskinfo?taskID=$value['id']">$value['id']</a>

-   #elif $key == 'host'

- <a href="hostinfo?hostID=$value['id']">$value['name']</a>

-   #elif $key == 'build'

- <a href="buildinfo?buildID=$value['id']">$value['nvr']</a>

-   #elif $key == 'buildroot'

- <a href="buildrootinfo?buildrootID=$value['id']">$value['id']</a>

-   #elif $key in ('tag', 'destination_tag', 'build_tag')

- <a href="taginfo?tagID=$value['id']">$value['name']</a>

-   #elif $key in ('build_target', 'target_info')

- <a href="buildtargetinfo?targetID=$value['id']">$value['name']</a>

-   #elif $key in ('repo_info', 'oldrepo', 'repo')

-     #if $key == 'repo' and isinstance($value, list)

- $sep.join([$str($val) for $val in $value])

-     #else

- <a href="repoinfo?repoID=$value.id">$value.id</a> ($koji.formatTimeLong($value.create_ts))

-     #end if

-   #elif $key == 'task_list'

-     #for $task in $params['task_list']

-       <br/><strong>&nbsp;Task:</strong><br/>

-       $printMap($task, '&nbsp;&nbsp;')

-     #end for

-   #elif $isinstance($value, list)

- $sep.join([$str($val) for $val in $value])

-   #elif $isinstance($value, dict)

- $sep.join(['%s=%s' % (($n == '' and "''" or $n), $v) for $n, $v in $value.items()])

-   #else

- $value

-   #end if

- #end def

- 

- #@util.safe_return

- #def printProperties($props)

-   #echo ', '.join([$v is not None and '%s=%s' % ($n, $v) or $str($n) for $n, $v in $props.items()])

- #end def

- 

- 

- #include "includes/header.chtml"

- 

-   <h4>Information for task <a href="taskinfo?taskID=$task.id">$koji.taskLabel($task)</a></h4>

- 

-   <table>

-     <tr>

-       <th>ID</th><td>$task.id</td>

-     </tr>

-     <tr>

-       <th>Method</th><td>$task.method</td>

-     </tr>

-     <tr>

-       <th>Parameters</th>

-       <td>

-         #for key in $sorted($params)

-           #if $params[$key] is not None

-         <strong>$key.capitalize().replace('_', ' ')</strong>: $printValue($key, $params[$key])<br/>

-           #end if

-         #end for

-         $printOpts($opts)

-       </td>

-     </tr>

-     <tr>

-       #set $state = $util.taskState($task.state)

-       <th>State</th>

-       <td class="task$state">$state

-       #if $currentUser and ('admin' in $perms or $task.owner == $currentUser.id)

-       #if $task.state in ($koji.TASK_STATES.FREE, $koji.TASK_STATES.OPEN, $koji.TASK_STATES.ASSIGNED)

-       <span class="adminLink">(<a href="canceltask?taskID=$task.id$util.authToken($self)">cancel</a>)</span>

-       #elif $task.state in ($koji.TASK_STATES.CANCELED, $koji.TASK_STATES.FAILED) and (not $parent)

-       <span class="adminLink">(<a href="resubmittask?taskID=$task.id$util.authToken($self)">resubmit</a>)</span>

-       #end if

-       #end if

-       #if $currentUser and 'admin' in $perms and $task.state in ($koji.TASK_STATES.OPEN, $koji.TASK_STATES.ASSIGNED)

-       <span class="adminLink">(<a href="freetask?taskID=$task.id$util.authToken($self)">free</a>)</span>

-       #end if

-       </td>

-     </tr>

-     #if $taskBuilds

-     #for $build in $taskBuilds

-     <tr>

-       <th>Build</th><td><a href="buildinfo?buildID=$build.build_id">$koji.buildLabel($build)</a></td>

-     </tr>

-     #end for

-     #end if

-     <tr>

-       <th>Created</th><td>$util.formatTimeLong($task.create_ts)</td>

-     </tr>

-     #if $task.start_time

-     <tr>

-       <th>Started</th><td>$util.formatTimeLong($task.start_ts)</td>

-     #end if

-     #set $end_ts = None

-     #if $task.state == $koji.TASK_STATES.OPEN

-     #if $estCompletion

-     <tr>

-       <th title="Estimation based on previous builds of same package">Est. Completion</th>

-       <td>$util.formatTimeLong($estCompletion)</td>

-     </tr>

-     #end if

-     #elif $task.completion_time

-     <tr>

-       <th>Completed</th><td>$util.formatTimeLong($task.completion_ts)</td>

-     </tr>

-     #set $end_ts = $task.completion_ts

-     #end if

-     #if not $end_ts

-     #set $end_ts = $kojiutil.parseTime($kojiutil.encode_datetime(datetime.datetime.utcnow()))

-     #end if

-     <tr>

-       <th title="From task's creation">Total time</th>

-       <td>$util.formatTimestampDifference($task.create_ts, $end_ts)</td>

-     </tr>

-     #if $task.start_time

-     <tr>

-       <th title="From task's start">Task time</th>

-       <td>$util.formatTimestampDifference($task.start_ts, $end_ts)</td>

-     </tr>

-     #end if

-     <tr>

-       <th>Owner</th>

-       <td>

-         #if $owner

-           #if $owner.usertype == $koji.USERTYPES['HOST']

-           <a href="hostinfo?userID=$owner.id">$owner.name</a>

-           #else

-           <a href="userinfo?userID=$owner.id">$owner.name</a>

-           #end if

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Channel</th>

-       <td>

-         #if $task.channel_id

-         <a href="channelinfo?channelID=$task.channel_id">$channelName</a>

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Host</th>

-       <td>

-         #if $task.host_id

-         <a href="hostinfo?hostID=$task.host_id">$hostName</a>

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Arch</th><td>$task.arch</td>

-     </tr>

-     #if $buildroots

-     <tr>

-       <th>Buildroot#if $len($buildroots) > 1 then 's' else ''#</th>

-       <td>

-         #for $buildroot in $buildroots

-         <a href="buildrootinfo?buildrootID=$buildroot.id">#if $task.method == 'vmExec' then '' else '/var/lib/mock/'#$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a><br/>

-         #end for

-       </td>

-     </tr>

-     #end if

-     <tr>

-       <th>Parent</th>

-         <td>

-         #if $parent

-         <a href="taskinfo?taskID=$parent.id" class="task$util.taskState($parent.state)">$koji.taskLabel($parent)</a>

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Descendants</th>

-       <td class="tree">

-         #if $len($descendents[$str($task.id)]) > 0

-         #set $taskState = $util.taskState($task.state)

-         <span class="task$taskState">$util.imageTag($taskState)</span>

-         <span class="root">$task.method</span>

-         #end if

-         $printChildren($task.id, $descendents)

-       </td>

-     </tr>

-     <tr>

-       <th>Waiting?</th><td>#if $task.waiting then 'yes' else 'no'#</td>

-     </tr>

-     <tr>

-       <th>Awaited?</th><td>#if $task.awaited then 'yes' else 'no'#</td>

-     </tr>

-     <tr>

-       <th>Priority</th><td>$task.priority</td>

-     </tr>

-     <tr>

-       <th>Weight</th><td>#echo '%.2f' % $task.weight#</td>

-     </tr>

-     <tr>

-       <th>Result</th>

-       <td>

-       #if $abbr_result_text

-         <div id="abbr-result">

-         $abbr_result_text

-         </div>

-         <div id="full-result">

-         $full_result_text

-         </div>

-         <a href="#" collapse" id="toggle-abbreviated-result" style="display: none;">Show abbreviated results</a>

-         <a href="#" collapse" id="toggle-full-result" style="display: none;">Show complete results</a>

-       #else

-          <div id="result">

-         $full_result_text

-         </div>

-       #end if

-       </td>

-     </tr>

-     <tr>

-       <th>Output</th>

-       <td>

-         #for $volume, $filename in $output

-         <a href="$pathinfo.task($task.id, volume=$volume)/$quote($filename)">$filename</a>

-            #if $filename.endswith('.log')

-            (<a href="getfile?taskID=$task.id&volume=$volume&name=$quote($filename)&offset=-4000">tail</a>)

-            #end if

-         <br/>

-         #end for

-         #if not $output

-             <div title="Not all tasks produce outputs, and task outputs are not retained indefinitely.">No outputs reported</div>

-         #end if

-         #if $task.state not in ($koji.TASK_STATES.CLOSED, $koji.TASK_STATES.CANCELED, $koji.TASK_STATES.FAILED) and \

-             $task.method in ('buildSRPMFromSCM', 'buildArch', 'createLiveMedia', 'buildMaven', 'wrapperRPM', 'vmExec', 'createrepo', 'runroot', 'createAppliance', 'createLiveCD')

-         <br/>

-         <a href="watchlogs?taskID=$task.id">Watch logs</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #if $abbr_result_text

-   <script type="text/javascript">

-     (function() {

-        var abbr = document.getElementById('abbr-result');

-        var full = document.getElementById('full-result');

-        var link_to_show_abbr = document.getElementById('toggle-abbreviated-result');

-        var link_to_show_full = document.getElementById('toggle-full-result');

-        full.style.display = 'none';

-        abbr.style.display = 'block'

-        link_to_show_full.style.display = 'inline'

-        link_to_show_abbr.style.display = 'none'

-        var trigger = function(e) {

-          if (link_to_show_abbr.style.display == 'none') {

-            link_to_show_abbr.style.display = 'inline'

-            link_to_show_full.style.display = 'none'

-            abbr.style.display = 'none';

-            full.style.display = 'block'

-          }

-          else {

-            link_to_show_abbr.style.display = 'none'

-            link_to_show_full.style.display = 'inline'

-            abbr.style.display = 'block';

-            full.style.display = 'none'

-          }

-          return false;

-        };

- 

-        link_to_show_full.onclick = trigger

-        link_to_show_abbr.onclick = trigger

-     })();

-   </script>

- #end if

- #include "includes/footer.chtml"

file removed
-237
@@ -1,237 +0,0 @@ 

- #import koji

- #from kojiweb import util

- #from kojiweb.util import SafeValue as S

- 

- #@util.safe_return

- #def printChildren($taskID, $childMap)

-   #set $iter = 0

-   #set $children = $childMap[$str($taskID)]

-   #if $children

-   <ul>

-     #for $child in $children

-     #set $iter += 1

-     #if $iter < $len($children)

-     <li class="sibling">

-     #else

-     <li>

-     #end if

-       #set $childState = $util.taskState($child.state)

-       <span class="treeBranch">

-         <span class="treeLabel">

-           <a href="taskinfo?taskID=$child.id" class="task$childState" title="$childState">$koji.taskLabel($child)</a>

-         </span>

-       </span>

-     $printChildren($child.id, $childMap)

-     </li>

-     #end for

-   </ul>

-   #end if

- #end def

- 

- #@util.safe_return

- #def headerPrefix($state)

-   #if $state == 'active'

- Active

-   #elif $state == 'all'

- All

-   #else

- #echo $state.capitalize()

-   #end if

- #end def

- 

- #attr _PASSTHROUGH = ['owner', 'state', 'view', 'method', 'hostID', 'channelID', 'order']

- 

- #include "includes/header.chtml"

- 

- #@util.safe_return

- #def getDescription()

- $headerPrefix($state)

- #if $view == 'toplevel'

- toplevel

- #end if

- #if $method != 'all'

- $method Tasks

- #end if

- #if $ownerObj

- owned by <a href="userinfo?userID=$ownerObj.id">$ownerObj.name</a>

- #end if

- #if $host

- on host <a href="hostinfo?hostID=$host.id">$host.name</a>

- #end if

- #if $channel

- in channel <a href="channelinfo?channelID=$channel.id">$channel.name</a>

- #end if

- #end def

- 

-   <h4>$getDescription()</h4>

- 

-   <table class="data-list">

-     <tr>

-       <td colspan="6">

-         <form action="tasks">

-         <table class="nested">

-         <tr><td>

-         <strong>State</strong>:

-         </td><td>

-         <select name="state" class="filterlist" onchange="javascript: window.location = 'tasks?state=' + this.value + '$util.passthrough_except($self, 'state')';">

-           <option value="active" $util.toggleSelected($self, $state, 'active')>active</option>

-           <option value="all" $util.toggleSelected($self, $state, 'all')>all</option>

-           <option value="free" #if $state == 'free' then 'selected' else ''#>free</option>

-           <option value="open" #if $state == 'open' then 'selected' else ''#>open</option>

-           <option value="closed" #if $state == 'closed' then 'selected' else ''#>closed</option>

-           <option value="failed" #if $state == 'failed' then 'selected' else ''#>failed</option>

-           <option value="canceled" #if $state == 'canceled' then 'selected' else ''#>canceled</option>

-           <option value="assigned" #if $state == 'assigned' then 'selected' else ''#>assigned</option> 

-         </select>

-         </td><td>

-         <strong>Owner</strong>:

-         </td><td>

-         <select name="owner" class="filterlist" onchange="javascript: window.location = 'tasks?owner=' + this.value + '$util.passthrough_except($self, 'owner')';">

-           <option value="" #if not $owner then 'selected' else ''#>everyone</option>

-           #if $loggedInUser

-           <option value="$loggedInUser.name">me</option>

-           #end if

-           #for $user in $users

-           <option value="$user.name" #if $user.name == $owner then 'selected' else ''#>$user.name</option>

-           #end for

-         </select>

-         </td></tr>

-         <tr><td>

-         <strong>Method</strong>:

-         </td><td>

-         <select name="method" class="filterlist" onchange="javascript: window.location = 'tasks?method=' + this.value + '$util.passthrough_except($self, 'method')';">

-           <option value="all" $util.toggleSelected($self, $method, 'all')>all</option>

-           #for $task_type in $alltasks

-           #if $task_type in ('maven', 'buildMaven') and not $mavenEnabled

-           #continue

-           #elif $task_type in ('winbuild', 'vmExec') and not $winEnabled

-           #continue

-           #elif $task_type == 'wrapperRPM' and not ($mavenEnabled or $winEnabled)

-           #continue

-           #else

-           <option value="$task_type" #if $method == $task_type then 'selected' else ''#>$task_type</option>

-           #end if

-           #end for

-         </select>

-         </td><td>

-         <strong>View</strong>:

-         </td><td>

-         <select name="view" class="filterlist" onchange="javascript: window.location = 'tasks?view=' + this.value + '$util.passthrough_except($self, 'view')';">

-           <option value="tree" $util.toggleSelected($self, $view, 'tree') #if not $treeEnabled then 'disabled="disabled"' else ''#>tree</option>

-           <option value="toplevel" $util.toggleSelected($self, $view, 'toplevel') #if not $toplevelEnabled then 'disabled="disabled"' else ''#>toplevel</option>

-           <option value="flat" $util.toggleSelected($self, $view, 'flat')>flat</option>

-         </select>

-         </td></tr>

-         </table>

-         </form>

-       </td>

-     </tr>

-     <tr>

-       <td class="paginate" colspan="6">

-         #if $taskPages is not None

-         #if $len($taskPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tasks?start=' + this.value * $taskRange + '$util.passthrough_except($self)';">

-             #for $pageNum in $taskPages

-             <option value="$pageNum"#if $pageNum == $taskCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $taskStart > 0

-         <a href="tasks?start=#echo $taskStart - $taskRange #$util.passthrough_except($self)">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalTasks != 0

-         <strong>Tasks #echo $taskStart + 1 # through #echo $taskStart + $taskCount # of $totalTasks</strong>

-         #end if

-         #if $taskStart + $taskCount < $totalTasks

-         <a href="tasks?start=#echo $taskStart + $taskRange#$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-         #else

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tasks?start=' + this.value * $taskRange + '$util.passthrough_except($self)';">

-             <option value="0"#if 0 == $taskCurrentPage then ' selected' else ''#>#echo 1#</option>

-             <option value="1"#if 1 == $taskCurrentPage then ' selected' else ''#>#echo "load more"#</option>

-           </select>

-         </form>

-         <strong>Tasks #echo $taskStart + 1 # through #echo $taskStart + $taskCount# of ???</strong>

-         <a href="tasks?start=$taskRange$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="tasks?order=$util.toggleOrder($self, 'id')$util.passthrough_except($self, 'order')">ID</a> $util.sortImage($self, 'id')</th>

-       <th><a href="tasks?order=$util.toggleOrder($self, 'method')$util.passthrough_except($self, 'order')">Type</a> $util.sortImage($self, 'method')</th>

-       <th><a href="tasks?order=$util.toggleOrder($self, 'owner')$util.passthrough_except($self, 'order')">Owner</a> $util.sortImage($self, 'owner')</th>

-       <th><a href="tasks?order=$util.toggleOrder($self, 'arch')$util.passthrough_except($self, 'order')">Arch</a> $util.sortImage($self, 'arch')</th>

-       <th><a href="tasks?order=$util.toggleOrder($self, 'completion_time')$util.passthrough_except($self, 'order')">Finished</a> $util.sortImage($self, 'completion_time')</th>

-       <th><a href="tasks?order=$util.toggleOrder($self, 'state')$util.passthrough_except($self, 'order')">State</a> $util.sortImage($self, 'state')</th>

-     </tr>

-     #if $len($tasks) > 0

-       #for $task in $tasks

-         <tr class="$util.rowToggle($self)">

-           #set $taskState = $util.taskState($task.state)

-           <td>$task.id</td>

-           <td#if $treeDisplay then S(' class="tree"') else ''#>

-             #if $treeDisplay then '&nbsp;' else ''#<a href="taskinfo?taskID=$task.id" class="task$taskState" title="$taskState">$koji.taskLabel($task)</a>

-             #if $treeDisplay

-             $printChildren($task.id, $task.descendents)

-             #end if

-           </td>

-           <td class="user-$task.owner_name">

-             #if $task.owner_type == $koji.USERTYPES['HOST']

-             <a href="hostinfo?userID=$task.owner">$task.owner_name</a>

-             #else

-             <a href="userinfo?userID=$task.owner">$task.owner_name</a>

-             #end if

-           </td>

-           <td>$task.arch</td>

-           <td>$util.formatTime($task.completion_ts)</td>

-           <td class="task$state">$util.imageTag($taskState)</td>

-         </tr>

-       #end for

-     #else

-       <tr class="row-odd">

-         <td colspan="6">No tasks</td>

-       </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="6">

-         #if $taskPages is not None

-         #if $len($taskPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tasks?start=' + this.value * $taskRange + '$util.passthrough_except($self)';">

-             #for $pageNum in $taskPages

-             <option value="$pageNum"#if $pageNum == $taskCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $taskStart > 0

-         <a href="tasks?start=#echo $taskStart - $taskRange #$util.passthrough_except($self)">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalTasks != 0

-         <strong>Tasks #echo $taskStart + 1 # through #echo $taskStart + $taskCount # of $totalTasks</strong>

-         #end if

-         #if $taskStart + $taskCount < $totalTasks

-         <a href="tasks?start=#echo $taskStart + $taskRange#$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-         #else

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tasks?start=' + this.value * $taskRange + '$util.passthrough_except($self)';">

-             <option value="0"#if 0 == $taskCurrentPage then ' selected' else ''#>#echo 1#</option>

-             <option value="1"#if 1 == $taskCurrentPage then ' selected' else ''#>#echo "load more"#</option>

-           </select>

-         </form>

-         <strong>Tasks #echo $taskStart + 1 # through #echo $taskStart + $taskCount# of ???</strong>

-         <a href="tasks?start=$taskRange$util.passthrough_except($self)">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,89 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <h4>Tasks by Host#if $hostArch then ' (%s)' % $hostArch else ''#</h4>

-   <table class="data-list">

-     <tr>

-       <td class="archlist" colspan="3">

-         <strong>Host arch:</strong> #for $arch in $hostArchList

-         #if $arch == $hostArch

-         <strong>$arch</strong> |

-         #else

-         <a href="tasksbyhost?hostArch=$arch$util.passthrough($self, 'order')">$arch</a> |

-         #end if

-         #end for

-         #if $hostArch

-         <a href="tasksbyhost?${util.passthrough($self, 'order', prefix='')}">all</a>

-         #else

-         <strong>all</strong>

-         #end if

-       </td>

-     </tr>

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($hostPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tasksbyhost?start=' + this.value * $hostRange + '$util.passthrough($self, 'order', 'hostArch')';">

-             #for $pageNum in $hostPages

-             <option value="$pageNum"#if $pageNum == $hostCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $hostStart > 0

-         <a href="tasksbyhost?start=#echo $hostStart - $hostRange #$util.passthrough($self, 'order', 'hostArch')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalHosts != 0

-         <strong>Hosts #echo $hostStart + 1 # through #echo $hostStart + $hostCount # of $totalHosts</strong>

-         #end if

-         #if $hostStart + $hostCount < $totalHosts

-         <a href="tasksbyhost?start=#echo $hostStart + $hostRange#$util.passthrough($self, 'order', 'hostArch')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="tasksbyhost?order=$util.toggleOrder($self, 'name')$util.passthrough($self, 'hostArch')">Name</a> $util.sortImage($self, 'name')</th>

-       <th><a href="tasksbyhost?order=$util.toggleOrder($self, 'tasks')$util.passthrough($self, 'hostArch')">Tasks</a> $util.sortImage($self, 'tasks')</th>

-       <th>&nbsp;</th>

-     </tr>

-     #if $len($hosts) > 0

-     #for $host in $hosts

-     <tr class="$util.rowToggle($self)">

-       <td><a href="hostinfo?hostID=$host.id">$host.name</a></td>

-       <td width="#echo $graphWidth + 5#"><img src="$util.themePath('images/1px.gif')" width="#echo $increment * $host.tasks#" height="15" class="graphrow" alt="graph row"/></td>

-       <td>$host.tasks</td>

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td colspan="3">No hosts</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($hostPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tasksbyhost?start=' + this.value * $hostRange + '$util.passthrough($self, 'order', 'hostArch')';">

-             #for $pageNum in $hostPages

-             <option value="$pageNum"#if $pageNum == $hostCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $hostStart > 0

-         <a href="tasksbyhost?start=#echo $hostStart - $hostRange #$util.passthrough($self, 'order', 'hostArch')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalHosts != 0

-         <strong>Hosts #echo $hostStart + 1 # through #echo $hostStart + $hostCount # of $totalHosts</strong>

-         #end if

-         #if $hostStart + $hostCount < $totalHosts

-         <a href="tasksbyhost?start=#echo $hostStart + $hostRange#$util.passthrough($self, 'order', 'hostArch')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

@@ -1,73 +0,0 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

- 

-   <h4>Tasks by User</h4>

-   <table class="data-list">

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($userPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tasksbyuser?start=' + this.value * $userRange + '$util.passthrough($self, 'order')';">

-             #for $pageNum in $userPages

-             <option value="$pageNum"#if $pageNum == $userCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $userStart > 0

-         <a href="tasksbyuser?start=#echo $userStart - $userRange #$util.passthrough($self, 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalUsers != 0

-         <strong>Users #echo $userStart + 1 # through #echo $userStart + $userCount # of $totalUsers</strong>

-         #end if

-         #if $userStart + $userCount < $totalUsers

-         <a href="tasksbyuser?start=#echo $userStart + $userRange#$util.passthrough($self, 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-     <tr class="list-header">

-       <th><a href="tasksbyuser?order=$util.toggleOrder($self, 'name')">Name</a> $util.sortImage($self, 'name')</th>

-       <th><a href="tasksbyuser?order=$util.toggleOrder($self, 'tasks')">Tasks</a> $util.sortImage($self, 'tasks')</th>

-       <th>&nbsp;</th>

-     </tr>

-     #if $len($users) > 0

-     #for $user in $users

-     <tr class="$util.rowToggle($self)">

-       <td><a href="userinfo?userID=$user.id">$user.name</a></td>

-       <td width="#echo $graphWidth + 5#"><img src="$util.themePath('images/1px.gif')" width="#echo $increment * $user.tasks#" height="15" class="graphrow" alt="graph row"/></td>

-       <td>$user.tasks</td>

-     </tr>

-     #end for

-     #else

-     <tr class="row-odd">

-       <td colspan="3">No users</td>

-     </tr>

-     #end if

-     <tr>

-       <td class="paginate" colspan="3">

-         #if $len($userPages) > 1

-         <form class="pageJump" action="">

-           Page:

-           <select onchange="javascript: window.location = 'tasksbyuser?start=' + this.value * $userRange + '$util.passthrough($self, 'order')';">

-             #for $pageNum in $userPages

-             <option value="$pageNum"#if $pageNum == $userCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>

-             #end for

-           </select>

-         </form>

-         #end if

-         #if $userStart > 0

-         <a href="tasksbyuser?start=#echo $userStart - $userRange #$util.passthrough($self, 'order')">&lt;&lt;&lt;</a>

-         #end if

-         #if $totalUsers != 0

-         <strong>Users #echo $userStart + 1 # through #echo $userStart + $userCount # of $totalUsers</strong>

-         #end if

-         #if $userStart + $userCount < $totalUsers

-         <a href="tasksbyuser?start=#echo $userStart + $userRange#$util.passthrough($self, 'order')">&gt;&gt;&gt;</a>

-         #end if

-       </td>

-     </tr>

-   </table>

- 

- #include "includes/footer.chtml"

www/kojiweb/templates/Makefile www/kojiweb/includes/Makefile
file renamed
+2 -2
@@ -1,5 +1,5 @@ 

- SERVERDIR = /includes

- FILES = $(wildcard *.chtml)

+ SERVERDIR = /templates

+ FILES = $(wildcard *.html.j2)

  

  _default:

  	@echo "nothing to make.  try make install"

@@ -0,0 +1,29 @@ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+ #set _PASSTHROUGH = ['userID']

+ 

+ <h4>Active sessions for {{ loggedInUser.name }} user</h4>

+ <br>

+   <table class="data-list">

+      <tr class="list-header">

+       <th><a href="activesession?order={{ util.toggleOrder('id') }}{{ util.passthrough_except('order') }}">Session ID</a> {{ util.sortImage('id') }}</th>

+       <th><a href="activesession?order={{ util.toggleOrder('hostip') }}{{ util.passthrough_except('order') }}">Client IP</a> {{ util.sortImage('hostip') }}</th>

+       <th><a href="activesession?order={{ util.toggleOrder('authtype') }}{{ util.passthrough_except('order') }}">Auth type</a> {{ util.sortImage('authtype') }}</th>

+       <th><a href="activesession?order={{ util.toggleOrder('start_time') }}{{ util.passthrough_except('order') }}">Session start time</a> {{ util.sortImage('start_time') }}</th>

+       <th><a href="activesession?order={{ util.toggleOrder('start_time') }}{{ util.passthrough_except('order') }}">Length session</a> {{ util.sortImage('start_time') }}</th>

+       <th><a href="activesession?order={{ util.toggleOrder('id') }}{{ util.passthrough_except('order') }}">Logout?</a> {{ util.sortImage('id') }}</th>

+    </tr>

+     #for act in activesess

+     <tr class="{{ rowToggle(loop) }}">

+       <td>{{ act.id }}</td>

+       <td>{{ act.hostip }}</td>

+       <td>{{ act.authtype }}</td>

+       <td>{{ util.formatTimeLong(act.start_time) }}</td>

+       <td>{{ act.lengthSession }} days</td>

+       <td><a href="activesessiondelete?sessionID={{ act.id }}{{ util.authToken() }}">Logout</a></td>

+     </tr>

+     #endfor

+   </table>

+ 

+ #include "footer.html.j2"

www/kojiweb/templates/api.html.j2 www/kojiweb/api.chtml
file renamed
+8 -9
@@ -1,7 +1,6 @@ 

- #include "includes/header.chtml"

- #import koji

+ #include "header.html.j2"

  

- <h4>API reference <small>(hub version: $koji_version, web version: $koji.__version__)</small></h4>

+ <h4>API reference <small>(hub version: {{ koji_version }}, web version: {{ web_version }})</small></h4>

  

  Various constants used in API calls can be found in first part of <a

  href="https://pagure.io/koji/blob/master/f/koji/__init__.py">koji module</a>.
@@ -15,7 +14,7 @@ 

  import koji

  

  mytag = "mytag"

- session = koji.ClientSession("$koji_hub_url")

+ session = koji.ClientSession("{{ koji_hub_url }}")

  try:

      repo_info = session.getRepo(mytag, koji.REPO_STATES["READY"], dist=True)

      if not repo_info:
@@ -26,13 +25,13 @@ 

  

  <h4>List of API calls</h4>

  <ul>

- #for method in $methods

+ #for method in methods

    <li>

-      <pre><b>$method['name']$method['argdesc']</b>

-   $method['doc']

+      <pre><b>{{ method['name'] ~ method['argdesc'] }}</b>

+   {{ method['doc'] if method['doc'] is not none else '' }}

       </pre>

    </li>

- #end for

+ #endfor

  </ul>

  

- #include "includes/footer.chtml"

+ #include "footer.html.j2"

@@ -0,0 +1,160 @@ 

+ 

+ #set _PASSTHROUGH = ['archiveID', 'fileOrder', 'fileStart', 'buildrootOrder', 'buildrootStart']

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+   <h4>Information for archive <a href="archiveinfo?archiveID={{ archive.id }}">{{ archive.filename }}</a></h4>

+ 

+   <table>

+     <tr>

+       <th>ID</th><td>{{ archive.id }}</td>

+     </tr>

+     <tr>

+     #if wininfo

+       <th>File Name</th><td>{{ koji.pathinfo.winfile(archive) }}</td>

+     #else

+       <th>File Name</th><td>{{ archive.filename }}</td>

+     #endif

+     </tr>

+     #if archive.metadata_only

+     <tr>

+       <th>Metadata only</th><td>True (file not imported)</td>

+     </tr>

+     #endif

+     <tr>

+       <th>File Type</th><td>{{ archive_type.description }}</td>

+     </tr>

+     <tr>

+       <th>Build</th><td><a href="buildinfo?buildID={{ build.id }}">{{ koji.buildLabel(build) }}</a></td>

+     </tr>

+     #if maveninfo

+     <tr>

+       <th>Maven groupId</th><td>{{ archive.group_id }}</td>

+     </tr>

+     <tr>

+       <th>Maven artifactId</th><td>{{ archive.artifact_id }}</td>

+     </tr>

+     <tr>

+       <th>Maven version</th><td>{{ archive.version }}</td>

+     </tr>

+     #endif

+     <tr>

+       <th>Size</th><td><span title="{{ util.formatThousands(archive.size) }}">{{ util.formatNatural(archive.size) }}</span></td>

+     </tr>

+     <tr>

+       <th>Checksum</th><td>{{ archive.checksum }}</td>

+     </tr>

+     #if wininfo

+     <tr>

+       <th>Platforms</th><td>{{ archive.platforms }}</td>

+     </tr>

+     <tr>

+       <th>Flags</th><td>{{ archive.flags }}</td>

+     </tr>

+     #endif

+     #if builtInRoot

+     <tr>

+       <th>Buildroot</th><td><a href="buildrootinfo?buildrootID={{ builtInRoot.id }}">{{ util.brLabel(builtInRoot) }}</a></td>

+     </tr>

+     #endif

+     #if archive.get('extra')

+     <tr>

+       <th>Extra</th><td class="usertext">{{ archive.extra|pprint }}</td>

+     </tr>

+     #endif

+     #if files

+     <tr>

+       <th id="filelist">Files</th>

+       <td class="container">

+         <table class="nested data-list">

+           <tr>

+             <td class="paginate" colspan="2">

+               #if (filePages |length) > 1

+               <form class="pageJump">

+                 Page:

+                 <select onchange="javascript: window.location = 'archiveinfo?fileStart=' + this.value * {{ fileRange }} + '{{ util.passthrough_except('fileStart') }}#filelist';">

+                   #for pageNum in filePages

+                   <option value="{{ pageNum }}"{{ ' selected' if pageNum == fileCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+                   #endfor

+                 </select>

+               </form>

+               #endif

+               #if fileStart > 0

+               <a href="archiveinfo?fileStart={{ fileStart - fileRange }}{{ util.passthrough_except('fileStart') }}#filelist">&lt;&lt;&lt;</a>

+               #endif

+               <strong>{{ fileStart + 1  }} through {{ fileStart + fileCount  }} of {{ totalFiles }}</strong>

+               #if fileStart + fileCount < totalFiles

+               <a href="archiveinfo?fileStart={{ fileStart + fileRange }}{{ util.passthrough_except('fileStart') }}#filelist">&gt;&gt;&gt;</a>

+               #endif

+             </td>

+           </tr>

+           <tr class="list-header">

+             <th><a href="archiveinfo?fileOrder={{ util.toggleOrder('name', 'fileOrder') }}{{ util.passthrough_except('fileOrder', 'fileStart') }}#filelist">Name</a> {{ util.sortImage('name', 'fileOrder') }}</th>

+             <th><a href="archiveinfo?fileOrder={{ util.toggleOrder('size', 'fileOrder') }}{{ util.passthrough_except('fileOrder', 'fileStart') }}#filelist">Size</a> {{ util.sortImage('size', 'fileOrder') }}</th>

+           </tr>

+           #for file in files

+           <tr class="{{ rowToggle(loop) }}">

+             <td><a href="fileinfo?archiveID={{ archive.id }}&filename={{ file.name|urlencode }}">{{ file.name }}</a></td><td><span title="{{ util.formatThousands(file.size) }}">{{ util.formatNatural(file.size) }}</span></td>

+           </tr>

+           #endfor

+         </table>

+       </td>

+     </tr>

+     #endif

+     <tr>

+       <th id="buildrootlist">Component&nbsp;of</th>

+       <td class="container">

+         #if (buildroots |length) > 0

+         <table class="nested data-list">

+           <tr>

+             <td class="paginate" colspan="3">

+               #if (buildrootPages |length) > 1

+               <form class="pageJump" action="">

+                 Page:

+                 <select onchange="javascript: window.location = 'archiveinfo?buildrootStart=' + this.value * {{ buildrootRange }} + '{{ util.passthrough_except('buildrootStart') }}#buildrootlist';">

+                   #for pageNum in buildrootPages

+                   <option value="{{ pageNum }}"{{ ' selected' if pageNum == buildrootCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+                   #endfor

+                 </select>

+               </form>

+               #endif

+               #if buildrootStart > 0

+               <a href="archiveinfo?buildrootStart={{ buildrootStart - buildrootRange  }}{{ util.passthrough_except('buildrootStart') }}#buildrootlist">&lt;&lt;&lt;</a>

+               #endif

+               <strong>{{ buildrootStart + 1  }} through {{ buildrootStart + buildrootCount  }} of {{ totalBuildroots }}</strong>

+               #if buildrootStart + buildrootCount < totalBuildroots

+               <a href="archiveinfo?buildrootStart={{ buildrootStart + buildrootRange }}{{ util.passthrough_except('buildrootStart') }}#buildrootlist">&gt;&gt;&gt;</a>

+               #endif

+             </td>

+           </tr>

+           <tr class="list-header">

+             <th><a href="archiveinfo?buildrootOrder={{ util.toggleOrder('id', 'buildrootOrder') }}{{ util.passthrough_except('buildrootOrder', 'buildrootStart') }}#buildrootlist">Buildroot</a> {{ util.sortImage('id', 'buildrootOrder') }}</th>

+             <th><a href="archiveinfo?buildrootOrder={{ util.toggleOrder('create_event_time', 'buildrootOrder') }}{{ util.passthrough_except('buildrootOrder', 'buildrootStart') }}#buildrootlist">Created</a> {{ util.sortImage('create_event_time', 'buildrootOrder') }}</th>

+             <th><a href="archiveinfo?buildrootOrder={{ util.toggleOrder('state', 'buildrootOrder') }}{{ util.passthrough_except('buildrootOrder', 'buildrootStart') }}#buildrootlist">State</a> {{ util.sortImage('state', 'buildrootOrder') }}</th>

+           </tr>

+           #for buildroot in buildroots

+           <tr class="{{ rowToggle(loop) }}">

+             <td><a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ util.brLabel(buildroot) }}</a></td>

+             <td>{{ util.formatTime(buildroot.create_event_time) }}</td>

+             <td>{{ util.imageTag(util.brStateName(buildroot.state)) }}</td>

+           </tr>

+           #endfor

+         </table>

+         #else

+         No buildroots

+         #endif

+       </td>

+     </tr>

+     #if show_rpm_components

+     <tr>

+       <th colspan="2"><a href="rpmlist?imageID={{ archive.id }}&amp;type=image" title="RPM components that are part of this archive">RPM components</a></th>

+     </tr>

+     #endif

+     #if show_archive_components

+     <tr>

+       <th colspan="2"><a href="archivelist?imageID={{ archive.id }}&amp;type=image" title="Archive components that are part of this archive">Archive components</a></th>

+     </tr>

+     #endif

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,93 @@ 

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+ #macro getID()

+   #if type == 'image'

+ imageID={{ image.id }}

+   #else

+ buildrootID={{ buildroot.id }}

+   #endif

+ #endmacro

+ 

+   #if type == 'component'

+   <h4>Component Archives of buildroot <a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ util.brLabel(buildroot) }}</a></h4>

+   #elif type == 'image'

+   <h4>Archives installed in <a href="archiveinfo?archiveID={{ image.id }}">{{ image.filename }}</a></h4>

+   #else

+   <h4>Archives built in buildroot <a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ util.brLabel(buildroot) }}</a></h4>

+   #endif

+ 

+   <table class="data-list">

+     <tr>

+       <td class="paginate" colspan="{{ '3' if type == 'component' else '2' }}">

+         #if (archivePages |length) > 1

+         <form class="pageJump">

+           Page:

+           <select onchange="javascript: window.location = 'archivelist?{{ getID()|trim }}&start=' + this.value * {{ archiveRange }} + '{{ util.passthrough('order', 'type') }}';">

+             #for pageNum in archivePages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == archiveCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if archiveStart > 0

+         <a href="archivelist?{{ getID()|trim }}&start={{ archiveStart - archiveRange  }}{{ util.passthrough('order', 'type') }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalArchives != 0

+         <strong>Archives {{ archiveStart + 1  }} through {{ archiveStart + archiveCount  }} of {{ totalArchives }}</strong>

+         #endif

+         #if archiveStart + archiveCount < totalArchives

+         <a href="archivelist?{{ getID()|trim }}&start={{ archiveStart + archiveRange }}{{ util.passthrough('order', 'type') }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th><a href="archivelist?{{ getID()|trim }}&order={{ util.toggleOrder('filename') }}{{ util.passthrough('type') }}">Filename</a> {{ util.sortImage('filename') }}</th>

+       <th><a href="archivelist?{{ getID()|trim }}&order={{ util.toggleOrder('type_name') }}{{ util.passthrough('type') }}">Type</a> {{ util.sortImage('type_name') }}</th>

+       #if type == 'component'

+       <th><a href="archivelist?{{ getID()|trim }}&order={{ util.toggleOrder('project') }}{{ util.passthrough('type') }}">Build Dependency?</a> {{ util.sortImage('project') }}</th>

+       #endif

+     </tr>

+     #if (archives |length) > 0

+     #for archive in archives

+     <tr class="{{ rowToggle(loop) }}">

+       <td><a href="archiveinfo?archiveID={{ archive.id }}">{{ archive.filename }}</a></td>

+       <td>{{ archive.type_name }}</td>

+       #if type == 'component'

+       #set project = archive.project and 'yes' or 'no'

+       <td class="{{ project }}">{{ util.imageTag(project) }}</td>

+       #endif

+     </tr>

+     #endfor

+     #else

+     <tr class="row-odd">

+       <td colspan="{{ '3' if type == 'component' else '2' }}">No Archives</td>

+     </tr>

+     #endif

+     <tr>

+       <td class="paginate" colspan="{{ '3' if type == 'component' else '2' }}">

+         #if (archivePages |length) > 1

+         <form class="pageJump">

+           Page:

+           <select onchange="javascript: window.location = 'archivelist?{{ getID()|trim }}&start=' + this.value * {{ archiveRange }} + '{{ util.passthrough('order', 'type') }}';">

+             #for pageNum in archivePages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == archiveCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if archiveStart > 0

+         <a href="archivelist?{{ getID()|trim }}&start={{ archiveStart - archiveRange  }}{{ util.passthrough('order', 'type') }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalArchives != 0

+         <strong>Archives {{ archiveStart + 1  }} through {{ archiveStart + archiveCount  }} of {{ totalArchives }}</strong>

+         #endif

+         #if archiveStart + archiveCount < totalArchives

+         <a href="archivelist?{{ getID()|trim }}&start={{ archiveStart + archiveRange }}{{ util.passthrough('order', 'type') }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,261 @@ 

+ 

+ #include "header.html.j2"

+ #set nvrpath = pathinfo.build(build)

+ 

+   <h4>Information for build <a href="buildinfo?buildID={{ build.id }}">{{ koji.buildLabel(build) }}</a></h4>

+ 

+   <table>

+     <tr>

+       <th>ID</th><td>{{ build.id }}</td>

+     </tr>

+     <tr>

+       <th>Package Name</th><td><a href="packageinfo?packageID={{ build.package_id }}">{{ build.package_name }}</a></td>

+     </tr>

+     <tr>

+       <th>Version</th><td>{{ build.version }}</td>

+     </tr>

+     <tr>

+       <th>Release</th><td>{{ build.release }}</td>

+     </tr>

+     <tr>

+       <th>Epoch</th><td>{{ build.epoch if build.epoch is not none else '' }}</td>

+     </tr>

+     <tr>

+     #if build.draft

+       <th>Draft</th><td>True</td>

+     #else

+       <th>Draft</th><td>False</td>

+     #endif

+     </tr>

+     #if build.get('source')

+     <tr>

+       <th>Source</th><td>{{ build.source }}</td>

+     </tr>

+     #endif

+     #if 'maven' in typeinfo

+     <tr>

+       <th>Maven&nbsp;groupId</th><td>{{ typeinfo.maven.group_id }}</td>

+     </tr>

+     <tr>

+       <th>Maven&nbsp;artifactId</th><td>{{ typeinfo.maven.artifact_id }}</td>

+     </tr>

+     <tr>

+       <th>Maven&nbsp;version</th><td>{{ typeinfo.maven.version }}</td>

+     </tr>

+     #endif

+     #if 'module' in typeinfo

+     #if module_id

+     <tr>

+       <th>Module&nbsp;ID</th>

+     #if mbs_web_url

+       <td><a href="{{ mbs_web_url }}/module/{{ module_id }}">{{ module_id }}</a></td>

+     #else

+       <td>{{ module_id }}</td>

+     #endif

+     </tr>

+     #endif

+     #if module_tag

+     <tr>

+       <th>Module&nbsp;Tag</th><td><a href="taginfo?tagID={{ module_tag.id }}">{{ module_tag.name }}</a></td>

+     </tr>

+     #endif

+     #endif

+     #if summary

+     <tr>

+       <th>Summary</th><td class="rpmheader">{{ summary }}</td>

+     </tr>

+     #endif

+     #if description

+     <tr>

+       <th>Description</th><td class="rpmheader">{{ description }}</td>

+     </tr>

+     #endif

+     #if vcs

+     <tr>

+         <th><label title="Package source code VCS location">VCS</label></th><td>{{ util.formatLink(vcs) }}</td>

+     </tr>

+     #endif

+     #if disturl

+     <tr>

+         <th>DistURL</th><td>{{ util.formatLink(disturl) }}</td>

+     </tr>

+     #endif

+     <tr>

+       <th>Built by</th><td><a href="userinfo?userID={{ build.owner_id }}">{{ build.owner_name }}</a></td>

+     </tr>

+     <tr>

+       #set stateName = util.stateName(build.state)

+       <th>State</th>

+       <td class="{{ stateName }}">{{ stateName }}

+       #if build.state == koji.BUILD_STATES.BUILDING

+       #if currentUser and ('admin' in perms or build.owner_id == currentUser.id)

+       <span class="adminLink">(<a href="cancelbuild?buildID={{ build.id }}{{ util.authToken() }}">cancel</a>)</span>

+       #endif

+       #endif

+       </td>

+     </tr>

+     <tr>

+       <th>Volume</th>

+       <td>{{ build.volume_name }}</td>

+     </tr>

+     <tr>

+       <th>Started</th><td>{{ util.formatTimeLong(start_ts) }}</td>

+     </tr>

+     #if build.state == koji.BUILD_STATES.BUILDING

+     #if estCompletion

+     <tr>

+       <th>Est. Completion</th><td>{{ util.formatTimeLong(estCompletion) }}</td>

+     </tr>

+     #endif

+     #else

+     <tr>

+       <th>Completed</th><td>{{ util.formatTimeLong(build.completion_ts) }}</td>

+     </tr>

+     #endif

+     #if build.promotion_ts

+     <tr>

+       <th>Promoted</th><td>{{ util.formatTimeLong(build.promotion_ts) }}</td>

+     </tr>

+     <tr>

+       <th>Promoted by</th><td><a href="userinfo?userID={{ build.promoter_id }}">{{ build.promoter_name }}</a></td>

+     </tr>

+     #endif

+     #if build.cg_id

+     <tr>

+       <th>Content generator</th><td>{{ build.cg_name }}</td>

+     </tr>

+     #endif

+     #if task

+     <tr>

+       <th>Task</th><td><a href="taskinfo?taskID={{ task.id }}" class="task{{ util.taskState(task.state) }}">{{ koji.taskLabel(task) }}</a></td>

+     </tr>

+     #endif

+     #if build.get('extra')

+     <tr>

+       <th>Extra</th><td class="usertext">{{ build.extra|pprint }}</td>

+     </tr>

+     #endif

+     <tr>

+       <th>Tags</th>

+       <td class="container">

+         #if (tags |length) > 0

+         <table class="nested">

+           #for tag in tags

+           <tr>

+             <td><a href="taginfo?tagID={{ tag.id }}">{{ tag.name }}</a></td>

+           </tr>

+           #endfor

+         </table>

+         #else

+         No tags

+         #endif

+       </td>

+     </tr>

+     <tr>

+       <th>RPMs</th>

+       <td class="container">

+         #if (rpmsByArch |length) > 0

+         <table class="nested">

+           #if 'src' in rpmsByArch

+           <tr><th>src</th><th></th></tr>

+           #for rpm in rpmsByArch['src']

+           #set rpmfile = '%(name)s-%(version)s-%(release)s.%(arch)s.rpm' % rpm

+           #set rpmpath = pathinfo.rpm(rpm)

+           <tr>

+             <td></td>

+             #if rpm.metadata_only

+             <td>{{ rpmfile }} (<a href="rpminfo?rpmID={{ rpm.id }}">info</a>) (metadata only)</td>

+             #elif build.state == koji.BUILD_STATES.DELETED

+             <td>{{ rpmfile }} (<a href="rpminfo?rpmID={{ rpm.id }}">info</a>)

+             #else

+             <td>{{ rpmfile }} (<a href="rpminfo?rpmID={{ rpm.id }}">info</a>) (<a href="{{ nvrpath }}/{{ rpmpath }}">download</a>)</td>

+             #endif

+           </tr>

+           #endfor

+           #endif

+           #set arches = rpmsByArch.keys()

+           #for arch in arches|sort if arch != 'src'

+           <tr>

+             <th>{{ arch }}</th>

+           </tr>

+           #for rpm in rpmsByArch[arch]

+           <tr>

+             #set rpmfile = '%(name)s-%(version)s-%(release)s.%(arch)s.rpm' % rpm

+             #set rpmpath = pathinfo.rpm(rpm)

+             <td></td>

+             <td>

+               #if build.state != koji.BUILD_STATES.DELETED

+               {{ rpmfile }} (<a href="rpminfo?rpmID={{ rpm.id }}">info</a>) (<a href="{{ nvrpath }}/{{ rpmpath }}">download</a>)

+               #else

+               {{ rpmfile }} (<a href="rpminfo?rpmID={{ rpm.id }}">info</a>)

+               #endif

+             </td>

+           </tr>

+           #endfor

+           #endfor

+         </table>

+         #else

+         No RPMs

+         #endif

+       </td>

+     </tr>

+     #for btype in archiveIndex if archiveIndex[btype]

+     #set archivesByExt = archiveIndex[btype]

+     <tr>

+       <th>{{ btype.capitalize() }} Archives</th>

+       <td class="container">

+         <table class="nested">

+           #set exts = archivesByExt.keys()

+           #for ext in exts

+           <tr>

+             <th>{{ ext }}</th>

+           </tr>

+           #for archive in archivesByExt[ext]

+           <tr>

+             <td/>

+             <td>

+             #if archive.metadata_only or build.state == koji.BUILD_STATES.DELETED

+             {{ archive.display }} (<a href="archiveinfo?archiveID={{ archive.id }}">info</a>)

+             #else

+             {{ archive.display }} (<a href="archiveinfo?archiveID={{ archive.id }}">info</a>) (<a href="{{ archive.dl_url }}">download</a>)

+             #endif

+             </td>

+           </tr>

+           #endfor

+           #endfor

+         </table>

+       </td>

+     </tr>

+     #endfor

+     #if logs_by_dir

+     <tr>

+       <th>Logs</th>

+       <td class="container">

+         <table class="nested">

+           #set logdirs = logs_by_dir.keys()

+           #for logdir in logdirs

+           <tr>

+             <th>{{ logdir }}</th>

+           </tr>

+           #for loginfo in logs_by_dir[logdir]

+           <tr>

+             <td/>

+             <td>

+             <a href="{{ loginfo.dl_url }}">{{ loginfo.name }}</a>

+             </td>

+           </tr>

+           #endfor

+           #endfor

+         </table>

+       </td>

+     </tr>

+     #endif

+     #if changelog

+     <tr>

+       <th>Changelog</th>

+       <td class="changelog">{{ koji.util.formatChangelog(changelog) }}</td>

+     </tr>

+     #endif

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,59 @@ 

+ 

+ #include "header.html.j2"

+ 

+   <h4>Information for buildroot <a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ util.brLabel(buildroot) }}</a></h4>

+ 

+   <table>

+     <tr>

+       <th>Host</th><td><a href="hostinfo?hostID={{ buildroot.host_id }}">{{ buildroot.host_name }}</a></td>

+     </tr>

+     <tr>

+       <th>Arch</th><td>{{ buildroot.arch }}</td>

+     </tr>

+     <tr>

+       <th>ID</th><td>{{ buildroot.id }}</td>

+     </tr>

+     <tr>

+       <th>Task</th><td><a href="taskinfo?taskID={{ task.id }}" class="task{{ util.taskState(task.state) }}">{{ koji.taskLabel(task) }}</a></td>

+     </tr>

+     <tr>

+       <th>State</th><td>{{ util.imageTag(util.brStateName(buildroot.state)) }}</td>

+     </tr>

+     <tr>

+       <th>Created</th><td>{{ util.formatTimeLong(buildroot.create_event_time) }}</td>

+     </tr>

+     <tr>

+       <th>Retired</th><td>{{ util.formatTimeLong(buildroot.retire_event_time) }}</td>

+     </tr>

+     <tr>

+       <th>Repo ID</th><td><a href="repoinfo?repoID={{ buildroot.repo_id }}">{{ buildroot.repo_id }}</a></td>

+     </tr>

+     <tr>

+       <th>Repo Tag</th><td><a href="taginfo?tagID={{ buildroot.tag_id }}">{{ buildroot.tag_name }}</a></td>

+     </tr>

+     <tr>

+       <th>Repo State</th><td>{{ util.imageTag(util.repoStateName(buildroot.repo_state)) }}</td>

+     </tr>

+     <tr>

+       <th>Repo Created</th><td>{{ util.formatTimeLong(buildroot.repo_create_event_time) }}</td>

+     </tr>

+     #if buildroot.get('extra')

+     <tr>

+       <th>Extra</th><td class="usertext">{{ buildroot.extra| pprint }}</td>

+     </tr>

+     #endif

+     <tr>

+       <th colspan="2"><a href="rpmlist?buildrootID={{ buildroot.id }}&amp;type=component" title="RPMs that are installed into this buildroot when building packages">Component RPMs</a></th>

+     </tr>

+     <tr>

+       <th colspan="2"><a href="rpmlist?buildrootID={{ buildroot.id }}&amp;type=built" title="RPMs that have been built in this buildroot">Built RPMs</a></th>

+     </tr>

+     <tr>

+       <th colspan="2"><a href="archivelist?buildrootID={{ buildroot.id }}&type=component" title="Archives that are installed into this buildroot when building packages">Component Archives</a></th>

+     </tr>

+     <tr>

+       <th colspan="2"><a href="archivelist?buildrootID={{ buildroot.id }}&type=built" title="Archives that have been built in this buildroot">Built Archives</a></th>

+     </tr>

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,44 @@ 

+ 

+ #include "header.html.j2"

+ 

+   <h4>Information for external buildroot <a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ util.brLabel(buildroot) }}</a></h4>

+ 

+   <table>

+     <tr>

+       <th>ID</th><td>{{ buildroot.id }}</td>

+     </tr>

+     <tr>

+       <th>Host OS</th><td>{{ buildroot.host_os }}</td>

+     </tr>

+     <tr>

+       <th>Host Arch</th><td>{{ buildroot.host_arch }}</td>

+     </tr>

+     <tr>

+       <th>Content Generator</th><td>{{ buildroot.cg_name }} ({{ buildroot.cg_version }})</td>

+     </tr>

+     <tr>

+       <th>Container Type</th><td>{{ buildroot.container_type }}</td>

+     </tr>

+     <tr>

+       <th>Container Arch</th><td>{{ buildroot.container_arch }}</td>

+     </tr>

+     #if buildroot.get('extra')

+     <tr>

+       <th>Extra</th><td class="usertext">{{ buildroot.extra |pprint }}</td>

+     </tr>

+     #endif

+     <tr>

+       <th colspan="2"><a href="rpmlist?buildrootID={{ buildroot.id }}&amp;type=component" title="RPMs that are installed into this buildroot when building packages">Component RPMs</a></th>

+     </tr>

+     <tr>

+       <th colspan="2"><a href="rpmlist?buildrootID={{ buildroot.id }}&amp;type=built" title="RPMs that have been built in this buildroot">Built RPMs</a></th>

+     </tr>

+     <tr>

+       <th colspan="2"><a href="archivelist?buildrootID={{ buildroot.id }}&type=component" title="Archives that are installed into this buildroot when building packages">Component Archives</a></th>

+     </tr>

+     <tr>

+       <th colspan="2"><a href="archivelist?buildrootID={{ buildroot.id }}&type=built" title="Archives that have been built in this buildroot">Built Archives</a></th>

+     </tr>

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,96 @@ 

+ 

+ #set _PASSTHROUGH = ['repoID', 'order', 'state']

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+   <h4>Buildroots in repo <a href="repoinfo?repoID={{ repoID }}">{{ repoID }}</a></h4>

+ 

+   <table class="data-list">

+   <tr>

+       <td colspan="5">

+         <table class="nested">

+         <tr><td>

+         <strong>State</strong>:

+         </td><td>

+         <select name="state" class="filterlist" onchange="javascript: window.location = 'buildroots?state=' + this.value + '{{ util.passthrough_except('state') }}';">

+           <option value="all">all</option>

+           #for stateOpt in ['INIT', 'WAITING', 'BUILDING', 'EXPIRED']

+           <option value="{{ koji.BR_STATES[stateOpt] }}"{{ ' selected' if state == koji.BR_STATES[stateOpt] else '' }}>{{ stateOpt|lower }}</option>

+           #endfor

+         </select>

+         </table>

+         </td>

+        </tr>

+       <tr>

+       <td class="paginate" colspan="5">

+         #if (buildrootPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'buildroots?start=' + this.value * {{ buildrootRange }} + '{{ util.passthrough_except() }}';">

+             #for pageNum in buildrootPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == buildrootCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if buildrootStart > 0

+         <a href="buildroots?start={{ buildrootStart - buildrootRange  }}{{ util.passthrough_except() }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalBuildroots != 0

+         <strong>Buildroots {{ buildrootStart + 1  }} through {{ buildrootStart + buildrootCount  }} of {{ totalBuildroots }}</strong>

+         #endif

+         #if buildrootStart + buildrootCount < totalBuildroots

+         <a href="buildroots?start={{ buildrootStart + buildrootRange }}{{ util.passthrough_except() }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th><a href="buildroots?order={{ util.toggleOrder('id') }}{{ util.passthrough_except('order') }}">BuildrootID</a> {{ util.sortImage('id') }}</th>

+       <th><a href="buildroots?order={{ util.toggleOrder('repo_id') }}{{ util.passthrough_except('order') }}">Repo ID</a> {{ util.sortImage('repo_id') }}</th>

+       <th><a href="buildroots?order={{ util.toggleOrder('task_id') }}{{ util.passthrough_except('order') }}">Task ID</a> {{ util.sortImage('task_id') }}</th>

+       <th><a href="buildroots?order={{ util.toggleOrder('tag_name') }}{{ util.passthrough_except('order') }}">Tag name</a> {{ util.sortImage('tag_name') }}</th>

+       <th><a href="buildroots?order={{ util.toggleOrder('state') }}{{ util.passthrough_except('order') }}">State</a> {{ util.sortImage('state') }}</th>

+     </tr>

+     #if (buildroots |length) > 0

+       #for buildroot in buildroots

+         <tr class="{{ rowToggle(loop) }}">

+           <td><a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ buildroot.id }}</a></td>

+           <td><a href="repoinfo?repoID={{ buildroot.repo_id }}">{{ buildroot.repo_id }}</a></td>

+           <td><a href="taskinfo?taskID={{ buildroot.task_id }}">{{ buildroot.task_id }}</a></td>

+           <td><a href="taginfo?tagID={{ buildroot.tag_id }}">{{ buildroot.tag_name }}</a></td>

+           #set stateName = util.brStateName(buildroot.state)

+           <td class="{{ stateName }}">{{ util.brStateImage(buildroot.state) }}</td>

+         </tr>

+       #endfor

+     #else

+       <tr class="row-odd">

+         <td colspan="5">No buildroots</td>

+       </tr>

+     #endif

+     <tr>

+       <td class="paginate" colspan="5">

+         #if (buildrootPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'buildroots?start=' + this.value * {{ buildrootRange }} + '{{ util.passthrough_except() }}';">

+             #for pageNum in buildrootPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == buildrootCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if buildrootStart > 0

+         <a href="buildroots?start={{ buildrootStart - buildrootRange  }}{{ util.passthrough_except() }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalBuildroots != 0

+         <strong>Buildroots {{ buildrootStart + 1  }} through {{ buildrootStart + buildrootCount  }} of {{ totalBuildroots }}</strong>

+         #endif

+         #if buildrootStart + buildrootCount < totalBuildroots

+         <a href="buildroots?start={{ buildrootStart + buildrootRange }}{{ util.passthrough_except() }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,188 @@ 

+ 

+ #set _PASSTHROUGH = ['userID', 'tagID', 'packageID', 'order', 'prefix', 'state', 'inherited', 'latest', 'type']

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+ #macro getDescription()

+ #if latest

+ Latest

+ #elif state != None

+ {{ util.stateName(state)|capitalize }}

+ #endif

+ #if type

+ {{ type|capitalize }}

+ #endif

+ Builds

+ #if package

+ of <a href="packageinfo?packageID={{ package.id }}">{{ package.name }}</a>

+ #endif

+ #if user

+ by <a href="userinfo?userID={{ user.id }}">{{ user.name }}</a>

+ #endif

+ #if prefix

+ starting with &quot;{{ prefix }}&quot;

+ #endif

+ #if tag

+ in tag <a href="taginfo?tagID={{ tag.id }}">{{ tag.name }}</a>

+ #endif

+ #endmacro

+ 

+   <h4>{{ getDescription() }}</h4>

+ 

+   <table class="data-list">

+     <tr>

+       <td colspan="{{ '6' if tag else '5' }}">

+         <table class="nested">

+         <tr><td>

+         #if tag

+         <strong>Latest</strong>:

+         </td><td>

+         <select name="latest" class="filterlist" onchange="javascript: window.location = 'builds?latest=' + this.value + '{{ util.passthrough_except('latest') }}';">

+           <option value="1" {{ 'selected' if latest else '' }}>yes</option>

+           <option value="0" {{ 'selected' if not latest else '' }}>no</option>

+         </select>

+         #else

+         <strong>State</strong>:

+         </td><td>

+         <select name="state" class="filterlist" onchange="javascript: window.location = 'builds?state=' + this.value + '{{ util.passthrough_except('state') }}';">

+           <option value="all">all</option>

+           #for stateOpt in ['BUILDING', 'COMPLETE', 'FAILED', 'CANCELED']

+           <option value="{{ koji.BUILD_STATES[stateOpt] }}"{{ ' selected' if state == koji.BUILD_STATES[stateOpt] else '' }}>{{ stateOpt|lower }}</option>

+           #endfor

+         </select>

+         #endif

+         </td><td>

+         <strong>Built by</strong>:

+         </td><td>

+         <select name="userID" class="filterlist" onchange="javascript: window.location = 'builds?userID=' + this.value + '{{ util.passthrough_except('userID') }}';">

+           <option value="" {{ 'selected' if not user else '' }}>everyone</option>

+           #if loggedInUser

+           <option value="{{ loggedInUser.name }}">me</option>

+           #endif

+           #for userOption in users

+           <option value="{{ userOption.name }}" {{ 'selected' if userOption.name == (user and user.name or None) else '' }}>{{ userOption.name }}</option>

+           #endfor

+         </select>

+         </td></tr>

+         <tr>

+         <td>

+         <strong>Type</strong>:

+         </td>

+         <td>

+         <select name="type" class="filterlist" onchange="javascript: window.location='builds?type=' + this.value + '{{ util.passthrough_except('type') }}';">

+           <option value="all" {{ 'selected' if not type else '' }}>all</option>

+           #for btype in btypes

+           <option value="{{ btype }}" {{ 'selected' if type == btype else '' }}>{{ btype }}</option>

+           #endfor

+         </select>

+         </td>

+         #if tag

+         <td>

+         <strong>Inherited</strong>:

+         </td><td>

+         <select name="inherited" class="filterlist" onchange="javascript: window.location = 'builds?inherited=' + this.value + '{{ util.passthrough_except('inherited') }}';">

+           <option value="1" {{ 'selected' if inherited else '' }}>yes</option>

+           <option value="0" {{ 'selected' if not inherited else '' }}>no</option>

+         </select>

+         </td>

+         #endif

+         </tr>

+         </table>

+       </td>

+     </tr>

+     <tr>

+       <td class="charlist" colspan="{{ '6' if tag else '5' }}">

+         #for char in chars

+         #if prefix == char

+         <strong>{{ char }}</strong>

+         #else

+         <a href="builds?prefix={{ char }}{{ util.passthrough_except('prefix') }}">{{ char }}</a>

+         #endif

+         | 

+         #endfor

+         #if prefix

+         <a href="builds?{{ util.passthrough_except('prefix', prefix='') }}">all</a>

+         #else

+         <strong>all</strong>

+         #endif

+       </td>

+     </tr>

+     <tr>

+       <td class="paginate" colspan="{{ '6' if tag else '5' }}">

+         #if (buildPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'builds?start=' + this.value * {{ buildRange }} + '{{ util.passthrough_except() }}';">

+             #for pageNum in buildPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == buildCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if buildStart > 0

+         <a href="builds?start={{ buildStart - buildRange  }}{{ util.passthrough_except() }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalBuilds != 0

+         <strong>Builds {{ buildStart + 1  }} through {{ buildStart + buildCount  }} of {{ totalBuilds }}</strong>

+         #endif

+         #if buildStart + buildCount < totalBuilds

+         <a href="builds?start={{ buildStart + buildRange }}{{ util.passthrough_except() }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th><a href="builds?order={{ util.toggleOrder('build_id') }}{{ util.passthrough_except('order') }}">ID</a> {{ util.sortImage('build_id') }}</th>

+       <th><a href="builds?order={{ util.toggleOrder('nvr') }}{{ util.passthrough_except('order') }}">NVR</a> {{ util.sortImage('nvr') }}</th>

+       #if tag

+       <th><a href="builds?order={{ util.toggleOrder('tag_name') }}{{ util.passthrough_except('order') }}">Tag</a> {{ util.sortImage('tag_name') }}</th>

+       #endif

+       <th><a href="builds?order={{ util.toggleOrder('owner_name') }}{{ util.passthrough_except('order') }}">Built by</a> {{ util.sortImage('owner_name') }}</th>

+       <th><a href="builds?order={{ util.toggleOrder('completion_time') }}{{ util.passthrough_except('order') }}">Finished</a> {{ util.sortImage('completion_time') }}</th>

+       <th><a href="builds?order={{ util.toggleOrder('state') }}{{ util.passthrough_except('order') }}">State</a> {{ util.sortImage('state') }}</th>

+     </tr>

+     #if (builds |length) > 0

+       #for build in builds

+         <tr class="{{ rowToggle(loop) }}">

+           <td>{{ build.build_id }}</td>

+           <td><a href="buildinfo?buildID={{ build.build_id }}">{{ koji.buildLabel(build) }}</a></td>

+           #if tag

+           <td><a href="taginfo?tagID={{ build.tag_id }}">{{ build.tag_name }}</a></td>

+           #endif

+           <td class="user-{{ build.owner_name }}"><a href="userinfo?userID={{ build.owner_id }}">{{ build.owner_name }}</a></td>

+           <td>{{ util.formatTime(build.completion_time) }}</td>

+           #set stateName = util.stateName(build.state)

+           <td class="{{ stateName }}">{{ util.stateImage(build.state) }}</td>

+         </tr>

+       #endfor

+     #else

+       <tr class="row-odd">

+         <td colspan="{{ '6' if tag else '5' }}">No builds</td>

+       </tr>

+     #endif

+     <tr>

+       <td class="paginate" colspan="{{ '6' if tag else '5' }}">

+         #if (buildPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'builds?start=' + this.value * {{ buildRange }} + '{{ util.passthrough_except() }}';">

+             #for pageNum in buildPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == buildCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if buildStart > 0

+         <a href="builds?start={{ buildStart - buildRange  }}{{ util.passthrough_except() }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalBuilds != 0

+         <strong>Builds {{ buildStart + 1  }} through {{ buildStart + buildCount  }} of {{ totalBuilds }}</strong>

+         #endif

+         #if buildStart + buildCount < totalBuilds

+         <a href="builds?start={{ buildStart + buildRange }}{{ util.passthrough_except() }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,63 @@ 

+ 

+ #macro printOption(value, label=None)

+ #if not label

+ #set label = value

+ #endif

+ <option value="{{ value }}"{{ ' selected' if value == days else '' }}>{{ label }}</option>

+ #endmacro

+ 

+ #set numTotal = numSucceeded + numFailed + numCanceled

+ 

+ #include "header.html.j2"

+ 

+   <h4>Succeeded/Failed/Canceled Builds{{ ' in the last %i days' % days if days != -1 else '' }}</h4>

+   <table class="data-list">

+     <tr style="text-align: left">

+       <td colspan="3">

+         <form action="">

+           Show last

+           <select onchange="javascript: window.location = 'buildsbystatus?days=' + this.value;">

+             {{ printOption(1) }}

+             {{ printOption(3) }}

+             {{ printOption(5) }}

+             {{ printOption(7) }}

+             {{ printOption(14) }}

+             {{ printOption(30) }}

+             {{ printOption(60) }}

+             {{ printOption(90) }}

+             {{ printOption(120) }}

+             {{ printOption(180) }}

+             {{ printOption(365) }}

+             {{ printOption(-1, 'all') }}

+           </select> days

+         </form>

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th>Type</th>

+       <th>Builds</th>

+       <th>&nbsp;</th>

+     </tr>

+     <tr class="row-odd taskclosed">

+       <td>Succeeded</td>

+       <td width="{{ graphWidth + 5 }}"><img src="{{ util.themePath('images/1px.gif') }}" width="{{ increment * numSucceeded }}" height="15" class="graphrow" alt="graph row"/></td>

+       <td>{{ numSucceeded }}</td>

+     </tr>

+     <tr class="row-even taskfailed">

+       <td>Failed</td>

+       <td width="{{ graphWidth + 5 }}"><img src="{{ util.themePath('images/1px.gif') }}" width="{{ increment * numFailed }}" height="15" class="graphrow" alt="graph row"/></td>

+       <td>{{ numFailed }}</td>

+     </tr>

+     <tr class="row-odd taskcanceled">

+       <td>Canceled</td>

+       <td width="{{ graphWidth + 5 }}"><img src="{{ util.themePath('images/1px.gif') }}" width="{{ increment * numCanceled }}" height="15" class="graphrow" alt="graph row"/></td>

+       <td>{{ numCanceled }}</td>

+     </tr>

+     <tr class="row-even">

+       <td>Total</td>

+       <td></td>

+       <td>{{ numTotal }}</td>

+     </tr>

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,99 @@ 

+ 

+ #macro printOption(value, label=None)

+ #if not label

+ #set label = value

+ #endif

+ <option value="{{ value }}"{{ ' selected' if value == days else '' }}>{{ label }}</option>

+ #endmacro

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+   <h4>Builds by Target{{ ' in the last %i days' % days if days != -1 else '' }}</h4>

+   <table class="data-list">

+     <tr style="text-align: left">

+       <td colspan="3">

+         <form action="">

+           Show last

+           <select onchange="javascript: window.location = 'buildsbytarget?days=' + this.value + '{{ util.passthrough('order') }}';">

+             {{ printOption(1) }}

+             {{ printOption(3) }}

+             {{ printOption(5) }}

+             {{ printOption(7) }}

+             {{ printOption(14) }}

+             {{ printOption(30) }}

+             {{ printOption(60) }}

+             {{ printOption(90) }}

+             {{ printOption(120) }}

+             {{ printOption(-1, 'all') }}

+           </select> days

+         </form>

+       </td>

+     </tr>

+     <tr>

+       <td class="paginate" colspan="3">

+         #if (targetPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'buildsbytarget?start=' + this.value * {{ targetRange }} + '{{ util.passthrough('days', 'order') }}';">

+             #for pageNum in targetPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == targetCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if targetStart > 0

+         <a href="buildsbytarget?start={{ targetStart - targetRange  }}{{ util.passthrough('days', 'order') }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalTargets != 0

+         <strong>Build Targets {{ targetStart + 1  }} through {{ targetStart + targetCount  }} of {{ totalTargets }}</strong>

+         #endif

+         #if targetStart + targetCount < totalTargets

+         <a href="buildsbytarget?start={{ targetStart + targetRange }}{{ util.passthrough('days', 'order') }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th><a href="buildsbytarget?order={{ util.toggleOrder('name') }}{{ util.passthrough('days') }}">Name</a> {{ util.sortImage('name') }}</th>

+       <th><a href="buildsbytarget?order={{ util.toggleOrder('builds') }}{{ util.passthrough('days') }}">Builds</a> {{ util.sortImage('builds') }}</th>

+       <th>&nbsp;</th>

+     </tr>

+     #if (targets |length) > 0

+     #for target in targets

+     <tr class="{{ rowToggle(loop) }}">

+       <td><a href="buildtargetinfo?name={{ target.name|urlencode }}">{{ target.name }}</a></td>

+       <td width="{{ graphWidth + 5 }}"><img src={{ util.themePath('images/1px.gif') }} width="{{ increment * target.builds }}" height="15" class="graphrow" alt="graph row"/></td>

+       <td>{{ target.builds }}</td>

+     </tr>

+     #endfor

+     #else

+     <tr class="row-odd">

+       <td colspan="3">No builds</td>

+     </tr>

+     #endif

+     <tr>

+       <td class="paginate" colspan="3">

+         #if (targetPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'buildsbytarget?start=' + this.value * {{ targetRange }} + '{{ util.passthrough('days', 'order') }}';">

+             #for pageNum in targetPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == targetCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if targetStart > 0

+         <a href="buildsbytarget?start={{ targetStart - targetRange  }}{{ util.passthrough('days', 'order') }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalTargets != 0

+         <strong>Build Targets {{ targetStart + 1  }} through {{ targetStart + targetCount  }} of {{ totalTargets }}</strong>

+         #endif

+         #if targetStart + targetCount < totalTargets

+         <a href="buildsbytarget?start={{ targetStart + targetRange }}{{ util.passthrough('days', 'order') }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,73 @@ 

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+   <h4>Builds by User</h4>

+   <table class="data-list">

+     <tr>

+       <td class="paginate" colspan="3">

+         #if (userBuildPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'buildsbyuser?start=' + this.value * {{ userBuildRange }} + '{{ util.passthrough('order') }}';">

+             #for pageNum in userBuildPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == userBuildCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if userBuildStart > 0

+         <a href="buildsbyuser?start={{ userBuildStart - userBuildRange  }}{{ util.passthrough('order') }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalUserBuilds != 0

+         <strong>Users {{ userBuildStart + 1  }} through {{ userBuildStart + userBuildCount  }} of {{ totalUserBuilds }}</strong>

+         #endif

+         #if userBuildStart + userBuildCount < totalUserBuilds

+         <a href="buildsbyuser?start={{ userBuildStart + userBuildRange }}{{ util.passthrough('order') }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th><a href="buildsbyuser?order={{ util.toggleOrder('name') }}">Name</a> {{ util.sortImage('name') }}</th>

+       <th><a href="buildsbyuser?order={{ util.toggleOrder('builds') }}">Builds</a> {{ util.sortImage('builds') }}</th>

+       <th>&nbsp;</th>

+     </tr>

+     #if (userBuilds |length) > 0

+     #for userBuild in userBuilds

+     <tr class="{{ rowToggle(loop) }}">

+       <td><a href="userinfo?userID={{ userBuild.id }}">{{ userBuild.name }}</a></td>

+       <td width="{{ graphWidth + 5 }}"><img src="{{ util.themePath('images/1px.gif') }}" width="{{ increment * userBuild.builds }}" height="15" class="graphrow" alt="graph row"/></td>

+       <td>{{ userBuild.builds }}</td>

+     </tr>

+     #endfor

+     #else

+     <tr class="row-odd">

+       <td colspan="3">No users</td>

+     </tr>

+     #endif

+     <tr>

+       <td class="paginate" colspan="3">

+         #if (userBuildPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'buildsbyuser?start=' + this.value * {{ userBuildRange }} + '{{ util.passthrough('order') }}';">

+             #for pageNum in userBuildPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == userBuildCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if userBuildStart > 0

+         <a href="buildsbyuser?start={{ userBuildStart - userBuildRange  }}{{ util.passthrough('order') }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalUserBuilds != 0

+         <strong>Users {{ userBuildStart + 1  }} through {{ userBuildStart + userBuildCount  }} of {{ totalUserBuilds }}</strong>

+         #endif

+         #if userBuildStart + userBuildCount < totalUserBuilds

+         <a href="buildsbyuser?start={{ userBuildStart + userBuildRange }}{{ util.passthrough('order') }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+   </table>

+ 

+ #include "footer.html.j2"

www/kojiweb/templates/buildtargetedit.html.j2 www/kojiweb/buildtargetedit.chtml
file renamed
+22 -23
@@ -1,38 +1,37 @@ 

- #from kojiweb import util

  

- #include "includes/header.chtml"

+ #include "header.html.j2"

  

-   #if $target

-   <h4>Edit target $target.name</h4>

+   #if target

+   <h4>Edit target {{ target.name }}</h4>

    #else

    <h4>Create build target</h4>

-   #end if

+   #endif

  

-   <form action="#if $target then 'buildtargetedit' else 'buildtargetcreate'#">

-     $util.authToken($self, form=True)

-     #if $target

-     <input type="hidden" name="targetID" value="$target.id"/>

-     #end if

+   <form action="{{ 'buildtargetedit' if target else 'buildtargetcreate' }}">

+     {{ util.authToken(form=True) }}

+     #if target

+     <input type="hidden" name="targetID" value="{{ target.id }}"/>

+     #endif

      <table>

        <tr>

          <th>Name</th>

        <td>

-         <input type="text" name="name" size="50" value="#if $target then $target.name else ''#"/>

+         <input type="text" name="name" size="50" value="{{ target.name if target else '' }}"/>

        </td>

      </tr>

-     #if $target

+     #if target

      <tr>

-       <th>ID</th><td>$target.id</td>

+       <th>ID</th><td>{{ target.id }}</td>

      </tr>

-     #end if

+     #endif

      <tr>

        <th>Build Tag</th>

        <td>

          <select name="buildTag">

            <option value="">select tag</option>

-           #for $tag in $tags

-           <option value="$tag.id"#if $target and $target.build_tag == $tag.id then ' selected' else ''#>$tag.name</option>

-           #end for

+           #for tag in tags

+           <option value="{{ tag.id }}"{{ ' selected' if target and target.build_tag == tag.id else '' }}>{{ tag.name }}</option>

+           #endfor

          </select>

        </td>

      </tr>
@@ -41,23 +40,23 @@ 

        <td>

          <select name="destTag">

            <option value="">select tag</option>

-           #for $tag in $tags

-           <option value="$tag.id"#if $target and $target.dest_tag == $tag.id then ' selected' else ''#>$tag.name</option>

-           #end for

+           #for tag in tags

+           <option value="{{ tag.id }}"{{ ' selected' if target and target.dest_tag == tag.id else '' }}>{{ tag.name }}</option>

+           #endfor

          </select>

        </td>

      </tr>

      <tr>

        <td>

-         #if $target

+         #if target

          <button type="submit" name="save" value="Save">Save</button>

          #else

          <button type="submit" name="add" value="Add">Add</button>

-         #end if

+         #endif

        </td>

        <td><button type="submit" name="cancel" value="Cancel">Cancel</button></td>

      </tr>

      </table>

      </form>

  

- #include "includes/footer.chtml"

+ #include "footer.html.j2"

@@ -0,0 +1,28 @@ 

+ #include "header.html.j2"

+ 

+   <h4>Information for target <a href="buildtargetinfo?targetID={{ target.id }}">{{ target.name }}</a></h4>

+ 

+   <table>

+     <tr>

+       <th>Name</th><td>{{ target.name }}</td>

+     </tr>

+     <tr>

+       <th>ID</th><td>{{ target.id }}</td>

+     </tr>

+     <tr>

+       <th>Build Tag</th><td><a href="taginfo?tagID={{ buildTag.id }}">{{ buildTag.name }}</a></td>

+     </tr>

+     <tr>

+       <th>Destination Tag</th><td><a href="taginfo?tagID={{ destTag.id }}">{{ destTag.name }}</a></td>

+     </tr>

+     #if "admin" in perms

+     <tr>

+       <td colspan="2"><a href="buildtargetedit?targetID={{ target.id }}{{ util.authToken() }}">Edit</a></td>

+     </tr>

+     <tr>

+       <td colspan="2"><a href="buildtargetdelete?targetID={{ target.id }}{{ util.authToken() }}">Delete</a></td>

+     </tr>

+     #endif

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,76 @@ 

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+   <h4>Build Targets</h4>

+   <table class="data-list">

+     <tr>

+       <td class="paginate" colspan="2">

+         #if (targetPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'buildtargets?start=' + this.value * {{ targetRange }} + '{{ util.passthrough('order') }}';">

+             #for pageNum in targetPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == targetCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if targetStart > 0

+         <a href="buildtargets?start={{ targetStart - targetRange  }}{{ util.passthrough('order') }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalTargets != 0

+         <strong>Targets {{ targetStart + 1  }} through {{ targetStart + targetCount  }} of {{ totalTargets }}</strong>

+         #endif

+         #if targetStart + targetCount < totalTargets

+         <a href="buildtargets?start={{ targetStart + targetRange }}{{ util.passthrough('order') }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th><a href="buildtargets?order={{ util.toggleOrder('id') }}">ID</a> {{ util.sortImage('id') }}</th>

+       <th><a href="buildtargets?order={{ util.toggleOrder('name') }}">Name</a> {{ util.sortImage('name') }}</th>

+     </tr>

+     #if (targets |length) > 0

+     #for target in targets

+     <tr class="{{ rowToggle(loop) }}">

+       <td>{{ target.id }}</td>

+       <td><a href="buildtargetinfo?targetID={{ target.id }}">{{ target.name }}</a></td>

+     </tr>

+     #endfor

+     #else

+     <tr class="row-odd">

+       <td colspan="2">No build targets</td>

+     </tr>

+     #endif

+     <tr>

+       <td class="paginate" colspan="2">

+         #if (targetPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'buildtargets?start=' + this.value * {{ targetRange }} + '{{ util.passthrough('order') }}';">

+             #for pageNum in targetPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == targetCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if targetStart > 0

+         <a href="buildtargets?start={{ targetStart - targetRange  }}{{ util.passthrough('order') }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalTargets != 0

+         <strong>Targets {{ targetStart + 1  }} through {{ targetStart + targetCount  }} of {{ totalTargets }}</strong>

+         #endif

+         #if targetStart + targetCount < totalTargets

+         <a href="buildtargets?start={{ targetStart + targetRange }}{{ util.passthrough('order') }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+   </table>

+   

+   #if 'admin' in perms

+   <br/>

+   <a href="buildtargetcreate{{ util.authToken(first=True) }}">Create new Build Target</a>

+   #endif

+ 

+ #include "footer.html.j2"

www/kojiweb/templates/channelinfo.html.j2 www/kojiweb/channelinfo.chtml
file renamed
+22 -22
@@ -1,60 +1,60 @@ 

- #from kojiweb import util

  

- #include "includes/header.chtml"

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

  

-   <h4>Information for channel <a href="channelinfo?channelID=$channel.id">$channel.name</a></h4>

+   <h4>Information for channel <a href="channelinfo?channelID={{ channel.id }}">{{ channel.name }}</a></h4>

  

    <table>

      <tr>

-       <th>Name</th><td>$channel.name</td>

+       <th>Name</th><td>{{ channel.name }}</td>

      </tr>

      <tr>

-       <th>ID</th><td>$channel.id</td>

+       <th>ID</th><td>{{ channel.id }}</td>

      </tr>

      <tr>

-       <th>Description</th><td>$channel.description</td>

+       <th>Description</th><td>{{ channel.description or '' }}</td>

      </tr>

      <tr>

-       #set $enabled = $channel.enabled and 'yes' or 'no'

+       #set enabled = channel.enabled and 'yes' or 'no'

        <th>Enabled?</th>

-       <td class="$enabled">

-         $util.imageTag($enabled)

+       <td class="{{ enabled }}">

+         {{ util.imageTag(enabled) }}

        </td>

      </tr>

      <tr>

-       <th>Comment</th><td>$channel.comment</td>

+       <th>Comment</th><td>{{ channel.comment or '' }}</td>

      </tr>

      <tr>

-       <th>Active Tasks</th><td><a href="tasks?view=flat&channelID=$channel.id">$taskCount</a></td>

+       <th>Active Tasks</th><td><a href="tasks?view=flat&channelID={{ channel.id }}">{{ taskCount }}</a></td>

      </tr>

      <tr>

        <th>Hosts</th>

        <td>

-       #if $len($hosts) > 0

+       #if hosts | length > 0

        <table class="data-list">

          <tr class="list-header">

            <th>Hostname</th>

            <th>Enabled</th>

            <th>Ready</th>

          </tr>

-       #for $host in $hosts

-         <tr class="$util.rowToggle($self)">

-           <td><a href="hostinfo?hostID=$host.id">$host.name</a></td>

-           <td class="$str($bool($host.enabled)).lower()">#if $host.enabled then $util.imageTag('yes') else $util.imageTag('no')#</td>

-           <td class="$str($bool($host.ready)).lower()">#if $host.ready then $util.imageTag('yes') else $util.imageTag('no')#</td>

+       #for host in hosts

+         <tr class="{{ rowToggle(loop) }}">

+           <td><a href="hostinfo?hostID={{ host.id }}">{{ host.name }}</a></td>

+           <td class="{{ host.enabled |string |lower }}">{{ util.imageTag('yes') if host.enabled else util.imageTag('no') }}</td>

+           <td class="{{ host.ready |string |lower }}">{{ util.imageTag('yes') if host.ready else util.imageTag('no') }}</td>

          </tr>

-       #end for

+       #endfor

          <tr>

            <th>Total</th>

-           <td>$enabled_hosts</td>

-           <td>$ready_hosts</td>

+           <td>{{ enabled_hosts }}</td>

+           <td>{{ ready_hosts }}</td>

          </tr>

        </table>

        #else

        No hosts

-       #end if

+       #endif

        </td>

      </tr>

    </table>

  

- #include "includes/footer.chtml"

+ #include "footer.html.j2"

www/kojiweb/templates/clusterhealth.html.j2 www/kojiweb/clusterhealth.chtml
file renamed
+28 -30
@@ -1,14 +1,12 @@ 

- #from kojiweb import util

  

- #@util.safe_return

- #def printOption(value, label=None)

- #if not $label

- #set $label = $value

- #end if

- <option value="$value"#if $value == $arch then ' selected' else ''#>$label</option>

- #end def

+ #macro printOption(value, label=None)

+ #if not label

+ #set label = value

+ #endif

+ <option value="{{ value }}"{{ ' selected' if value == arch else '' }}>{{ label }}</option>

+ #endmacro

  

- #include "includes/header.chtml"

+ #include "header.html.j2"

  <style>

    span {

      display: inline-block;
@@ -43,11 +41,11 @@ 

        <td colspan="3">

          <form action="">

            Architecture:

-           <select onchange="javascript: window.location = 'clusterhealth?arch=' + this.value + '$util.passthrough($self, 'order')';">

-             $printOption('__all__', 'all')

-             #for $arch in $arches

-             $printOption($arch)

-             #end for

+           <select onchange="javascript: window.location = 'clusterhealth?arch=' + this.value + '{{ util.passthrough('order') }}';">

+             {{ printOption('__all__', 'all') }}

+             #for arch in arches

+             {{ printOption(arch) }}

+             #endfor

            </select>

          </form>

        </td>
@@ -57,29 +55,29 @@ 

        <th>Load/Capacity</th>

        <th>Builder readiness</th>

      </tr>

-     #for $channel in $channels

-     #if $channel['enabled_channel']

+     #for channel in channels

+     #if channel['enabled_channel']

      <tr>

        <th>

-           <a href="channelinfo?channelID=$channel['id']">$channel['name']</a>

+           <a href="channelinfo?channelID={{ channel.id }}">{{ channel.name }}</a>

        </th>

-       <td width="$graphWidth" class="graph">

-         #if $channel['capacityPerc']

-         <span style="width: $channel['capacityPerc']%">

-           <span style="width: #echo $channel['perc_load']#%" class="busy" title="Load: #echo int($channel['load'])#"></span>

-           <span style="width: #echo 100 - $channel['perc_load']#%" class="free" title="Free capacity: #echo int($channel['capacity'] - $channel['load'])#">#echo int(100 - $channel['perc_load'])#%&nbsp;</span>

+       <td width="{{ graphWidth }}" class="graph">

+         #if channel['capacityPerc']

+         <span style="width: {{ channel.capacityPerc }}%">

+           <span style="width: {{ channel.perc_load }}%" class="busy" title="Load: {{ channel.load|int }}"></span>

+           <span style="width: {{ 100 - channel.perc_load }}%" class="free" title="Free capacity: {{ (channel.capacity - channel.load)|int }}">{{ (100 - channel.perc_load)|int }}%&nbsp;</span>

          </span>

-         #end if

+         #endif

        </td>

-       <td width="$graphWidth" class="graph">

-         <span style="width: #echo $channel['enabledPerc']#%">

-           <span style="width: #echo 100 - $channel['perc_ready']#%" class="busy" title="Busy builders: #echo $channel['enabled'] - $channel['ready']#"></span>

-           <span style="width: #echo $channel['perc_ready']#%" class="free" title="Ready builders: $channel['ready']"">#echo int($channel['ready'])#&nbsp;</span>

+       <td width="{{ graphWidth }}" class="graph">

+         <span style="width: {{ channel.enabledPerc }}%">

+           <span style="width: {{ 100 - channel.perc_ready }}%" class="busy" title="Busy builders: {{ channel.enabled - channel.ready }}"></span>

+           <span style="width: {{ channel.perc_ready }}%" class="free" title="Ready builders: {{ channel.ready }}"">{{ channel.ready|int }}&nbsp;</span>

          </span>

        </td>

      </tr>

-     #end if

-     #end for

+     #endif

+     #endfor

    </table>

  

- #include "includes/footer.chtml"

+ #include "footer.html.j2"

www/kojiweb/templates/error.html.j2 www/kojiweb/error.chtml
file renamed
+9 -11
@@ -1,29 +1,27 @@ 

- #from kojiweb import util

- 

- #include "includes/header.chtml"

+ #include "header.html.j2"

  

    <h4>Error</h4>

  

  <div>

- $explanation

+ {{ explanation }}

  </div>

  

- #if $debug_level >= 1

+ #if debug_level >= 1

  <div>

  #else

  <div style="visibility: hidden">

- #end if

- $tb_short

+ #endif

+ {{ tb_short }}

  </div>

  

- #if $debug_level >= 2

+ #if debug_level >= 2

  <div>

  #else

  <div style="visibility: hidden">

- #end if

+ #endif

  <pre>

- #echo $tb_long

+ {{ tb_long }}

  </pre>

  </div>

  

- #include "includes/footer.chtml"

+ #include "footer.html.j2"

www/kojiweb/templates/externalrepoinfo.html.j2 www/kojiweb/externalrepoinfo.chtml
file renamed
+11 -13
@@ -1,31 +1,29 @@ 

- #from kojiweb import util

+ #include "header.html.j2"

  

- #include "includes/header.chtml"

- 

-   <h4>Information for external repo <a href="externalrepoinfo?extrepoID=$extRepo.id">$extRepo.name</a></h4>

+   <h4>Information for external repo <a href="externalrepoinfo?extrepoID={{ extRepo.id }}">{{ extRepo.name }}</a></h4>

  

    <table>

      <tr>

-       <th>Name</th><td>$extRepo.name</td>

+       <th>Name</th><td>{{ extRepo.name }}</td>

      </tr>

      <tr>

-       <th>ID</th><td>$extRepo.id</td>

+       <th>ID</th><td>{{ extRepo.id }}</td>

      </tr>

      <tr>

-       <th>URL</th><td><a href="$extRepo.url">$extRepo.url</a></td>

+       <th>URL</th><td><a href="{{ extRepo.url }}">{{ extRepo.url }}</a></td>

      </tr>

      <tr>

        <th>Tags using this external repo</th>

        <td>

-         #if $len($repoTags)

-         #for $tag in $repoTags

-         <a href="taginfo?tagID=$tag.tag_id">$tag.tag_name</a><br/>

-         #end for

+         #if repoTags|length

+         #for tag in repoTags

+         <a href="taginfo?tagID={{ tag.tag_id }}">{{ tag.tag_name }}</a><br/>

+         #endfor

          #else

          No tags

-         #end if

+         #endif

        </td>

      </tr>

    </table>

  

- #include "includes/footer.chtml"

+ #include "footer.html.j2"

@@ -0,0 +1,61 @@ 

+ 

+ #include "header.html.j2"

+   #if rpm

+   <h4>Information for file <a href="fileinfo?rpmID={{ rpm.id }}&amp;filename={{ file.name|urlencode }}">{{ file.name }}</a></h4>

+   #elif archive

+   <h4>Information for file <a href="fileinfo?archiveID={{ archive.id }}&amp;filename={{ file.name|urlencode }}">{{ file.name }}</a></h4>

+   #endif

+ 

+   <table>

+     <tr>

+       <th>Name</th><td>{{ file.name }}</td>

+     </tr>

+     #if rpm

+     <tr>

+       <th>Digest ({{ file.digest_algo }})</th><td>{{ file.digest }}</td>

+     </tr>

+     #endif

+     <tr>

+       <th>Size</th><td><span title="{{ util.formatThousands(file.size) }}">{{ util.formatNatural(file.size) }}</span></td>

+     </tr>

+     #if 'mtime' in file and file.mtime

+     <tr>

+       <th>Modification time</th><td>{{ util.formatTimeLong(file.mtime) }}</td>

+     </tr>

+     #endif

+     #if 'user' in file and file.user

+     <tr>

+       <th>User</th><td>{{ file.user }}</td>

+     </tr>

+     #endif

+     #if 'group' in file and file.group

+     <tr>

+       <th>Group</th><td>{{ file.group }}</td>

+     </tr>

+     #endif

+     #if 'mode' in file and file.mode

+     <tr>

+       <th>Mode</th><td class="rpmheader">{{ util.formatMode(file.mode) }}</td>

+     </tr>

+     #endif

+     #if rpm

+     <tr>

+       <th>Flags</th>

+       <td>

+         #for flag in util.formatFileFlags(file.flags)

+         {{ flag }}<br/>

+         #endfor

+       </td>

+     </tr>

+     <tr>

+       #set epoch = ( rpm.epoch ~ ':' if rpm.epoch is not none else '')

+       <th>RPM</th><td><a href="rpminfo?rpmID={{ rpm.id }}">{{ rpm.name }}-{{ epoch }}{{ rpm.version }}-{{ rpm.release }}.{{ rpm.arch }}.rpm</a></td>

+     </tr>

+     #elif archive

+     <tr>

+       <th>Archive</th><td><a href="archiveinfo?archiveID={{ archive.id }}">{{ archive.filename }}</a></td>

+     </tr>

+     #endif

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,12 @@ 

+         </div>

+ 

+         <p id="footer">

+           Copyright &copy; 2006-2016 Red Hat, Inc.

+           <a href="https://pagure.io/koji/"><img src="{{ themePath('images/powered-by-koji.png') }}" alt="Powered By Koji" id="PoweredByKojiLogo"/></a>

+         </p>

+ {{ localfooter }}

+       </div>

+     </div>

+ {{ localbottom }}

+   </body>

+ </html>

www/kojiweb/templates/header.html.j2 www/kojiweb/includes/header.chtml
file renamed
+29 -40
@@ -1,55 +1,43 @@ 

- #encoding UTF-8

- #import koji

- #from kojiweb import util

- #from koji_cli.lib import greetings

- #import random

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  

- #def greeting()

- #echo $random.choice($greetings)##slurp

- #end def

  

  <html xmlns="http://www.w3.org/1999/xhtml">

    <head>

      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

-     <title>$title | $siteName</title>

-     <link rel="shortcut icon" href="$util.themePath('images/koji.ico')"/>

-     <link rel="stylesheet" type="text/css" media="screen" title="Koji Style" href="$util.themePath('koji.css')"/>

-     <link rel="alternate stylesheet" type="text/css" media="screen" title="Debug" href="$util.themePath('debug.css')"/>

+     <title>{{ title }} | {{ siteName }}</title>

+     <link rel="shortcut icon" href="{{ themePath('images/koji.ico') }}"/>

+     <link rel="stylesheet" type="text/css" media="screen" title="Koji Style" href="{{ themePath('koji.css') }}"/>

+     <link rel="alternate stylesheet" type="text/css" media="screen" title="Debug" href="{{ themePath('debug.css') }}"/>

      <link rel="alternate" type="application/rss+xml" title="Koji: recent builds" href="/koji/recentbuilds"/>

    </head>

-   <body id="$pageID">

+   <body id="{{ pageID }}">

  

      <div id="wrap">

        <div id="innerwrap">

  

          <!-- HEADER -->

          <div id="header">

-           <img src="$util.themePath('images/koji.png')" alt="Koji Logo" id="kojiLogo"/>

- #set $localnavpath=$util.themePath("extra-nav.html", local=True)

- #if os.path.exists($localnavpath)

- #set $localnav=$util.SafeValue("".join(open($localnavpath, 'rt', encoding='utf-8').readlines()))

- $localnav

- #end if

+           <img src="{{ themePath('images/koji.png') }}" alt="Koji Logo" id="kojiLogo"/>

+ {{ localnav }}

            <form action="search" id="headerSearch">

              <input type="hidden" name="match" value="glob"/>

              <select name="type">

-               <option $util.toggleSelected($self, $type, "package") value="package">Packages</option>

-               <option $util.toggleSelected($self, $type, "build") value="build">Builds</option>

-               <option $util.toggleSelected($self, $type, "tag") value="tag">Tags</option>

-               <option $util.toggleSelected($self, $type, "target") value="target">Build Targets</option>

-               <option $util.toggleSelected($self, $type, "user") value="user">Users</option>

-               <option $util.toggleSelected($self, $type, "host") value="host">Hosts</option>

-               <option $util.toggleSelected($self, $type, "rpm") value="rpm">RPMs</option>

-               #if $mavenEnabled

-               <option $util.toggleSelected($self, $type, "maven") value="maven">Maven Artifacts</option>

-               #end if

-               #if $winEnabled

-               <option $util.toggleSelected($self, $type, "win") value="win">Windows Artifacts</option>

-               #end if

+               <option {{ toggleSelected(type, "package") }} value="package">Packages</option>

+               <option {{ toggleSelected(type, "build") }} value="build">Builds</option>

+               <option {{ toggleSelected(type, "tag") }} value="tag">Tags</option>

+               <option {{ toggleSelected(type, "target") }} value="target">Build Targets</option>

+               <option {{ toggleSelected(type, "user") }} value="user">Users</option>

+               <option {{ toggleSelected(type, "host") }} value="host">Hosts</option>

+               <option {{ toggleSelected(type, "rpm") }} value="rpm">RPMs</option>

+               {%- if mavenEnabled %}

+               <option {{ toggleSelected(type, "maven") }} value="maven">Maven Artifacts</option>

+               {%- endif %}

+               {%- if winEnabled %}

+               <option {{ toggleSelected(type, "win") }} value="win">Windows Artifacts</option>

+               {%- endif %}

              </select>

-             <input type="text" name="terms" title="You can use glob expressions here (e.g. 'bash-*')" value="$terms"/>

+             <input type="text" name="terms" title="You can use glob expressions here (e.g. 'bash-*')" value="{{ terms }}"/>

              <input type="submit" value="Search"/>

            </form>

          </div><!-- end header -->
@@ -73,15 +61,16 @@ 

          </div><!-- end mainNav -->

  

          <span id="loginInfo">

-           $koji.formatTimeLong($currentDate)

-           #if not $LoginDisabled

+           {{ date_str }}

+           {%- if not LoginDisabled %}

             |

-           #if $currentUser

-           $greeting(), <a href="userinfo?userID=$currentUser.id">$currentUser.name</a> | <a href="logout">logout</a>

-           #else

+           {%- if currentUser %}

+           {{ greeting }}, <a href="userinfo?userID={{ currentUser.id }}">{{ currentUser.name }}</a> | <a href="logout">logout</a>

+           {%- else %}

            <a href="login">login</a>

-           #end if

-           #end if

+           {%- endif %}

+           {%- endif %}

          </span>

  

          <div id="content">

+ 

www/kojiweb/templates/hostedit.html.j2 www/kojiweb/hostedit.chtml
file renamed
+15 -16
@@ -1,50 +1,49 @@ 

- #from kojiweb import util

  

- #include "includes/header.chtml"

+ #include "header.html.j2"

  

-   <h4>Edit host $host.name</h4>

+   <h4>Edit host {{ host.name }}</h4>

  

    <form action="hostedit">

-     $util.authToken($self, form=True)

+     {{ util.authToken(form=True) }}

      <table>

        <tr>

          <th>Name</th>

-         <td>$host.name</td>

+         <td>{{ host.name }}</td>

        </tr>

        <tr>

          <th>ID</th>

          <td>

-           $host.id

-           <input type="hidden" name="hostID" value="$host.id"/>

+           {{ host.id }}

+           <input type="hidden" name="hostID" value="{{ host.id }}"/>

          </td>

        </tr>

        <tr>

          <th>Arches</th>

-         <td><input type="text" name="arches" value="$host.arches"/></td>

+         <td><input type="text" name="arches" value="{{ host.arches }}"/></td>

        </tr>

        <tr>

          <th>Capacity</th>

-         <td><input type="text" name="capacity" value="$host.capacity"/></td>

+         <td><input type="text" name="capacity" value="{{ host.capacity }}"/></td>

        </tr>

        <tr>

          <th>Description</th>

-         <td><textarea name="description" rows="6" cols="50">$host.description</textarea></td>

+         <td><textarea name="description" rows="6" cols="50">{{ host.description or '' }}</textarea></td>

        </tr>

        <tr>

          <th>Comment</th>

-         <td><textarea name="comment" rows="2" cols="50">$host.comment</textarea></td>

+         <td><textarea name="comment" rows="2" cols="50">{{ host.comment or '' }}</textarea></td>

        </tr>

        <tr>

          <th>Enabled?</th>

-         <td><input type="checkbox" name="enabled" value="yes" #if $host.enabled then 'checked="checked"' else ''#/>

+         <td><input type="checkbox" name="enabled" value="yes"{{ ' checked' if host.enabled else '' }}/>

        </tr>

        <tr>

          <th>Channels</th>

          <td>

            <select name="channels" multiple="multiple">

-             #for $channel in $allChannels

-             <option value="$channel.name" #if $channel in $hostChannels then 'selected' else ''#>$channel.name</option>

-             #end for

+             #for channel in allChannels

+             <option value="{{ channel.name }}" {{ 'selected' if channel in hostChannels else '' }}>{{ channel.name }}</option>

+             #endfor

            </select>

          </td>

        <tr>
@@ -54,4 +53,4 @@ 

      </table>

    </form>

  

- #include "includes/footer.chtml"

+ #include "footer.html.j2"

www/kojiweb/templates/hostinfo.html.j2 www/kojiweb/hostinfo.chtml
file renamed
+39 -39
@@ -1,91 +1,91 @@ 

- #from kojiweb import util

  

- #include "includes/header.chtml"

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

  

-   <h4>Information for host <a href="hostinfo?hostID=$host.id">$host.name</a></h4>

+   <h4>Information for host <a href="hostinfo?hostID={{ host.id }}">{{ host.name }}</a></h4>

  

    <table>

      <tr>

-       <th>Name</th><td>$host.name</td>

+       <th>Name</th><td>{{ host.name }}</td>

      </tr>

      <tr>

-       <th>ID</th><td>$host.id</td>

+       <th>ID</th><td>{{ host.id }}</td>

      </tr>

      <tr>

-       <th>Arches</th><td>$host.arches</td>

+       <th>Arches</th><td>{{ host.arches }}</td>

      </tr>

      <tr>

-       <th>Capacity</th><td>$host.capacity</td>

+       <th>Capacity</th><td>{{ host.capacity }}</td>

      </tr>

      <tr>

-       <th>Task Load</th><td><a href="tasks?hostID=$host.id">#echo '%.2f' % $host.task_load#</a></td>

+       <th>Task Load</th><td><a href="tasks?hostID={{ host.id }}">{{ '%.2f' % host.task_load }}</a></td>

      </tr>

      <tr>

-       <th>Description</th><td class="usertext">$host.description</td>

+       <th>Description</th><td class="usertext">{{ host.description or '' }}</td>

      </tr>

      <tr>

-       <th>Comment</th><td class="usertext">$host.comment</td>

+       <th>Comment</th><td class="usertext">{{ host.comment or '' }}</td>

      </tr>

      <tr>

-       #set $enabled = $host.enabled and 'yes' or 'no'

+       #set enabled = host.enabled and 'yes' or 'no'

        <th>Enabled?</th>

-       <td class="$enabled">

-         $util.imageTag($enabled)

-         #if 'admin' in $perms

-         #if $host.enabled

-         <span class="adminLink">(<a href="disablehost?hostID=$host.id$util.authToken($self)">disable</a>)</span>

+       <td class="{{ enabled }}">

+         {{ util.imageTag(enabled) }}

+         #if 'admin' in perms

+         #if host.enabled

+         <span class="adminLink">(<a href="disablehost?hostID={{ host.id }}{{ util.authToken() }}">disable</a>)</span>

          #else

-         <span class="adminLink">(<a href="enablehost?hostID=$host.id$util.authToken($self)">enable</a>)</span>

-         #end if

-         #end if

+         <span class="adminLink">(<a href="enablehost?hostID={{ host.id }}{{ util.authToken() }}">enable</a>)</span>

+         #endif

+         #endif

        </td>

      </tr>

      <tr>

-       #set $ready = $host.ready and 'yes' or 'no'

-       <th>Ready?</th><td class="$ready">$util.imageTag($ready)</td>

+       #set ready = host.ready and 'yes' or 'no'

+       <th>Ready?</th><td class="{{ ready }}">{{ util.imageTag(ready) }}</td>

      </tr>

      <tr>

-       <th>Last Update</th><td>$util.formatTime($lastUpdate)</td>

+       <th>Last Update</th><td>{{ util.formatTime(lastUpdate) }}</td>

      </tr>

      <tr>

        <th>Channels</th>

        <td>

-         #for $channel in $channels

-         <a href="channelinfo?channelID=$channel.id" class="$channel.enabled">$channel.name</a><br/>

-         #end for

-         #if not $channels

+         #for channel in channels

+         <a href="channelinfo?channelID={{ channel.id }}" class="{{ channel.enabled }}">{{ channel.name }}</a><br/>

+         #endfor

+         #if not channels

          No channels

-         #end if

+         #endif

        </td>

      </tr>

      <tr>

        <th>Active Buildroots</th>

-       #if $buildroots

+       #if buildroots

        <td class="container">

          <table class="nested data-list">

            <tr class="list-header">

              <th>Buildroot</th><th>Created</th><th>State</th>

            </tr>

-           #for $buildroot in $buildroots

-           <tr class="$util.rowToggle($self)">

-             <td><a href="buildrootinfo?buildrootID=$buildroot.id">$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a></td>

-             <td>$util.formatTime($buildroot.create_event_time)</td>

-             <td>$util.imageTag($util.brStateName($buildroot.state))</td>

+           #for buildroot in buildroots

+           <tr class="{{ rowToggle(loop) }}">

+             <td><a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ buildroot.tag_name }}-{{ buildroot.id }}-{{ buildroot.repo_id }}</a></td>

+             <td>{{ util.formatTime(buildroot.create_event_time) }}</td>

+             <td>{{ util.imageTag(util.brStateName(buildroot.state)) }}</td>

            </tr>

-           #end for

+           #endfor

          </table>

        </td>

        #else

        <td>

          No buildroots

        </td>

-       #end if

+       #endif

      </tr>

-     #if 'admin' in $perms

+     #if 'admin' in perms

      <tr>

-       <td colspan="2"><a href="hostedit?hostID=$host.id$util.authToken($self)">Edit host</a></td>

+       <td colspan="2"><a href="hostedit?hostID={{ host.id }}{{ util.authToken() }}">Edit host</a></td>

      </tr>

-     #end if

+     #endif

    </table>

  

- #include "includes/footer.chtml"

+ #include "footer.html.j2"

@@ -0,0 +1,169 @@ 

+ 

+ #macro headerState(state)

+   #if state == 'enabled'

+ Enabled hosts

+   #elif state == 'disabled'

+ Disabled hosts

+   #else

+ Hosts

+   #endif

+ #endmacro

+ 

+ #macro headerReady(ready)

+   #if ready == 'ready'

+ which are ready

+   #elif ready == 'notready'

+ which are not ready

+   #endif

+ #endmacro

+ 

+ #macro headerArch(arch)

+   #if arch == 'all'

+ on all arches

+   #else

+ on {{ arch }} arch

+   #endif

+ #endmacro

+ 

+ #macro headerChannel(channel)

+   #if channel == 'all'

+ in all channels

+   #else

+ in {{ channel }} channel

+   #endif

+ #endmacro

+ 

+ #set _PASSTHROUGH = ['state', 'order', 'ready', 'channel', 'arch']

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+   <h4>{{ headerState(state) }} {{ headerReady(ready) }} {{ headerArch(arch) }} {{ headerChannel(channel) }}</h4>

+   <table class="data-list">

+     <tr>

+       <td colspan="9">

+         <table class="nested">

+           <tr><td>

+               <strong>State</strong>:

+           </td><td>

+               <select name="state" class="filterlist" onchange="javascript: window.location = 'hosts?state=' + this.value + '{{ util.passthrough_except('state') }}';">

+                 <option value="enabled" {{ 'selected' if state == 'enabled' else '' }}>enabled</option>

+                 <option value="disabled" {{ 'selected' if state == 'disabled' else '' }}>disabled</option>

+                 <option value="all" {{ 'selected' if state == 'all' else '' }}>all</option>

+               </select>

+           </td>

+           <td>

+               <strong>Channels</strong>:

+           </td><td>

+               <select name="channel" class="filterlist" onchange="javascript: window.location = 'hosts?channel=' + this.value + '{{ util.passthrough_except('channel') }}';">

+                 <option value="all" {{ 'selected' if not channel else '' }}>all</option>

+                 #for chan in channels

+                 <option value="{{ chan.name }}" {{ 'selected' if chan.name == channel else '' }}>{{ chan.name }}</option>

+                 #endfor

+               </select>

+           </td>

+           </tr>

+           <tr><td>

+               <strong>Ready</strong>:

+           </td><td>

+               <select name="ready" class="filterlist" onchange="javascript: window.location = 'hosts?ready=' + this.value + '{{ util.passthrough_except('ready') }}';">

+                 <option value="yes" {{ 'selected' if ready == 'yes' else '' }}>yes</option>

+                 <option value="no" {{ 'selected' if ready == 'no' else '' }}>no</option>

+                 <option value="all" {{ 'selected' if ready== 'all' else '' }}>all</option>

+               </select>

+           </td><td>

+               <strong>Arches</strong>:

+           </td><td>

+               <select name="arch" class="filterlist" onchange="javascript: window.location = 'hosts?arch=' + this.value + '{{ util.passthrough_except('arch') }}';">

+                 <option value="all" {{ 'selected' if not arch else '' }}>all</option>

+                 #for arch_item in arches

+                 <option value="{{ arch_item }}" {{ 'selected' if arch_item == arch else '' }}>{{ arch_item }}</option>

+                 #endfor

+               </select>

+           </td></tr>

+         </table>

+       </td>

+     </tr>

+     <tr>

+       <td class="paginate" colspan="9">

+         #if (hostPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'hosts?start=' + this.value * {{ hostRange }} + '{{ util.passthrough_except() }}';">

+             #for pageNum in hostPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == hostCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if hostStart > 0

+         <a href="hosts?start={{ hostStart - hostRange  }}{{ util.passthrough_except() }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalHosts != 0

+         <strong>Hosts {{ hostStart + 1  }} through {{ hostStart + hostCount  }} of {{ totalHosts }}</strong>

+         #endif

+         #if hostStart + hostCount < totalHosts

+         <a href="hosts?start={{ hostStart + hostRange }}{{ util.passthrough_except() }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th><a href="hosts?order={{ util.toggleOrder('id') }}{{ util.passthrough_except('order') }}">ID</a> {{ util.sortImage('id') }}</th>

+       <th><a href="hosts?order={{ util.toggleOrder('name') }}{{ util.passthrough_except('order') }}">Name</a> {{ util.sortImage('name') }}</th>

+       <th><a href="hosts?order={{ util.toggleOrder('arches') }}{{ util.passthrough_except('order') }}">Arches</a> {{ util.sortImage('arches') }}</th>

+       <th><a href="hosts?order={{ util.toggleOrder('channels') }}{{ util.passthrough_except('order') }}">Channels</a> {{ util.sortImage('channels') }}</th>

+       <th><a href="hosts?order={{ util.toggleOrder('enabled') }}{{ util.passthrough_except('order') }}">Enabled?</a> {{ util.sortImage('enabled') }}</th>

+       <th><a href="hosts?order={{ util.toggleOrder('ready') }}{{ util.passthrough_except('order') }}">Ready?</a> {{ util.sortImage('ready') }}</th>

+       <th><a href="hosts?order={{ util.toggleOrder('task_load') }}{{ util.passthrough_except('order') }}">Load</a> {{ util.sortImage('task_load') }}</th>

+       <th><a href="hosts?order={{ util.toggleOrder('capacity') }}{{ util.passthrough_except('order') }}">Cap.</a> {{ util.sortImage('capacity') }}</th>

+       <th><a href="hosts?order={{ util.toggleOrder('last_update') }}{{ util.passthrough_except('order') }}">Last Update</a> {{ util.sortImage('last_update') }}</th>

+     </tr>

+     #if (hosts |length) > 0

+       #for host in hosts

+         <tr class="{{ rowToggle(loop) }}">

+           <td>{{ host.id }}</td>

+           <td><a href="hostinfo?hostID={{ host.id }}">{{ host.name }}</a></td>

+           <td>{{ host.arches }}</td>

+           <td>

+               #for channame, chan_id, chan_enabled in zip(host.channels, host.channels_id, host.channels_enabled)

+                 <a href="channelinfo?channelID={{ chan_id }}" class="{{ chan_enabled }}">{{ channame }}</a>

+               #endfor

+           </td>

+           <td class="{{ 'true' if host.enabled else 'false' }}">{{ util.imageTag('yes') if host.enabled else util.imageTag('no') }}</td>

+           <td class="{{ 'true' if host.ready else 'false' }}">{{ util.imageTag('yes') if host.ready else util.imageTag('no') }}</td>

+           <td>{{ '%.2f' % host.task_load }}</td>

+           <td>{{ host.capacity }}</td>

+           <td>{{ util.formatTime(host.last_update) }}</td>

+         </tr>

+       #endfor

+     #else

+       <tr class="row-odd">

+         <td colspan="9">No hosts</td>

+       </tr>

+     #endif

+     <tr>

+       <td class="paginate" colspan="9">

+         #if (hostPages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'hosts?start=' + this.value * {{ hostRange }} + '{{ util.passthrough_except() }}';">

+             #for pageNum in hostPages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == hostCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if hostStart > 0

+         <a href="hosts?start={{ hostStart - hostRange  }}{{ util.passthrough_except() }}">&lt;&lt;&lt;</a>

+         #endif

+         #if totalHosts != 0

+         <strong>Hosts {{ hostStart + 1  }} through {{ hostStart + hostCount  }} of {{ totalHosts }}</strong>

+         #endif

+         #if hostStart + hostCount < totalHosts

+         <a href="hosts?start={{ hostStart + hostRange }}{{ util.passthrough_except() }}">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+   </table>

+ 

+ #include "footer.html.j2"

@@ -0,0 +1,160 @@ 

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+   <div class="pageHeader">{{ welcomeMessage }}</div>

+ 

+   <div class="dataHeader noPaginate" id="buildlist">{{ 'Your ' if user else '' }}Recent Builds</div>

+   <table class="data-list">

+     <tr class="list-header">

+       <th>ID {{ util.sortImage('id') }}</th>

+       <th>NVR</th>

+       #if not user

+       <th>Built by</th>

+       #endif

+       <th>Finished</th>

+       <th>State</th>

+     </tr>

+     #for build in builds

+     <tr class="{{ rowToggle(loop) }}">

+       #set stateName = util.stateName(build.state)

+       <td>{{ build.build_id }}</td>

+       <td><a href="buildinfo?buildID={{ build.build_id }}">{{ build.nvr }}</a></td>

+       #if not user

+       <td class="user-{{ build.owner_name }}"><a href="userinfo?userID={{ build.owner_id }}">{{ build.owner_name }}</a></td>

+       #endif

+       <td>{{ util.formatTime(build.completion_ts) }}</td>

+       <td class="{{ stateName }}">{{ util.stateImage(build.state) }}</td>

+     </tr>

+     #endfor

+     #if not builds

+     <tr class="row-odd">

+       <td colspan="3">No builds</td>

+     </tr>

+     #endif

+   </table>

+ 

+   <br/>

+ 

+   <div class="dataHeader noPaginate" id="tasklist">{{ 'Your ' if user else '' }}Recent Tasks</div>

+   <table class="data-list">

+     <tr class="list-header">

+       <th>ID {{ util.sortImage('id') }}</th>

+       <th>Type</th>

+       #if not user

+       <th>Owner</th>

+       #endif

+       <th>Arch</th>

+       <th>Finished</th>

+       <th>State</th>

+     </tr>

+     #for task in tasks

+     #set scratch = util.taskScratchClass(task)

+     <tr class="{{ rowToggle(loop) }} {{ scratch }}">

+       #set state = util.taskState(task.state)

+       <td>{{ task.id }}</td>

+       <td><a href="taskinfo?taskID={{ task.id }}" class="task{{ state }}" title="{{ state }}">{{ koji.taskLabel(task) }}</a></td>

+       #if not user

+       <td class="user-{{ task.owner_name }}">

+         #if task.owner_type == koji.USERTYPES['HOST']

+         <a href="hostinfo?userID={{ task.owner }}">{{ task.owner_name }}</a>

+         #else

+         <a href="userinfo?userID={{ task.owner }}">{{ task.owner_name }}</a>

+         #endif

+       </td>

+       #endif

+       <td>{{ task.arch }}</td>

+       <td>{{ util.formatTime(task.completion_ts) }}</td>

+       <td class="task{{ state }}">{{ util.imageTag(state) }}</td>

+     </tr>

+     #endfor

+     #if not tasks

+       <tr class="row-odd">

+         <td colspan="5">No tasks</td>

+       </tr>

+     #endif

+   </table>

+ 

+   #if user

+   <br/>

+ 

+   <div class="dataHeader" id="packagelist">Your Packages</div>

+   <table class="data-list">

+     <tr>

+       <td class="paginate" colspan="3">

+         #if (packagePages |length) > 1

+         <form class="pageJump" action="">

+           Page:

+           <select onchange="javascript: window.location = 'index?packageStart=' + this.value * {{ packageRange }} + '{{ util.passthrough('packageOrder', 'buildOrder', 'buildStart', 'taskOrder', 'taskStart') }}#packagelist';">

+             #for pageNum in packagePages

+             <option value="{{ pageNum }}"{{ ' selected' if pageNum == packageCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+             #endfor

+           </select>

+         </form>

+         #endif

+         #if packageStart > 0

+         <a href="index?packageStart={{ packageStart - packageRange  }}{{ util.passthrough('packageOrder', 'buildOrder', 'buildStart', 'taskOrder', 'taskStart') }}#packagelist">&lt;&lt;&lt;</a>

+         #endif

+         #if totalPackages != 0

+         <strong>Package {{ packageStart + 1  }} through {{ packageStart + packageCount  }} of {{ totalPackages }}</strong>

+         #endif

+         #if packageStart + packageCount < totalPackages

+         <a href="index?packageStart={{ packageStart + packageRange }}{{ util.passthrough('packageOrder', 'buildOrder', 'buildStart', 'taskOrder', 'taskStart') }}#packagelist">&gt;&gt;&gt;</a>

+         #endif

+       </td>

+     </tr>

+     <tr class="list-header">

+       <th><a href="index?packageOrder={{ util.toggleOrder('package_name', 'packageOrder') }}{{ util.passthrough('buildOrder', 'buildStart', 'taskOrder', 'taskStart') }}#packagelist">Name</a> {{ util.sortImage('package_name', 'packageOrder') }}</th>

+       <th><a href="index?packageOrder={{ util.toggleOrder('tag_name', 'packageOrder') }}{{ util.passthrough('buildOrder', 'buildStart', 'taskOrder', 'taskStart') }}#packagelist">Tag</a> {{ util.sortImage('tag_name', 'packageOrder') }}</th>

+       <th><a href="index?packageOrder={{ util.toggleOrder('blocked', 'packageOrder') }}{{ util.passthrough('buildOrder', 'buildStart', 'taskOrder', 'taskStart') }}#packagelist">Included?</a> {{ util.sortImage('blocked', 'packageOrder') }}</th>

+     </tr>

+     #for package in packages

+     <tr class="{{ rowToggle(loop) }}">

+       <td><a href="packageinfo?packageID={{ package.package_id }}">{{ package.package_name }}</a></td>

+       <td><a href="taginfo?tagID={{ package.tag_id }}">{{ package.tag_name }}</a></td>

+       #set included = package.blocked and 'no' or 'yes'

+       <td>{{ util.imageTag(included) }}</td>

+     </tr>

+     #endfor

+     #if totalPackages == 0

+     <tr class="row-odd">

+       <td colspan="3">No packages</td>

+     </tr>

+     #endif

+   </table>

+   

+   <br/>

+   

+   <div class="dataHeader" id="notificationlist">Your Notifications</div>

+   <table class="data-list">

+     <tr>

+       <td colspan="5"></td>

+     </tr>

+     <tr class="list-header">

+       <th>Package</th>

+       <th>Tag</th>

+       <th>Type</th>

+       <th></th>

+       <th></th>

+     </tr>

+     #for notif in notifs

+     <tr class="{{ rowToggle(loop) }}">

+       <td>{{ notif.package.name if notif.package else 'all' }}</td>

+       <td>{{ notif.tag.name if notif.tag else 'all' }}</td>

+       <td>{{ 'success only' if notif.success_only else 'all' }}</td>

+       <td><a href="notificationedit?notificationID={{ notif.id }}{{ util.authToken() }}">edit</a></td>

+       <td><a href="notificationdelete?notificationID={{ notif.id }}{{ util.authToken() }}">delete</a></td>

+     </tr>

+     #endfor

+     #if (notifs |length) == 0

+     <tr class="row-odd">

+       <td colspan="5">No notifications</td>

+     </tr>

+     #endif

+   </table>

+ 

+   <br/>

+   <a href="notificationcreate{{ util.authToken(first=True) }}">Add a Notification</a>

+   #endif

+     

+ #include "footer.html.j2"

@@ -0,0 +1,11 @@ 

+ {%- set TOGGLE = cycler('row-odd', 'row-even') %}

+ 

+ {%- macro rowToggle(loop=None) %}

+   {%- if loop is not none %}

+     {{- loop.cycle('row-odd', 'row-even') }}

+   {%- else %}

+     {# use the global one #}

+     {{- TOGGLE.next() }}

+   {%- endif %}

+ {%- endmacro %}

+ 

www/kojiweb/templates/notificationedit.html.j2 www/kojiweb/notificationedit.chtml
file renamed
+20 -21
@@ -1,27 +1,26 @@ 

- #from kojiweb import util

  

- #include "includes/header.chtml"

+ #include "header.html.j2"

  

-   #if $notif

+   #if notif

    <h4>Edit notification</h4>

    #else

    <h4>Create notification</h4>

-   #end if

+   #endif

  

-   <form action="#if $notif then 'notificationedit' else 'notificationcreate'#">

-     $util.authToken($self, form=True)

-     #if $notif

-     <input type="hidden" name="notificationID" value="$notif.id"/>

-     #end if

+   <form action="{{ 'notificationedit' if notif else 'notificationcreate' }}">

+     {{ util.authToken(form=True) }}

+     #if notif

+     <input type="hidden" name="notificationID" value="{{ notif.id }}"/>

+     #endif

      <table>

        <tr>

          <th>Package</th>

          <td>

            <select name="package">

-             <option value="all"#if $notif and not $notif.package_id then ' selected' else ''#>all</option>

-             #for $package in $packages

-             <option value="$package.package_id"#if $notif and $notif.package_id == $package.package_id then ' selected' else ''#>$package.package_name</option>

-             #end for

+             <option value="all"{{ ' selected' if notif and not notif.package_id else '' }}>all</option>

+             #for package in packages

+             <option value="{{ package.package_id }}"{{ ' selected' if notif and notif.package_id == package.package_id else '' }}>{{ package.package_name }}</option>

+             #endfor

            </select>

          </td>

        </tr>
@@ -29,28 +28,28 @@ 

          <th>Tag</th>

          <td>

            <select name="tag">

-             <option value="all"#if $notif and not $notif.tag_id then ' selected' else ''#>all</option>

-             #for $tag in $tags

-             <option value="$tag.id"#if $notif and $notif.tag_id == $tag.id then ' selected' else ''#>$tag.name</option>

-             #end for

+             <option value="all"{{ ' selected' if notif and not notif.tag_id else '' }}>all</option>

+             #for tag in tags

+             <option value="{{ tag.id }}"{{ ' selected' if notif and notif.tag_id == tag.id else '' }}>{{ tag.name }}</option>

+             #endfor

            </select>

          </td>

        </tr>

        <tr>

          <th>Success Only?</th>

-         <td><input type="checkbox" name="success_only" value="yes"#if $notif and $notif.success_only then ' checked="checked"' else ''#/></td>

+         <td><input type="checkbox" name="success_only" value="yes"{{ ' checked' if notif and notif.success_only else '' }}/></td>

        </tr>

        <tr>

          <td>

-           #if $notif

+           #if notif

            <button type="submit" name="save" value="Save">Save</button>

            #else

            <button type="submit" name="add" value="Add">Add</button>

-           #end if

+           #endif

          </td>

          <td><button type="submit" name="cancel" value="Cancel">Cancel</button></td>

        </tr>

      </table>

    </form>

  

- #include "includes/footer.chtml"

+ #include "footer.html.j2"

@@ -0,0 +1,127 @@ 

+ 

+ #include "header.html.j2"

+ # from "macros.html.j2" import rowToggle

+ 

+   <h4>Information for package <a href="packageinfo?packageID={{ package.id }}">{{ package.name }}</a></h4>

+ 

+   <table>

+     <tr>

+       <th>Name</th><td>{{ package.name }}</td>

+     </tr>

+     <tr>

+       <th>ID</th><td>{{ package.id }}</td>

+     </tr>

+     

+     <tr>

+       <th id="buildlist">Builds</th>

+       <td class="container">

+         #if (builds |length) > 0

+         <table class="nested data-list">

+           <tr>

+             <td class="paginate" colspan="4">

+               #if (buildPages |length) > 1

+               <form class="pageJump" action="">

+                 Page:

+                 <select onchange="javascript: window.location = 'packageinfo?buildStart=' + this.value * {{ buildRange }} + '{{ util.passthrough('packageID', 'buildOrder', 'tagOrder', 'tagStart') }}#buildlist';">

+                   #for pageNum in buildPages

+                   <option value="{{ pageNum }}"{{ ' selected' if pageNum == buildCurrentPage else '' }}>{{ pageNum + 1 }}</option>

+                   #endfor

+                 </select>

+               </form>

+               #endif

+               #if buildStart > 0

+               <a href="packageinfo?buildStart={{ buildStart - buildRange }}{{ util.passthrough('packageID', 'buildOrder', 'tagOrder', 'tagStart') }}#buildlist">&lt;&lt;&lt;</a>

+               #endif

+               <strong>{{ buildStart + 1  }} through {{ buildStart + buildCount  }} of {{ totalBuilds }}</strong>

+               #if buildStart + buildCount < totalBuilds

+               <a href="packageinfo?buildStart={{ buildStart + buildRange }}{{ util.passthrough('packageID', 'buildOrder', 'tagOrder', 'tagStart') }}#buildlist">&gt;&gt;&gt;</a>