euscanwww: big ugly commit, sorry

Signed-off-by: Corentin Chary <corentincj@iksaif.net>
This commit is contained in:
Corentin Chary 2011-04-15 19:28:37 +02:00
parent 2dee08dfb7
commit c8d0e5a789
28 changed files with 428 additions and 99 deletions

15
euscan
View File

@ -45,10 +45,13 @@ from gentoolkit.eclean.search import (port_settings)
QUERY_OPTS = {"include_masked": True} QUERY_OPTS = {"include_masked": True}
BLACKLIST_PACKAGES = ['sys-kernel/usermode-sources', 'sys-kernel/xbox-sources',
'sys-kernel/cell-sources', 'sys-libs/libstdc++-v3']
SCANDIR_BLACKLIST_URLS = ['mirror://rubygems/(.*)', 'mirror://gentoo/(.*)'] SCANDIR_BLACKLIST_URLS = ['mirror://rubygems/(.*)', 'mirror://gentoo/(.*)']
BRUTEFORCE_BLACKLIST_PACKAGES = ['dev-util/patchelf', 'net-zope/plonepopoll'] BRUTEFORCE_BLACKLIST_PACKAGES = ['dev-util/patchelf', 'net-zope/plonepopoll']
BRUTEFORCE_BLACKLIST_URLS = ['http://www.dockapps.org/download.php/id/(.*)'] BRUTEFORCE_BLACKLIST_URLS = ['http://(.*)dockapps.org/download.php/id/(.*)']
# ========= # =========
# Functions # Functions
@ -282,11 +285,16 @@ def scan_directory_recursive(url, steps, vmin, vmax, output):
for version, path in results: for version, path in results:
ver = parse_version(version) ver = parse_version(version)
if vmin and ver <= vmin: if vmin and ver <= vmin:
continue continue
if vmax and ver >= vmax: if vmax and ver >= vmax:
continue continue
# Try to skip nightly builds when not wanted (www-apps/moodle)
if len(vmin) != len(ver) and len(ver) == 2 and len(ver[0]) == len('yyyymmdd'):
continue
if not url.endswith('/') and not path.startswith('/'): if not url.endswith('/') and not path.startswith('/'):
path = url + '/' + path path = url + '/' + path
else: else:
@ -576,6 +584,7 @@ def scanUpstream(options, package, output):
matches = sorted(matches) matches = sorted(matches)
pkg = matches.pop() pkg = matches.pop()
if pkg.version == '9999': if pkg.version == '9999':
if len(matches) == 0: if len(matches) == 0:
sys.stderr.write(pp.warn("Package '%s' only have a dev version (9999)" % pp.pkgquery(package))) sys.stderr.write(pp.warn("Package '%s' only have a dev version (9999)" % pp.pkgquery(package)))
@ -583,6 +592,10 @@ def scanUpstream(options, package, output):
else: else:
pkg = matches.pop() pkg = matches.pop()
if pkg.cp in BLACKLIST_PACKAGES:
sys.stderr.write(pp.warn("Package '%s' is blacklisted" % pp.pkgquery(package)))
sys.exit(errno.ENOENT)
pp.uprint(" * %s [%s]" % (pp.cpv(pkg.cpv), pp.section(pkg.repo_name()))) pp.uprint(" * %s [%s]" % (pp.cpv(pkg.cpv), pp.section(pkg.repo_name())))
pp.uprint() pp.uprint()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,7 @@
from django import forms
class WorldFileForm(forms.Form):
world_file = forms.FileField()
class WorldForm(forms.Form):
world = forms.CharField(widget=forms.Textarea)

View File

@ -1,3 +1,5 @@
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from euscanwww.euscan.models import Package from euscanwww.euscan.models import Package
@ -5,6 +7,49 @@ class Command(BaseCommand):
_overlays = {} _overlays = {}
help = 'List packages' help = 'List packages'
option_list = BaseCommand.option_list + (
make_option('--after',
action='store',
dest='after',
default=False,
help='After package'),
make_option('--before',
action='store',
dest='before',
default=False,
help='Before package'),
make_option('--limit',
action='store',
dest='limit',
default=False,
help='limit'),
)
def handle(self, *args, **options): def handle(self, *args, **options):
for pkg in Package.objects.all(): after = None
before = None
if options['after']:
category, name = options['after'].split('/')
after = Package.objects.get(category=category, name=name)
if options['before']:
category, name = options['before'].split('/')
before = Package.objects.get(category=category, name=name)
packages = Package.objects
if after or before:
if after:
packages = packages.filter(id__gte=after.id)
if before:
packages = packages.filter(id__lte=before.id)
else:
packages = packages.all()
if options['limit']:
packages = packages[:int(options['limit'])]
for pkg in packages:
self.stdout.write('%s/%s\n' % (pkg.category, pkg.name)) self.stdout.write('%s/%s\n' % (pkg.category, pkg.name))
self.stdout.close()

View File

@ -74,6 +74,9 @@ class Command(BaseCommand):
sys.stderr.write(self.style.ERROR("Gentoolkit fatal error: '%s'\n" % str(err))) sys.stderr.write(self.style.ERROR("Gentoolkit fatal error: '%s'\n" % str(err)))
if pkg.metadata: if pkg.metadata:
obj.herds.clear()
obj.maintainers.clear()
for herd in pkg.metadata.herds(True): for herd in pkg.metadata.herds(True):
herd = self.store_herd(options, herd[0], herd[1]) herd = self.store_herd(options, herd[0], herd[1])
obj.herds.add(herd) obj.herds.add(herd)
@ -88,6 +91,10 @@ class Command(BaseCommand):
obj.save() obj.save()
def store_herd(self, options, name, email): def store_herd(self, options, name, email):
if not name:
name = '{nil}'
name = name.strip("\r").strip("\n").strip("\t").strip()
herd, created = Herd.objects.get_or_create(herd=name) herd, created = Herd.objects.get_or_create(herd=name)
if created or herd.email != email: if created or herd.email != email:
@ -102,13 +109,16 @@ class Command(BaseCommand):
def store_maintainer(self, options, name, email): def store_maintainer(self, options, name, email):
if not name: if not name:
name = email name = email
if not name:
name = '{nil}'
maintainer, created = Maintainer.objects.get_or_create(name=name, email=email) maintainer, created = Maintainer.objects.get_or_create(email=email)
if created: if created:
if not options['quiet']: if not options['quiet']:
sys.stdout.write('[m] %s <%s>\n' % (name.encode('utf-8'), email)) sys.stdout.write('[m] %s <%s>\n' % (name.encode('utf-8'), email))
maintainer.name = name
maintainer.save() maintainer.save()
return maintainer return maintainer

View File

@ -120,6 +120,7 @@ class Command(BaseCommand):
# Delete previous versions to handle incremental scan correctly # Delete previous versions to handle incremental scan correctly
Version.objects.filter(package=obj, packaged=True).delete() Version.objects.filter(package=obj, packaged=True).delete()
obj.n_packaged = 0
obj.n_versions = Version.objects.filter(package=obj).count() obj.n_versions = Version.objects.filter(package=obj).count()
obj.save() obj.save()

View File

@ -0,0 +1,99 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Removing unique constraint on 'Maintainer', fields ['name', 'email']
db.delete_unique('euscan_maintainer', ['name', 'email'])
# Adding unique constraint on 'Maintainer', fields ['email']
db.create_unique('euscan_maintainer', ['email'])
def backwards(self, orm):
# Removing unique constraint on 'Maintainer', fields ['email']
db.delete_unique('euscan_maintainer', ['email'])
# Adding unique constraint on 'Maintainer', fields ['name', 'email']
db.create_unique('euscan_maintainer', ['name', 'email'])
models = {
'euscan.categorylog': {
'Meta': {'object_name': 'CategoryLog'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'euscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'euscan.herdlog': {
'Meta': {'object_name': 'HerdLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Herd']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.maintainer': {
'Meta': {'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.maintainerlog': {
'Meta': {'object_name': 'MaintainerLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Maintainer']"}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
}
}
complete_apps = ['euscan']

View File

@ -11,14 +11,11 @@ class Herd(models.Model):
class Maintainer(models.Model): class Maintainer(models.Model):
name = models.CharField(max_length=128) name = models.CharField(max_length=128)
email = models.CharField(max_length=128) email = models.CharField(max_length=128, unique=True)
def __unicode__(self): def __unicode__(self):
return '%s <%s>' % (self.name, self.email) return '%s <%s>' % (self.name, self.email)
class Meta:
unique_together = ['name', 'email']
class Package(models.Model): class Package(models.Model):
category = models.CharField(max_length=128) category = models.CharField(max_length=128)
name = models.CharField(max_length=128) name = models.CharField(max_length=128)

View File

@ -0,0 +1,7 @@
from django import template
register = template.Library()
@register.inclusion_tag('euscan/_packages.html')
def packages(packages):
return { 'packages' : packages }

View File

@ -3,11 +3,13 @@ from django.conf.urls.defaults import *
urlpatterns = patterns('euscan.views', urlpatterns = patterns('euscan.views',
(r'^$', 'index'), (r'^$', 'index'),
(r'^logs/$', 'logs'), (r'^logs/$', 'logs'),
(r'^world/$', 'world'),
(r'^world/scan/$', 'world_scan'),
(r'^categories/$', 'categories'), (r'^categories/$', 'categories'),
(r'^category/(?P<category>[\w+][\w+.-]*)/packages/$', 'category'), (r'^categories/(?P<category>[\w+][\w+.-]*)/view/$', 'category'),
(r'^herds/$', 'herds'), (r'^herds/$', 'herds'),
(r'^herd/(?P<herd>[\w+][\w+.-]*)/packages/$', 'herd'), (r'^herds/(?P<herd>[\{\}\w+.-]*)/view/$', 'herd'),
(r'^maintainers/$', 'maintainers'), (r'^maintainers/$', 'maintainers'),
(r'^maintainer/(?P<maintainer_id>\d+)/packages/$', 'maintainer'), (r'^maintainers/(?P<maintainer_id>\d+)/view/$', 'maintainer'),
(r'^package/(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/$', 'package'), (r'^package/(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/$', 'package'),
) )

Binary file not shown.

View File

@ -4,13 +4,14 @@ from django.shortcuts import get_object_or_404
from django.db.models import Sum, Max from django.db.models import Sum, Max
from euscan.models import Version, Package, Herd, Maintainer, EuscanResult from euscan.models import Version, Package, Herd, Maintainer, EuscanResult
from euscan.forms import WorldForm, WorldFileForm
@render_to('euscan/index.html') @render_to('euscan/index.html')
def index(request): def index(request):
ctx = {} ctx = {}
ctx['n_packaged'] = Package.objects.aggregate(Sum('n_packaged'))['n_packaged__sum'] ctx['n_packaged'] = Package.objects.aggregate(Sum('n_packaged'))['n_packaged__sum']
ctx['n_versions'] = Package.objects.aggregate(Sum('n_versions'))['n_versions__sum'] ctx['n_versions'] = Package.objects.aggregate(Sum('n_versions'))['n_versions__sum']
if ctx['n_versions'] is not None and ctx['n_pacaged'] is not None: if ctx['n_versions'] is not None and ctx['n_packaged'] is not None:
ctx['n_upstream'] = ctx['n_versions'] - ctx['n_packaged'] ctx['n_upstream'] = ctx['n_versions'] - ctx['n_packaged']
ctx['n_packages'] = Package.objects.count() ctx['n_packages'] = Package.objects.count()
ctx['n_herds'] = Herd.objects.count() ctx['n_herds'] = Herd.objects.count()
@ -36,19 +37,26 @@ def category(request, category):
@render_to('euscan/herds.html') @render_to('euscan/herds.html')
def herds(request): def herds(request):
return {} # FIXME: optimize the query, it uses 'LEFT OUTER JOIN' instead of 'INNER JOIN'
herds = Package.objects.filter(herds__isnull=False).values('herds__herd').annotate(n_packaged=Sum('n_packaged'), n_versions=Sum('n_versions'))
return { 'herds' : herds }
@render_to('euscan/herd.html') @render_to('euscan/herd.html')
def herd(request, herd): def herd(request, herd):
return {} herd = get_object_or_404(Herd, herd=herd)
packages = Package.objects.filter(herds__id=herd.id)
return { 'herd' : herd, 'packages' : packages }
@render_to('euscan/maintainers.html') @render_to('euscan/maintainers.html')
def maintainers(request): def maintainers(request):
return {} maintainers = Package.objects.filter(maintainers__isnull=False).values('maintainers__id', 'maintainers__name').annotate(n_packaged=Sum('n_packaged'), n_versions=Sum('n_versions'))
return { 'maintainers' : maintainers }
@render_to('euscan/maintainer.html') @render_to('euscan/maintainer.html')
def maintainer(request, maintainer_id): def maintainer(request, maintainer_id):
return {} maintainer = get_object_or_404(Maintainer, id=maintainer_id)
packages = Package.objects.filter(maintainers__id=maintainer.id)
return { 'maintainer' : maintainer, 'packages' : packages }
@render_to('euscan/package.html') @render_to('euscan/package.html')
def package(request, category, package): def package(request, category, package):
@ -56,3 +64,33 @@ def package(request, category, package):
packaged = Version.objects.filter(package=package, packaged=True) packaged = Version.objects.filter(package=package, packaged=True)
upstream = Version.objects.filter(package=package, packaged=False) upstream = Version.objects.filter(package=package, packaged=False)
return { 'package' : package, 'packaged' : packaged, 'upstream' : upstream } return { 'package' : package, 'packaged' : packaged, 'upstream' : upstream }
@render_to('euscan/world.html')
def world(request):
form = WorldForm()
file_form = WorldFileForm()
return { 'form' : form , 'file_form' : file_form }
@render_to('euscan/world_scan.html')
def world_scan(request):
packages = []
# FIXME
if 'world_file' in request.FILES:
data = request.FILES['world_file'].read()
elif 'world' in request.POST:
data = request.POST['world']
else:
data = ""
for pkg in data.split('\n'):
try:
cat, pkg = pkg.split('/')
packages.append(Package.objects.get(category=cat, name=pkg))
except:
pass
return { 'packages' : packages }

Binary file not shown.

View File

@ -13,12 +13,17 @@ MANAGERS = ADMINS
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. # 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': os.path.join(os.path.dirname( __file__ ), 'euscan.db'), # Or path to database file if using sqlite3. # 'NAME': os.path.join(os.path.dirname( __file__ ), 'euscan.db'), # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3. 'ENGINE': 'django.db.backends.mysql',
'PASSWORD': '', # Not used with sqlite3. 'NAME': 'euscan',
'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 'USER': 'euscan', # Not used with sqlite3.
'PASSWORD': 'w7RGZVQx6edAMaDE', # Not used with sqlite3.
'HOST': 'localhost', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3. 'PORT': '', # Set to empty string for default. Not used with sqlite3.
'OPTIONS': {
'init_command': 'SET storage_engine=INNODB',
}
} }
} }
@ -79,6 +84,8 @@ MIDDLEWARE_CLASSES = (
ROOT_URLCONF = 'euscanwww.urls' ROOT_URLCONF = 'euscanwww.urls'
FORCE_SCRIPT_NAME=""
TEMPLATE_DIRS = ( TEMPLATE_DIRS = (
os.path.join(os.path.dirname( __file__ ), 'templates'), os.path.join(os.path.dirname( __file__ ), 'templates'),
) )

View File

@ -21,9 +21,15 @@
<div id="menu"> <div id="menu">
<ul> <ul>
{% block menu %} {% block menu %}
<li><a href="/categories/">Categories</a></li> <li><a href="{% url euscan.views.index %}">Home</a></li>
<li><a href="/herds/">Herds</a></li> <li><a href="{% url euscan.views.categories %}">Categories</a></li>
<li><a href="/maintainers/">Maintainers</a></li> <li><a href="{% url euscan.views.herds %}">Herds</a></li>
<li><a href="{% url euscan.views.maintainers %}">Maintainers</a></li>
<li>---</li>
<li><a href="#">Login</a></li>
<li><a href="#">Register</a></li>
<li>---</li>
<li><a href="#">About</a></li>
{% endblock %} {% endblock %}
</ul> </ul>
</div> </div>

View File

@ -1,46 +0,0 @@
<?xml version="1.0" encoding="utf8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
<head>
<title>{% block title %}euscan{% endblock %}</title>
<meta http-equiv="Content-Type" content="text/html; charset="utf-8" />
{% block css %}
<link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}img/style.css" media="screen" title="Normal" />
{% endblock %}
{% block javascript %}
{% endblock %}
</head>
<body>
<div id="header">
{% block header %}<h1>euscan</h1>{% endblock %}
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
<div id="menus">
{% block menus %}
<div id="menu">
<ul>
{% block menu %}
<li><a href="categories/">Categories</a></li>
<li><a href="herds/">Herds</a></li>
<li><a href="maintainers/">Maintainers</a></li>
{% endblock %}
</ul>
</div>
{% endblock %}
</div>
<div id="footer">
Powered by:
<a href="http://kernel.org" titke="Linux Kernel">
<img src="{{MEDIA_URL}}img/linux.png" alt="Linux" />
</a>
<a href="http://gentoo.org" title="Gentoo">
<img src="{{MEDIA_URL}}img/gentoo.png" alt="Gentoo Linux" />
</a>
-
Copyright (C) 2011 <strong>Corentin Chary</strong>
</div>
</body>
</html>

View File

@ -0,0 +1,29 @@
{% load sub %}
{% load mul %}
<table id="table" class="display">
<thead>
<th>Package</th>
<th>Ebuilds</th>
<th>Unpackaged</th>
</thead>
<tbody>
{% for package in packages %}
{% if package.n_versions == package.n_packaged %}
<tr class="gradeA">
{% else %}{% if package.n_versions < package.n_packaged|mul:2 %}
<tr class="gradeC">
{% else %}
<tr class="gradeX">
{% endif %}{% endif %}
<td>
<a href="{% url euscan.views.package package.category package.name %}">
{{ package.category }}/{{ package.name }}
</a>
</td>
<td>{{ package.n_packaged }}</td>
<td>{{ package.n_versions|sub:package.n_packaged }}</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -1,38 +1,12 @@
{% extends "euscan/_datatable.html" %} {% extends "euscan/_datatable.html" %}
{% load sub %} {% load packages %}
{% load mul %}
{% block title %} {% block title %}
{{ block.super }} - {{ category }} {{ block.super }} - Category: {{ category }}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<h2>Category: {{ category }}</h2> <h2>Category: {{ category }}</h2>
<table id="table" class="display"> {% packages packages %}
<thead>
<th>Package</th>
<th>Ebuilds</th>
<th>Unpackaged</th>
</thead>
<tbody>
{% for package in packages %}
{% if package.n_versions == package.n_packaged %}
<tr class="gradeA">
{% else %}{% if package.n_versions < package.n_packaged|mul:2 %}
<tr class="gradeC">
{% else %}
<tr class="gradeX">
{% endif %}{% endif %}
<td>
<a href="{% url euscan.views.package package.category package.name %}">
{{ package.category }}/{{ package.name }}
</a>
</td>
<td>{{ package.n_packaged }}</td>
<td>{{ package.n_versions|sub:package.n_packaged }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,12 @@
{% extends "euscan/_datatable.html" %}
{% load packages %}
{% block title %}
{{ block.super }} - Herd: {{ herd.herd }}
{% endblock %}
{% block content %}
<h2>Herd: {{ herd.herd }}</h2>
{% packages packages %}
{% endblock %}

View File

@ -0,0 +1,38 @@
{% extends "euscan/_datatable.html" %}
{% load sub %}
{% load mul %}
{% block title %}
{{ block.super }} - herds
{% endblock %}
{% block content %}
<h2>Herds</h2>
<table id="table" class="display">
<thead>
<th>Herd</th>
<th>Ebuilds</th>
<th>Unpackaged</th>
</thead>
<tbody>
{% for herd in herds %}
{% if herd.n_versions == herd.n_packaged %}
<tr class="gradeA">
{% else %}{% if herd.n_versions < herd.n_packaged|mul:2 %}
<tr class="gradeC">
{% else %}
<tr class="gradeX">
{% endif %}{% endif %}
<td>
<a href="{% url euscan.views.herd herd.herds__herd %}">
{{ herd.herds__herd }}
</a>
</td>
<td>{{ herd.n_packaged }}</td>
<td>{{ herd.n_versions|sub:herd.n_packaged }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -0,0 +1,12 @@
{% extends "euscan/_datatable.html" %}
{% load packages %}
{% block title %}
{{ block.super }} - Maintainer: {{ maintainer.name }}
{% endblock %}
{% block content %}
<h2>Maintainer: {{ maintainer.name }} &lt{{ maintainer.email }}&gt</h2>
{% packages packages %}
{% endblock %}

View File

@ -0,0 +1,38 @@
{% extends "euscan/_datatable.html" %}
{% load sub %}
{% load mul %}
{% block title %}
{{ block.super }} - maintainers
{% endblock %}
{% block content %}
<h2>Maintainers</h2>
<table id="table" class="display">
<thead>
<th>Maintainer</th>
<th>Ebuilds</th>
<th>Unpackaged</th>
</thead>
<tbody>
{% for maintainer in maintainers %}
{% if maintainer.n_versions == maintainer.n_packaged %}
<tr class="gradeA">
{% else %}{% if maintainer.n_versions < maintainer.n_packaged|mul:2 %}
<tr class="gradeC">
{% else %}
<tr class="gradeX">
{% endif %}{% endif %}
<td>
<a href="{% url euscan.views.maintainer maintainer.maintainers__id %}">
{{ maintainer.maintainers__name }}
</a>
</td>
<td>{{ maintainer.n_packaged }}</td>
<td>{{ maintainer.n_versions|sub:maintainer.n_packaged }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -63,7 +63,7 @@
<ul> <ul>
{% for version in upstream %} {% for version in upstream %}
<li> <li>
{{ version.version }} - {{ version.url }} {{ version.version }} - {{ version.urls }}
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>

View File

@ -0,0 +1,28 @@
{% extends "_base.html" %}
{% block title %}
{{ block.super }} - World scan
{% endblock %}
{% block content %}
<h2>Scan your packages</h2>
<hr />
<p>Import your /var/lib/portage/world file</p>
<form action="{% url euscan.views.world_scan %}" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ file_form.as_p }}
<input type="submit" value="Submit" />
</form>
<hr />
<p>Or just list some packages</p>
<form action="{% url euscan.views.world_scan %}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock %}

View File

@ -0,0 +1,12 @@
{% extends "euscan/_datatable.html" %}
{% load packages %}
{% block title %}
{{ block.super }} - World Scan
{% endblock %}
{% block content %}
<h2>World scan:</h2>
{% packages packages %}
{% endblock %}