From 1a55c0f0bc8359f85f6c23d69cdf3ca05a4d25a2 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 28 Jan 2013 13:50:33 -0700 Subject: Don't error on empty torrent data Signed-off-by: Dan McGee --- releng/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/releng/models.py b/releng/models.py index a0dd57aa..19040905 100644 --- a/releng/models.py +++ b/releng/models.py @@ -160,6 +160,8 @@ class Release(models.Model): data = b64decode(self.torrent_data) except TypeError: return None + if not data: + return None data = bdecode(data) # transform the data into a template-friendly dict info = data.get('info', {}) -- cgit v1.2.3-55-g3dc8 From 7d4a8b9adf353d7adce4c3c22101e774092eb4de Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 28 Jan 2013 14:06:41 -0700 Subject: Add MD5 and SHA1 fields for releases Signed-off-by: Dan McGee --- ...dd_field_release_md5__add_field_release_sha1.py | 122 +++++++++++++++++++++ releng/models.py | 4 +- templates/releng/release_detail.html | 2 + 3 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 releng/migrations/0007_auto__add_field_release_md5__add_field_release_sha1.py diff --git a/releng/migrations/0007_auto__add_field_release_md5__add_field_release_sha1.py b/releng/migrations/0007_auto__add_field_release_md5__add_field_release_sha1.py new file mode 100644 index 00000000..f76be3d7 --- /dev/null +++ b/releng/migrations/0007_auto__add_field_release_md5__add_field_release_sha1.py @@ -0,0 +1,122 @@ +# -*- 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.add_column('releng_release', 'md5_sum', + self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True), + keep_default=False) + db.add_column('releng_release', 'sha1_sum', + self.gf('django.db.models.fields.CharField')(default='', max_length=40, blank=True), + keep_default=False) + db.alter_column('releng_release', 'torrent_infohash', self.gf('django.db.models.fields.CharField')(max_length=40)) + + def backwards(self, orm): + db.delete_column('releng_release', 'md5_sum') + db.delete_column('releng_release', 'sha1_sum') + db.alter_column('releng_release', 'torrent_infohash', self.gf('django.db.models.fields.CharField')(max_length=64)) + + models = { + 'releng.architecture': { + 'Meta': {'object_name': 'Architecture'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.bootloader': { + 'Meta': {'object_name': 'Bootloader'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.boottype': { + 'Meta': {'object_name': 'BootType'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.clockchoice': { + 'Meta': {'object_name': 'ClockChoice'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.filesystem': { + 'Meta': {'object_name': 'Filesystem'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.hardwaretype': { + 'Meta': {'object_name': 'HardwareType'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.installtype': { + 'Meta': {'object_name': 'InstallType'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.iso': { + 'Meta': {'object_name': 'Iso'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {}), + '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'}) + }, + 'releng.isotype': { + 'Meta': {'object_name': 'IsoType'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.module': { + 'Meta': {'object_name': 'Module'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.release': { + 'Meta': {'ordering': "('-release_date', '-version')", 'object_name': 'Release'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {}), + 'file_size': ('main.fields.PositiveBigIntegerField', [], {'null': 'True', 'blank': 'True'}), + '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'}), + 'torrent_infohash': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}), + 'version': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}) + }, + 'releng.source': { + 'Meta': {'object_name': 'Source'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'releng.test': { + 'Meta': {'object_name': 'Test'}, + 'architecture': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['releng.Architecture']"}), + 'boot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['releng.BootType']"}), + 'bootloader': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['releng.Bootloader']"}), + 'clock_choice': ('django.db.models.fields.related.ForeignKey', [], {'to': "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': "orm['releng.Filesystem']"}), + 'hardware_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['releng.HardwareType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'install_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['releng.InstallType']"}), + 'ip_address': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), + 'iso': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['releng.Iso']"}), + 'iso_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['releng.IsoType']"}), + 'modules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "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': "orm['releng.Filesystem']"}), + 'rollback_modules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'rollback_test_set'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['releng.Module']"}), + 'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['releng.Source']"}), + 'success': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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 19040905..dd034e7f 100644 --- a/releng/models.py +++ b/releng/models.py @@ -118,7 +118,9 @@ 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=64, 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) diff --git a/templates/releng/release_detail.html b/templates/releng/release_detail.html index f4de9e52..ea54be66 100644 --- a/templates/releng/release_detail.html +++ b/templates/releng/release_detail.html @@ -13,6 +13,8 @@ title="Download torrent for {{ release.version }}">Torrent, Magnet{% endif %} {% if release.torrent_infohash %}
  • Torrent Info Hash: {{ release.torrent_infohash }}
  • {% endif %} + {% if release.md5_sum %}
  • MD5: {{ release.md5_sum }}
  • {% endif %} + {% if release.sha1_sum %}
  • SHA1: {{ release.sha1_sum }}
  • {% endif %}
  • Download Size: {% if release.file_size %}{{ release.file_size|filesizeformat }}{% else %}Unknown{% endif %}
  • -- cgit v1.2.3-55-g3dc8 From bc539b6ed174fed1545aabaa4ceb7a7f925cbbed Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 28 Jan 2013 14:13:53 -0700 Subject: Extract torrent trackers into a settings variable This allows them to be overridden and changed in a central location, like we do with the SVN URL, PXE boot URL, etc. Signed-off-by: Dan McGee --- releng/models.py | 5 +++-- settings.py | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/releng/models.py b/releng/models.py index dd034e7f..b95f7d52 100644 --- a/releng/models.py +++ b/releng/models.py @@ -5,6 +5,7 @@ import hashlib import markdown from pytz import utc +from django.conf import settings from django.core.urlresolvers import reverse from django.db import models from django.db.models.signals import pre_save @@ -146,9 +147,9 @@ class Release(models.Model): def magnet_uri(self): query = [ ('dn', "archlinux-%s-dual.iso" % self.version), - ('tr', "udp://tracker.archlinux.org:6969"), - ('tr', "http://tracker.archlinux.org:6969/announce"), ] + 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)) return "magnet:?%s" % '&'.join(['%s=%s' % (k, v) for k, v in query]) diff --git a/settings.py b/settings.py index dbc06159..c856bf57 100644 --- a/settings.py +++ b/settings.py @@ -164,6 +164,12 @@ PXEBOOT_URL = 'https://releng.archlinux.org/pxeboot/' # community bit on the end, repo.svn_root is appended) SVN_BASE_URL = 'svn://svn.archlinux.org/' +# Trackers used for ISO download magnet links +TORRENT_TRACKERS = ( + 'udp://tracker.archlinux.org:6969', + 'http://tracker.archlinux.org:6969/announce', +) + ## Import local settings from local_settings import * -- cgit v1.2.3-55-g3dc8 From a471316a58a9c62b869696fe36d72abcbf9f2ab1 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 28 Jan 2013 14:27:44 -0700 Subject: Use torrent view and checksums where appropriate We no longer need to link externally to these items since we have all the data available in the web application now. Signed-off-by: Dan McGee --- templates/public/download.html | 12 +++++------- templates/releng/release_detail.html | 5 ++++- templates/releng/release_list.html | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/templates/public/download.html b/templates/public/download.html index 29490849..f385ea29 100644 --- a/templates/public/download.html +++ b/templates/public/download.html @@ -56,8 +56,8 @@

    If you can spare the bytes, please leave the client open after your download is finished, so you can seed it back to others. A web-seed capable client is recommended for fastest download speeds.

    -

    Download torrent for {{ release.version }} +

    Download torrent for {{ release.version }} (Magnet) {% if release.file_size %}({{ release.file_size|filesizeformat }}){% endif %}

    @@ -81,11 +81,9 @@
    • PGP signature
    • -
    • SHA1 checksums
    • -
    • MD5 checksums
    • + title="PGP signature">PGP signature + {% if release.md5_sum %}
    • MD5: {{ release.md5_sum }}
    • {% endif %} + {% if release.sha1_sum %}
    • SHA1: {{ release.sha1_sum }}
    • {% endif %}
    {% cache 600 download-mirrors %} diff --git a/templates/releng/release_detail.html b/templates/releng/release_detail.html index ea54be66..01c0319e 100644 --- a/templates/releng/release_detail.html +++ b/templates/releng/release_detail.html @@ -1,4 +1,6 @@ {% extends "base.html" %} +{% load url from future %} + {% block title %}Arch Linux - Release: {{ release.version }}{% endblock %} {% block content %} @@ -9,7 +11,8 @@
  • Release Date: {{ release.release_date|date }}
  • {% if release.kernel_version %}
  • Kernel Version: {{ release.kernel_version }}
  • {% endif %}
  • Available: {{ release.available|yesno }}
  • - {% if release.available %}
  • Download: Download: Torrent, Magnet
  • {% endif %} {% if release.torrent_infohash %}
  • Torrent Info Hash: {{ release.torrent_infohash }}
  • {% endif %} diff --git a/templates/releng/release_list.html b/templates/releng/release_list.html index 84008541..ef53a93d 100644 --- a/templates/releng/release_list.html +++ b/templates/releng/release_list.html @@ -31,7 +31,7 @@ {{ item.version }} {{ item.kernel_version|default:"" }} {{ item.available|yesno|capfirst }} - {% if item.available %}{% if item.available %}Torrent{% endif %} {% if item.available %}Magnet{% endif %} {% if item.file_size %}{{ item.file_size|filesizeformat }}{% endif %} -- cgit v1.2.3-55-g3dc8 From 6cf98552f1c83d8e4fca1526131febd17045eae7 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 28 Jan 2013 14:48:37 -0700 Subject: Slight reorginization in the download page template Move things up that don't belong to the torrent section; make magnet link more prominent by using a bulleted list. Signed-off-by: Dan McGee --- templates/public/download.html | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/templates/public/download.html b/templates/public/download.html index f385ea29..c68cf66b 100644 --- a/templates/public/download.html +++ b/templates/public/download.html @@ -28,6 +28,7 @@
    • Current Release: {{ release.version }}
    • {% if release.kernel_version %}
    • Included Kernel: {{ release.kernel_version }}
    • {% endif %} + {% if release.file_size %}
    • ISO Size: {{ release.file_size|filesizeformat }}
    • {% endif %}
    • Installation Guide
    • Resources: