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

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 euscanwww.euscan.models import Package
@ -5,6 +7,49 @@ class Command(BaseCommand):
_overlays = {}
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):
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.close()

View File

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

View File

@ -120,6 +120,7 @@ class Command(BaseCommand):
# Delete previous versions to handle incremental scan correctly
Version.objects.filter(package=obj, packaged=True).delete()
obj.n_packaged = 0
obj.n_versions = Version.objects.filter(package=obj).count()
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):
name = models.CharField(max_length=128)
email = models.CharField(max_length=128)
email = models.CharField(max_length=128, unique=True)
def __unicode__(self):
return '%s <%s>' % (self.name, self.email)
class Meta:
unique_together = ['name', 'email']
class Package(models.Model):
category = 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',
(r'^$', 'index'),
(r'^logs/$', 'logs'),
(r'^world/$', 'world'),
(r'^world/scan/$', 'world_scan'),
(r'^categories/$', 'categories'),
(r'^category/(?P<category>[\w+][\w+.-]*)/packages/$', 'category'),
(r'^categories/(?P<category>[\w+][\w+.-]*)/view/$', 'category'),
(r'^herds/$', 'herds'),
(r'^herd/(?P<herd>[\w+][\w+.-]*)/packages/$', 'herd'),
(r'^herds/(?P<herd>[\{\}\w+.-]*)/view/$', 'herd'),
(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'),
)

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 euscan.models import Version, Package, Herd, Maintainer, EuscanResult
from euscan.forms import WorldForm, WorldFileForm
@render_to('euscan/index.html')
def index(request):
ctx = {}
ctx['n_packaged'] = Package.objects.aggregate(Sum('n_packaged'))['n_packaged__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_packages'] = Package.objects.count()
ctx['n_herds'] = Herd.objects.count()
@ -36,19 +37,26 @@ def category(request, category):
@render_to('euscan/herds.html')
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')
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')
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')
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')
def package(request, category, package):
@ -56,3 +64,33 @@ def package(request, category, package):
packaged = Version.objects.filter(package=package, packaged=True)
upstream = Version.objects.filter(package=package, packaged=False)
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 = {
'default': {
'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.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
# '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.
'ENGINE': 'django.db.backends.mysql',
'NAME': 'euscan',
'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.
'OPTIONS': {
'init_command': 'SET storage_engine=INNODB',
}
}
}
@ -79,6 +84,8 @@ MIDDLEWARE_CLASSES = (
ROOT_URLCONF = 'euscanwww.urls'
FORCE_SCRIPT_NAME=""
TEMPLATE_DIRS = (
os.path.join(os.path.dirname( __file__ ), 'templates'),
)

View File

@ -21,9 +21,15 @@
<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>
<li><a href="{% url euscan.views.index %}">Home</a></li>
<li><a href="{% url euscan.views.categories %}">Categories</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 %}
</ul>
</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" %}
{% load sub %}
{% load mul %}
{% load packages %}
{% block title %}
{{ block.super }} - {{ category }}
{{ block.super }} - Category: {{ category }}
{% endblock %}
{% block content %}
<h2>Category: {{ category }}</h2>
<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>
{% packages packages %}
{% 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>
{% for version in upstream %}
<li>
{{ version.version }} - {{ version.url }}
{{ version.version }} - {{ version.urls }}
</li>
{% endfor %}
</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 %}