summaryrefslogtreecommitdiff
path: root/releng
diff options
context:
space:
mode:
authorLuke Shumaker <LukeShu@sbcglobal.net>2014-05-25 19:34:21 -0400
committerLuke Shumaker <LukeShu@sbcglobal.net>2014-05-25 19:34:21 -0400
commit1a1fd4a3d6aa7f6b2338f7751f5f97a30a059a04 (patch)
treef608874663d24f19ecf175ec556f2a330d47a726 /releng
parent747a562ddca10e29dd003e8b3c59f8f384d1bc8d (diff)
parentcd7222047b41ac3efa389a22fdd22148d03c1d61 (diff)
Merge tag 'release_2014-03-22' into archweb-generic
Fix long filenames; local storage for filter prefs Conflicts: templates/public/download.html
Diffstat (limited to 'releng')
-rw-r--r--releng/migrations/0008_auto__del_field_release_torrent_infohash__del_field_release_file_size.py118
-rw-r--r--releng/models.py10
-rw-r--r--releng/urls.py2
-rw-r--r--releng/views.py45
4 files changed, 170 insertions, 5 deletions
diff --git a/releng/migrations/0008_auto__del_field_release_torrent_infohash__del_field_release_file_size.py b/releng/migrations/0008_auto__del_field_release_torrent_infohash__del_field_release_file_size.py
new file mode 100644
index 00000000..4a80fd8e
--- /dev/null
+++ b/releng/migrations/0008_auto__del_field_release_torrent_infohash__del_field_release_file_size.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ db.delete_column(u'releng_release', 'torrent_infohash')
+ db.delete_column(u'releng_release', 'file_size')
+
+ def backwards(self, orm):
+ db.add_column(u'releng_release', 'torrent_infohash',
+ self.gf('django.db.models.fields.CharField')(default='', max_length=40, blank=True),
+ keep_default=False)
+ db.add_column(u'releng_release', 'file_size',
+ self.gf('main.fields.PositiveBigIntegerField')(null=True, blank=True),
+ keep_default=False)
+
+ models = {
+ u'releng.architecture': {
+ 'Meta': {'object_name': 'Architecture'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.bootloader': {
+ 'Meta': {'object_name': 'Bootloader'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.boottype': {
+ 'Meta': {'object_name': 'BootType'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.clockchoice': {
+ 'Meta': {'object_name': 'ClockChoice'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.filesystem': {
+ 'Meta': {'object_name': 'Filesystem'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.hardwaretype': {
+ 'Meta': {'object_name': 'HardwareType'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.installtype': {
+ 'Meta': {'object_name': 'InstallType'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.iso': {
+ 'Meta': {'object_name': 'Iso'},
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'removed': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'})
+ },
+ u'releng.isotype': {
+ 'Meta': {'object_name': 'IsoType'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.module': {
+ 'Meta': {'object_name': 'Module'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.release': {
+ 'Meta': {'ordering': "('-release_date', '-version')", 'object_name': 'Release'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'info': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'kernel_version': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
+ 'md5_sum': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
+ 'release_date': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
+ 'sha1_sum': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
+ 'torrent_data': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'version': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'})
+ },
+ u'releng.source': {
+ 'Meta': {'object_name': 'Source'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ u'releng.test': {
+ 'Meta': {'object_name': 'Test'},
+ 'architecture': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.Architecture']"}),
+ 'boot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.BootType']"}),
+ 'bootloader': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.Bootloader']"}),
+ 'clock_choice': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.ClockChoice']"}),
+ 'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'filesystem': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.Filesystem']"}),
+ 'hardware_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.HardwareType']"}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'install_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.InstallType']"}),
+ 'ip_address': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
+ 'iso': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.Iso']"}),
+ 'iso_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.IsoType']"}),
+ 'modules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['releng.Module']", 'null': 'True', 'blank': 'True'}),
+ 'rollback_filesystem': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rollback_test_set'", 'null': 'True', 'to': u"orm['releng.Filesystem']"}),
+ 'rollback_modules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'rollback_test_set'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['releng.Module']"}),
+ 'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['releng.Source']"}),
+ 'success': ('django.db.models.fields.BooleanField', [], {}),
+ 'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+ 'user_name': ('django.db.models.fields.CharField', [], {'max_length': '500'})
+ }
+ }
+
+ complete_apps = ['releng']
diff --git a/releng/models.py b/releng/models.py
index 47803a36..a3af54f9 100644
--- a/releng/models.py
+++ b/releng/models.py
@@ -119,14 +119,13 @@ class Release(models.Model):
release_date = models.DateField(db_index=True)
version = models.CharField(max_length=50, unique=True)
kernel_version = models.CharField(max_length=50, blank=True)
- torrent_infohash = models.CharField(max_length=40, blank=True)
md5_sum = models.CharField('MD5 digest', max_length=32, blank=True)
sha1_sum = models.CharField('SHA1 digest', max_length=40, blank=True)
- file_size = PositiveBigIntegerField(null=True, blank=True)
created = models.DateTimeField(editable=False)
available = models.BooleanField(default=True)
info = models.TextField('Public information', blank=True)
- torrent_data = models.TextField(blank=True)
+ torrent_data = models.TextField(blank=True,
+ help_text="base64-encoded torrent file")
class Meta:
get_latest_by = 'release_date'
@@ -150,8 +149,9 @@ class Release(models.Model):
]
if settings.TORRENT_TRACKERS:
query.extend(('tr', uri) for uri in settings.TORRENT_TRACKERS)
- if self.torrent_infohash:
- query.insert(0, ('xt', "urn:btih:%s" % self.torrent_infohash))
+ metadata = self.torrent()
+ if metadata and 'info_hash' in metadata:
+ query.insert(0, ('xt', "urn:btih:%s" % metadata['info_hash']))
return "magnet:?%s" % '&'.join(['%s=%s' % (k, v) for k, v in query])
def info_html(self):
diff --git a/releng/urls.py b/releng/urls.py
index 76c36345..ca76eb25 100644
--- a/releng/urls.py
+++ b/releng/urls.py
@@ -14,6 +14,8 @@ feedback_patterns = patterns('releng.views',
releases_patterns = patterns('releng.views',
(r'^$',
ReleaseListView.as_view(), {}, 'releng-release-list'),
+ (r'^json/$',
+ 'releases_json', {}, 'releng-release-list-json'),
(r'^(?P<version>[-.\w]+)/$',
ReleaseDetailView.as_view(), {}, 'releng-release-detail'),
(r'^(?P<version>[-.\w]+)/torrent/$',
diff --git a/releng/views.py b/releng/views.py
index bc7ddb34..af25b966 100644
--- a/releng/views.py
+++ b/releng/views.py
@@ -1,7 +1,10 @@
from base64 import b64decode
+import json
from django import forms
from django.conf import settings
+from django.core.serializers.json import DjangoJSONEncoder
+from django.core.urlresolvers import reverse
from django.db.models import Count, Max
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
@@ -238,4 +241,46 @@ def release_torrent(request, version):
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response
+
+class ReleaseJSONEncoder(DjangoJSONEncoder):
+ release_attributes = ('release_date', 'version', 'kernel_version',
+ 'created', 'md5_sum', 'sha1_sum')
+
+ def default(self, obj):
+ if hasattr(obj, '__iter__'):
+ # mainly for queryset serialization
+ return list(obj)
+ if isinstance(obj, Release):
+ data = {attr: getattr(obj, attr) or None
+ for attr in self.release_attributes}
+ data['available'] = obj.available
+ data['iso_url'] = '/' + obj.iso_url()
+ data['magnet_uri'] = obj.magnet_uri()
+ data['torrent_url'] = reverse('releng-release-torrent', args=[obj.version])
+ data['info'] = obj.info_html()
+ torrent_data = obj.torrent()
+ if torrent_data:
+ torrent_data.pop('url_list', None)
+ data['torrent'] = torrent_data
+ return data
+ return super(ReleaseJSONEncoder, self).default(obj)
+
+
+def releases_json(request):
+ releases = Release.objects.all()
+ try:
+ latest_version = Release.objects.filter(available=True).values_list(
+ 'version', flat=True).latest()
+ except Release.DoesNotExist:
+ latest_version = None
+
+ data = {
+ 'version': 1,
+ 'releases': releases,
+ 'latest_version': latest_version,
+ }
+ to_json = json.dumps(data, ensure_ascii=False, cls=ReleaseJSONEncoder)
+ response = HttpResponse(to_json, content_type='application/json')
+ return response
+
# vim: set ts=4 sw=4 et: