summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--devel/migrations/0006_auto__add_field_userprofile_country.py107
-rw-r--r--devel/migrations/0007_auto_assign_countries.py157
-rw-r--r--devel/models.py2
-rw-r--r--main/migrations/0004_add_pkgname_index.py22
-rw-r--r--mirrors/admin.py2
-rw-r--r--mirrors/migrations/0009_auto__chg_field_mirrorurl_country.py6
-rw-r--r--mirrors/migrations/0010_auto__add_field_mirrorprotocol_default.py2
-rw-r--r--mirrors/migrations/0011_adjust_protocol_defaults.py2
-rw-r--r--mirrors/migrations/0012_auto__add_on_delete_attribute.py2
-rw-r--r--mirrors/migrations/0013_rename_country_fields.py68
-rw-r--r--mirrors/migrations/0014_add_country_code_fields.py74
-rw-r--r--mirrors/migrations/0015_assign_country_codes.py93
-rw-r--r--mirrors/migrations/0016_auto__del_field_mirror_country_old__del_field_mirrorurl_country_old.py76
-rw-r--r--mirrors/models.py15
-rw-r--r--mirrors/utils.py18
-rw-r--r--mirrors/views.py82
-rw-r--r--public/views.py12
-rw-r--r--requirements.txt9
-rw-r--r--requirements_prod.txt17
-rw-r--r--settings.py1
-rw-r--r--sitestatic/archweb.css100
-rw-r--r--templates/devel/clock.html2
-rw-r--r--templates/mirrors/mirror_details.html2
-rw-r--r--templates/mirrors/mirrorlist.txt2
-rw-r--r--templates/mirrors/mirrorlist_generate.html (renamed from templates/mirrors/index.html)2
-rw-r--r--templates/mirrors/mirrorlist_status.txt3
-rw-r--r--templates/mirrors/mirrors.html16
-rw-r--r--templates/mirrors/status.html14
-rw-r--r--templates/mirrors/status_table.html4
-rw-r--r--templates/packages/details.html2
-rw-r--r--templates/packages/files.html8
-rw-r--r--templates/packages/files_list.html2
-rw-r--r--templates/public/developer_list.html8
33 files changed, 776 insertions, 156 deletions
diff --git a/devel/migrations/0006_auto__add_field_userprofile_country.py b/devel/migrations/0006_auto__add_field_userprofile_country.py
new file mode 100644
index 00000000..1b3b182c
--- /dev/null
+++ b/devel/migrations/0006_auto__add_field_userprofile_country.py
@@ -0,0 +1,107 @@
+# -*- 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('user_profiles', 'country',
+ self.gf('django_countries.fields.CountryField')(default='', max_length=2, blank=True),
+ keep_default=True)
+
+ def backwards(self, orm):
+ db.delete_column('user_profiles', 'country')
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'devel.masterkey': {
+ 'Meta': {'ordering': "('created',)", 'object_name': 'MasterKey'},
+ 'created': ('django.db.models.fields.DateField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'masterkey_owner'", 'to': "orm['auth.User']"}),
+ 'pgp_key': ('devel.fields.PGPKeyField', [], {'max_length': '40'}),
+ 'revoked': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'revoker': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'masterkey_revoker'", 'to': "orm['auth.User']"})
+ },
+ 'devel.pgpsignature': {
+ 'Meta': {'object_name': 'PGPSignature'},
+ 'created': ('django.db.models.fields.DateField', [], {}),
+ 'expires': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'signee': ('devel.fields.PGPKeyField', [], {'max_length': '40'}),
+ 'signer': ('devel.fields.PGPKeyField', [], {'max_length': '40'}),
+ 'valid': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
+ },
+ 'devel.userprofile': {
+ 'Meta': {'object_name': 'UserProfile', 'db_table': "'user_profiles'"},
+ 'alias': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'allowed_repos': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Repo']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}),
+ 'favorite_distros': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'interests': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'languages': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'latin_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'location': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'notify': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'other_contact': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'pgp_key': ('devel.fields.PGPKeyField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+ 'picture': ('django.db.models.fields.files.FileField', [], {'default': "'devs/silhouette.png'", 'max_length': '100'}),
+ 'public_email': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'roles': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'time_zone': ('django.db.models.fields.CharField', [], {'default': "'UTC'", 'max_length': '100'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': "orm['auth.User']"}),
+ 'website': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'yob': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'main.repo': {
+ 'Meta': {'ordering': "['name']", 'object_name': 'Repo', 'db_table': "'repos'"},
+ 'bugs_category': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}),
+ 'bugs_project': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'staging': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'svn_root': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'testing': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ }
+ }
+
+ complete_apps = ['devel']
diff --git a/devel/migrations/0007_auto_assign_countries.py b/devel/migrations/0007_auto_assign_countries.py
new file mode 100644
index 00000000..2bad95a2
--- /dev/null
+++ b/devel/migrations/0007_auto_assign_countries.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+class Migration(DataMigration):
+
+ def forwards(self, orm):
+ # This is by no means an exhaustive list, but covered most of the time
+ # zones selected by existing developers at the time I wrote this
+ # migration.
+ tz_map = {
+ 'America/Argentina/Buenos_Aires': 'AR',
+ 'America/Chicago': 'US',
+ 'America/Los_Angeles': 'US',
+ 'America/Maceio': 'BR',
+ 'America/Montreal': 'CA',
+ 'America/New_York': 'US',
+ 'America/Puerto_Rico': 'PR',
+ 'America/Sao_Paulo': 'BR',
+ 'America/Toronto': 'CA',
+ 'America/Vancouver': 'CA',
+ 'Asia/Kolkata': 'IN',
+ 'Asia/Singapore': 'SG',
+ 'Australia/Brisbane': 'AU',
+ 'Australia/Melbourne': 'AU',
+ 'Australia/Sydney': 'AU',
+ 'Canada/Central': 'CA',
+ 'Canada/Eastern': 'CA',
+ 'Europe/Amsterdam': 'NL',
+ 'Europe/Athens': 'GR',
+ 'Europe/Berlin': 'DE',
+ 'Europe/Brussels': 'BE',
+ 'Europe/Bucharest': 'RO',
+ 'Europe/Budapest': 'HU',
+ 'Europe/Copenhagen': 'DK',
+ 'Europe/Dublin': 'IE',
+ 'Europe/Helsinki': 'FI',
+ 'Europe/Kiev': 'UA',
+ 'Europe/London': 'GB',
+ 'Europe/Madrid': 'ES',
+ 'Europe/Moscow': 'RU',
+ 'Europe/Oslo': 'NO',
+ 'Europe/Paris': 'FR',
+ 'Europe/Prague': 'CZ',
+ 'Europe/Rome': 'IT',
+ 'Europe/Vienna': 'AT',
+ 'Europe/Warsaw': 'PL',
+ 'Europe/Zurich': 'CH',
+ 'Pacific/Auckland': 'NZ',
+ 'US/Central': 'US',
+ 'US/Eastern': 'US',
+ 'US/Mountain': 'US',
+ 'US/Pacific': 'US',
+ }
+ empty_loc = models.Q(location__isnull=True) | models.Q(location='')
+ for tz, code in tz_map.items():
+ orm.UserProfile.objects.filter(time_zone=tz, country='').exclude(
+ empty_loc).update(country=code)
+
+
+ def backwards(self, orm):
+ pass
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'devel.masterkey': {
+ 'Meta': {'ordering': "('created',)", 'object_name': 'MasterKey'},
+ 'created': ('django.db.models.fields.DateField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'masterkey_owner'", 'to': "orm['auth.User']"}),
+ 'pgp_key': ('devel.fields.PGPKeyField', [], {'max_length': '40'}),
+ 'revoked': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'revoker': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'masterkey_revoker'", 'to': "orm['auth.User']"})
+ },
+ 'devel.pgpsignature': {
+ 'Meta': {'object_name': 'PGPSignature'},
+ 'created': ('django.db.models.fields.DateField', [], {}),
+ 'expires': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'signee': ('devel.fields.PGPKeyField', [], {'max_length': '40'}),
+ 'signer': ('devel.fields.PGPKeyField', [], {'max_length': '40'}),
+ 'valid': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
+ },
+ 'devel.userprofile': {
+ 'Meta': {'object_name': 'UserProfile', 'db_table': "'user_profiles'"},
+ 'alias': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'allowed_repos': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Repo']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}),
+ 'favorite_distros': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'interests': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'languages': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'latin_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'location': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'notify': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'other_contact': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'pgp_key': ('devel.fields.PGPKeyField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+ 'picture': ('django.db.models.fields.files.FileField', [], {'default': "'devs/silhouette.png'", 'max_length': '100'}),
+ 'public_email': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'roles': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'time_zone': ('django.db.models.fields.CharField', [], {'default': "'UTC'", 'max_length': '100'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': "orm['auth.User']"}),
+ 'website': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'yob': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'main.repo': {
+ 'Meta': {'ordering': "['name']", 'object_name': 'Repo', 'db_table': "'repos'"},
+ 'bugs_category': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}),
+ 'bugs_project': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'staging': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'svn_root': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'testing': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ }
+ }
+
+ complete_apps = ['devel']
+ symmetrical = True
diff --git a/devel/models.py b/devel/models.py
index 79c56f2a..fd5a0347 100644
--- a/devel/models.py
+++ b/devel/models.py
@@ -3,6 +3,7 @@ import pytz
from django.db import models
from django.contrib.auth.models import User
+from django_countries import CountryField
from .fields import PGPKeyField
from main.utils import make_choice
@@ -30,6 +31,7 @@ class UserProfile(models.Model):
help_text="consists of 40 hex digits; use `gpg --fingerprint`")
website = models.CharField(max_length=200, null=True, blank=True)
yob = models.IntegerField("Year of birth", null=True, blank=True)
+ country = CountryField(blank=True)
location = models.CharField(max_length=50, null=True, blank=True)
languages = models.CharField(max_length=50, null=True, blank=True)
interests = models.CharField(max_length=255, null=True, blank=True)
diff --git a/main/migrations/0004_add_pkgname_index.py b/main/migrations/0004_add_pkgname_index.py
index aeb85b2e..0aae4522 100644
--- a/main/migrations/0004_add_pkgname_index.py
+++ b/main/migrations/0004_add_pkgname_index.py
@@ -1,34 +1,18 @@
-
+# encoding: utf-8
from south.db import db
+from south.v2 import SchemaMigration
from django.db import models
-from main.models import *
-class Migration:
+class Migration(SchemaMigration):
def forwards(self, orm):
-
- # Changing field 'Package.maintainer'
- # (to signature: django.db.models.fields.related.ForeignKey(blank=True, null=True, to=orm['auth.User']))
db.alter_column('packages', 'maintainer_id', orm['main.package:maintainer'])
-
- # Changing field 'Package.pkgname'
- # (to signature: django.db.models.fields.CharField(max_length=255, db_index=True))
db.alter_column('packages', 'pkgname', orm['main.package:pkgname'])
-
- db.create_index('packages', ['pkgname'])
def backwards(self, orm):
-
- # Changing field 'Package.maintainer'
- # (to signature: django.db.models.fields.related.ForeignKey(null=True, to=orm['auth.User']))
db.alter_column('packages', 'maintainer_id', orm['main.package:maintainer'])
-
- # Changing field 'Package.pkgname'
- # (to signature: django.db.models.fields.CharField(max_length=255))
db.alter_column('packages', 'pkgname', orm['main.package:pkgname'])
-
- db.delete_index('packages', ['pkgname'])
models = {
diff --git a/mirrors/admin.py b/mirrors/admin.py
index a2b59b41..b7b9894c 100644
--- a/mirrors/admin.py
+++ b/mirrors/admin.py
@@ -64,7 +64,7 @@ class MirrorAdmin(admin.ModelAdmin):
form = MirrorAdminForm
list_display = ('name', 'tier', 'country', 'active', 'public',
'isos', 'admin_email')
- list_filter = ('tier', 'active', 'public', 'country')
+ list_filter = ('tier', 'active', 'public', 'country')
search_fields = ('name',)
inlines = [
MirrorUrlInlineAdmin,
diff --git a/mirrors/migrations/0009_auto__chg_field_mirrorurl_country.py b/mirrors/migrations/0009_auto__chg_field_mirrorurl_country.py
index 941ecfbb..bca6b6fb 100644
--- a/mirrors/migrations/0009_auto__chg_field_mirrorurl_country.py
+++ b/mirrors/migrations/0009_auto__chg_field_mirrorurl_country.py
@@ -7,11 +7,11 @@ from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
- db.alter_column('mirrors_mirrorurl', 'country', self.gf('mirrors.models.NullCharField')(max_length=255, null=True))
+ pass
def backwards(self, orm):
- db.alter_column('mirrors_mirrorurl', 'country', self.gf('django.db.models.fields.CharField')(max_length=255, null=True))
+ pass
models = {
'mirrors.mirror': {
@@ -53,7 +53,7 @@ class Migration(SchemaMigration):
},
'mirrors.mirrorurl': {
'Meta': {'object_name': 'MirrorUrl'},
- 'country': ('mirrors.models.NullCharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
diff --git a/mirrors/migrations/0010_auto__add_field_mirrorprotocol_default.py b/mirrors/migrations/0010_auto__add_field_mirrorprotocol_default.py
index 6868cb25..d30c78c7 100644
--- a/mirrors/migrations/0010_auto__add_field_mirrorprotocol_default.py
+++ b/mirrors/migrations/0010_auto__add_field_mirrorprotocol_default.py
@@ -53,7 +53,7 @@ class Migration(SchemaMigration):
},
'mirrors.mirrorurl': {
'Meta': {'object_name': 'MirrorUrl'},
- 'country': ('mirrors.models.NullCharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
diff --git a/mirrors/migrations/0011_adjust_protocol_defaults.py b/mirrors/migrations/0011_adjust_protocol_defaults.py
index 0118de67..a5ffafb4 100644
--- a/mirrors/migrations/0011_adjust_protocol_defaults.py
+++ b/mirrors/migrations/0011_adjust_protocol_defaults.py
@@ -54,7 +54,7 @@ class Migration(DataMigration):
},
'mirrors.mirrorurl': {
'Meta': {'object_name': 'MirrorUrl'},
- 'country': ('mirrors.models.NullCharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
diff --git a/mirrors/migrations/0012_auto__add_on_delete_attribute.py b/mirrors/migrations/0012_auto__add_on_delete_attribute.py
index 3990d466..f81fe0ae 100644
--- a/mirrors/migrations/0012_auto__add_on_delete_attribute.py
+++ b/mirrors/migrations/0012_auto__add_on_delete_attribute.py
@@ -55,7 +55,7 @@ class Migration(SchemaMigration):
},
'mirrors.mirrorurl': {
'Meta': {'object_name': 'MirrorUrl'},
- 'country': ('mirrors.models.NullCharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
diff --git a/mirrors/migrations/0013_rename_country_fields.py b/mirrors/migrations/0013_rename_country_fields.py
new file mode 100644
index 00000000..8a9bc34a
--- /dev/null
+++ b/mirrors/migrations/0013_rename_country_fields.py
@@ -0,0 +1,68 @@
+# -*- 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.rename_column('mirrors_mirror', 'country', 'country_old')
+ db.rename_column('mirrors_mirrorurl', 'country', 'country_old')
+
+ def backwards(self, orm):
+ db.rename_column('mirrors_mirror', 'country_old', 'country')
+ db.rename_column('mirrors_mirrorurl', 'country_old', 'country')
+
+ models = {
+ 'mirrors.mirror': {
+ 'Meta': {'ordering': "('country_old', 'name')", 'object_name': 'Mirror'},
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'admin_email': ('django.db.models.fields.EmailField', [], {'max_length': '255', 'blank': 'True'}),
+ 'country_old': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'isos': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'rsync_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'rsync_user': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'tier': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}),
+ 'upstream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['mirrors.Mirror']", 'null': 'True', 'on_delete': 'models.SET_NULL'})
+ },
+ 'mirrors.mirrorlog': {
+ 'Meta': {'object_name': 'MirrorLog'},
+ 'check_time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
+ 'error': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_success': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'logs'", 'to': "orm['mirrors.MirrorUrl']"})
+ },
+ 'mirrors.mirrorprotocol': {
+ 'Meta': {'ordering': "('protocol',)", 'object_name': 'MirrorProtocol'},
+ 'default': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_download': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'})
+ },
+ 'mirrors.mirrorrsync': {
+ 'Meta': {'object_name': 'MirrorRsync'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip': ('django.db.models.fields.CharField', [], {'max_length': '24'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rsync_ips'", 'to': "orm['mirrors.Mirror']"})
+ },
+ 'mirrors.mirrorurl': {
+ 'Meta': {'object_name': 'MirrorUrl'},
+ 'country_old': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['mirrors.Mirror']"}),
+ 'protocol': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'on_delete': 'models.PROTECT', 'to': "orm['mirrors.MirrorProtocol']"}),
+ 'url': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ }
+ }
+
+ complete_apps = ['mirrors']
diff --git a/mirrors/migrations/0014_add_country_code_fields.py b/mirrors/migrations/0014_add_country_code_fields.py
new file mode 100644
index 00000000..010194d7
--- /dev/null
+++ b/mirrors/migrations/0014_add_country_code_fields.py
@@ -0,0 +1,74 @@
+# -*- 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('mirrors_mirror', 'country',
+ self.gf('django_countries.fields.CountryField')(default='', max_length=2, blank=True),
+ keep_default=False)
+ db.add_column('mirrors_mirrorurl', 'country',
+ self.gf('django_countries.fields.CountryField')(default='', max_length=2, blank=True),
+ keep_default=False)
+
+ def backwards(self, orm):
+ db.delete_column('mirrors_mirror', 'country')
+ db.delete_column('mirrors_mirrorurl', 'country')
+
+ models = {
+ 'mirrors.mirror': {
+ 'Meta': {'ordering': "('country', 'name')", 'object_name': 'Mirror'},
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'admin_email': ('django.db.models.fields.EmailField', [], {'max_length': '255', 'blank': 'True'}),
+ 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}),
+ 'country_old': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'isos': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'rsync_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'rsync_user': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'tier': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}),
+ 'upstream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['mirrors.Mirror']", 'null': 'True', 'on_delete': 'models.SET_NULL'})
+ },
+ 'mirrors.mirrorlog': {
+ 'Meta': {'object_name': 'MirrorLog'},
+ 'check_time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
+ 'error': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_success': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'logs'", 'to': "orm['mirrors.MirrorUrl']"})
+ },
+ 'mirrors.mirrorprotocol': {
+ 'Meta': {'ordering': "('protocol',)", 'object_name': 'MirrorProtocol'},
+ 'default': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_download': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'})
+ },
+ 'mirrors.mirrorrsync': {
+ 'Meta': {'object_name': 'MirrorRsync'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip': ('django.db.models.fields.CharField', [], {'max_length': '24'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rsync_ips'", 'to': "orm['mirrors.Mirror']"})
+ },
+ 'mirrors.mirrorurl': {
+ 'Meta': {'object_name': 'MirrorUrl'},
+ 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}),
+ 'country_old': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['mirrors.Mirror']"}),
+ 'protocol': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'on_delete': 'models.PROTECT', 'to': "orm['mirrors.MirrorProtocol']"}),
+ 'url': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ }
+ }
+
+ complete_apps = ['mirrors']
diff --git a/mirrors/migrations/0015_assign_country_codes.py b/mirrors/migrations/0015_assign_country_codes.py
new file mode 100644
index 00000000..c1b0f969
--- /dev/null
+++ b/mirrors/migrations/0015_assign_country_codes.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+from django_countries.countries import OFFICIAL_COUNTRIES
+
+class Migration(DataMigration):
+
+ def forwards(self, orm):
+ reverse_map = dict((v, k) for k, v in OFFICIAL_COUNTRIES.items())
+ # add a few special cases to the list that we know might exist
+ reverse_map['GREAT BRITAIN'] = 'GB'
+ reverse_map['KOREA'] = 'KR'
+ reverse_map['MACEDONIA'] = 'MK'
+ reverse_map['RUSSIA'] = 'RU'
+ reverse_map['SOUTH KOREA'] = 'KR'
+ reverse_map['TAIWAN'] = 'TW'
+ reverse_map['VIETNAM'] = 'VN'
+
+ for country_name in orm.Mirror.objects.values_list(
+ 'country_old', flat=True).order_by().distinct():
+ code = reverse_map.get(country_name.upper(), '')
+ orm.Mirror.objects.filter(
+ country_old=country_name).update(country=code)
+
+ for country_name in orm.MirrorUrl.objects.filter(
+ country_old__isnull=False).values_list(
+ 'country_old', flat=True).order_by().distinct():
+ code = reverse_map.get(country_name.upper(), '')
+ orm.MirrorUrl.objects.filter(
+ country_old=country_name).update(country=code)
+
+ def backwards(self, orm):
+ orm.MirrorUrl.objects.all().update(country='')
+ orm.Mirror.objects.all().update(country='')
+
+ models = {
+ 'mirrors.mirror': {
+ 'Meta': {'ordering': "('country', 'name')", 'object_name': 'Mirror'},
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'admin_email': ('django.db.models.fields.EmailField', [], {'max_length': '255', 'blank': 'True'}),
+ 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}),
+ 'country_old': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'isos': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'rsync_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'rsync_user': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'tier': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}),
+ 'upstream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['mirrors.Mirror']", 'null': 'True', 'on_delete': 'models.SET_NULL'})
+ },
+ 'mirrors.mirrorlog': {
+ 'Meta': {'object_name': 'MirrorLog'},
+ 'check_time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
+ 'error': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_success': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'logs'", 'to': "orm['mirrors.MirrorUrl']"})
+ },
+ 'mirrors.mirrorprotocol': {
+ 'Meta': {'ordering': "('protocol',)", 'object_name': 'MirrorProtocol'},
+ 'default': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_download': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'})
+ },
+ 'mirrors.mirrorrsync': {
+ 'Meta': {'object_name': 'MirrorRsync'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip': ('django.db.models.fields.CharField', [], {'max_length': '24'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rsync_ips'", 'to': "orm['mirrors.Mirror']"})
+ },
+ 'mirrors.mirrorurl': {
+ 'Meta': {'object_name': 'MirrorUrl'},
+ 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}),
+ 'country_old': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['mirrors.Mirror']"}),
+ 'protocol': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'on_delete': 'models.PROTECT', 'to': "orm['mirrors.MirrorProtocol']"}),
+ 'url': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ }
+ }
+
+ complete_apps = ['mirrors']
+ symmetrical = True
diff --git a/mirrors/migrations/0016_auto__del_field_mirror_country_old__del_field_mirrorurl_country_old.py b/mirrors/migrations/0016_auto__del_field_mirror_country_old__del_field_mirrorurl_country_old.py
new file mode 100644
index 00000000..b296d7ae
--- /dev/null
+++ b/mirrors/migrations/0016_auto__del_field_mirror_country_old__del_field_mirrorurl_country_old.py
@@ -0,0 +1,76 @@
+# -*- 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('mirrors_mirror', 'country_old')
+ db.delete_column('mirrors_mirrorurl', 'country_old')
+ db.create_index('mirrors_mirror', ['country'])
+ db.create_index('mirrors_mirrorurl', ['country'])
+
+ def backwards(self, orm):
+ db.delete_index('mirrors_mirrorurl', ['country'])
+ db.delete_index('mirrors_mirror', ['country'])
+ db.add_column('mirrors_mirror', 'country_old',
+ self.gf('django.db.models.fields.CharField')(default='Any', max_length=255, db_index=True),
+ keep_default=False)
+ db.add_column('mirrors_mirrorurl', 'country_old',
+ self.gf('django.db.models.fields.CharField')(blank=True, max_length=255, null=True, db_index=True),
+ keep_default=False)
+
+ models = {
+ 'mirrors.mirror': {
+ 'Meta': {'ordering': "('country', 'name')", 'object_name': 'Mirror'},
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'admin_email': ('django.db.models.fields.EmailField', [], {'max_length': '255', 'blank': 'True'}),
+ 'country': ('django_countries.fields.CountryField', [], {'db_index': 'True', 'max_length': '2', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'isos': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'rsync_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'rsync_user': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'tier': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}),
+ 'upstream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['mirrors.Mirror']", 'null': 'True', 'on_delete': 'models.SET_NULL'})
+ },
+ 'mirrors.mirrorlog': {
+ 'Meta': {'object_name': 'MirrorLog'},
+ 'check_time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
+ 'error': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_success': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'logs'", 'to': "orm['mirrors.MirrorUrl']"})
+ },
+ 'mirrors.mirrorprotocol': {
+ 'Meta': {'ordering': "('protocol',)", 'object_name': 'MirrorProtocol'},
+ 'default': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_download': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'})
+ },
+ 'mirrors.mirrorrsync': {
+ 'Meta': {'object_name': 'MirrorRsync'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip': ('django.db.models.fields.CharField', [], {'max_length': '24'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rsync_ips'", 'to': "orm['mirrors.Mirror']"})
+ },
+ 'mirrors.mirrorurl': {
+ 'Meta': {'object_name': 'MirrorUrl'},
+ 'country': ('django_countries.fields.CountryField', [], {'db_index': 'True', 'max_length': '2', 'blank': 'True'}),
+ 'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['mirrors.Mirror']"}),
+ 'protocol': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'on_delete': 'models.PROTECT', 'to': "orm['mirrors.MirrorProtocol']"}),
+ 'url': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ }
+ }
+
+ complete_apps = ['mirrors']
diff --git a/mirrors/models.py b/mirrors/models.py
index 86905eea..19437610 100644
--- a/mirrors/models.py
+++ b/mirrors/models.py
@@ -3,15 +3,8 @@ from urlparse import urlparse
from django.db import models
from django.core.exceptions import ValidationError
+from django_countries import CountryField
-class NullCharField(models.CharField):
- description = "String (up to %(max_length)s), NULL if value is empty"
- _south_introspects = True
-
- def get_prep_value(self, value):
- if value == '':
- return None
- return self.to_python(value)
TIER_CHOICES = (
(0, 'Tier 0'),
@@ -20,11 +13,12 @@ TIER_CHOICES = (
(-1, 'Untiered'),
)
+
class Mirror(models.Model):
name = models.CharField(max_length=255, unique=True)
tier = models.SmallIntegerField(default=2, choices=TIER_CHOICES)
upstream = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- country = models.CharField(max_length=255, db_index=True)
+ country = CountryField(blank=True, db_index=True)
admin_email = models.EmailField(max_length=255, blank=True)
public = models.BooleanField(default=True)
active = models.BooleanField(default=True)
@@ -68,8 +62,7 @@ class MirrorUrl(models.Model):
protocol = models.ForeignKey(MirrorProtocol, related_name="urls",
editable=False, on_delete=models.PROTECT)
mirror = models.ForeignKey(Mirror, related_name="urls")
- country = NullCharField(max_length=255, null=True, blank=True,
- db_index=True)
+ country = CountryField(blank=True, db_index=True)
has_ipv4 = models.BooleanField("IPv4 capable", default=True,
editable=False)
has_ipv6 = models.BooleanField("IPv6 capable", default=False,
diff --git a/mirrors/utils.py b/mirrors/utils.py
index ddecb095..32fa3587 100644
--- a/mirrors/utils.py
+++ b/mirrors/utils.py
@@ -1,6 +1,7 @@
from datetime import timedelta
from django.db.models import Avg, Count, Max, Min, StdDev
+from django_countries.fields import Country
from main.utils import cache_function, utc_now
from .models import MirrorLog, MirrorProtocol, MirrorUrl
@@ -42,8 +43,7 @@ def get_mirror_statuses(cutoff=default_cutoff):
last_sync=Max('logs__last_sync'),
last_check=Max('logs__check_time'),
duration_avg=Avg('logs__duration'),
- duration_stddev=StdDev('logs__duration')
- ).order_by('-last_sync', '-duration_avg')
+ duration_stddev=StdDev('logs__duration'))
# The Django ORM makes it really hard to get actual average delay in the
# above query, so run a seperate query for it and we will process the
@@ -95,7 +95,8 @@ def get_mirror_errors(cutoff=default_cutoff):
).order_by('-last_occurred', '-error_count')
errors = list(errors)
for err in errors:
- err['country'] = err['url__country'] or err['url__mirror__country']
+ ctry_code = err['url__country'] or err['url__mirror__country']
+ err['country'] = Country(ctry_code)
return errors
@@ -110,20 +111,19 @@ def get_mirror_url_for_download(cutoff=default_cutoff):
Max('check_time'), Max('last_sync'))
if status_data['check_time__max'] is not None:
min_check_time = status_data['check_time__max'] - timedelta(minutes=5)
- min_sync_time = status_data['last_sync__max'] - timedelta(minutes=30)
+ min_sync_time = status_data['last_sync__max'] - timedelta(minutes=20)
best_logs = MirrorLog.objects.filter(is_success=True,
check_time__gte=min_check_time, last_sync__gte=min_sync_time,
url__mirror__public=True, url__mirror__active=True,
- url__protocol__protocol__iexact='HTTP').order_by(
+ url__protocol__default=True).order_by(
'duration')[:1]
if best_logs:
return MirrorUrl.objects.get(id=best_logs[0].url_id)
mirror_urls = MirrorUrl.objects.filter(
- mirror__public=True, mirror__active=True,
- protocol__protocol__iexact='HTTP')
- # look first for an 'Any' URL, then fall back to any HTTP URL
- filtered_urls = mirror_urls.filter(mirror__country='Any')[:1]
+ mirror__public=True, mirror__active=True, protocol__default=True)
+ # look first for a country-agnostic URL, then fall back to any HTTP URL
+ filtered_urls = mirror_urls.filter(mirror__country='')[:1]
if not filtered_urls:
filtered_urls = mirror_urls[:1]
if not filtered_urls:
diff --git a/mirrors/views.py b/mirrors/views.py
index e93097a3..c52656f7 100644
--- a/mirrors/views.py
+++ b/mirrors/views.py
@@ -1,4 +1,8 @@
+from datetime import timedelta
+from operator import attrgetter, itemgetter
+
from django import forms
+from django.forms.widgets import CheckboxSelectMultiple
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Q
from django.http import Http404, HttpResponse
@@ -6,33 +10,55 @@ from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.simple import direct_to_template
from django.utils import simplejson
+from django_countries.countries import COUNTRIES
-from main.utils import make_choice
from .models import Mirror, MirrorUrl, MirrorProtocol
from .utils import get_mirror_statuses, get_mirror_errors
-import datetime
+COUNTRY_LOOKUP = dict(COUNTRIES)
+
class MirrorlistForm(forms.Form):
country = forms.MultipleChoiceField(required=False)
- protocol = forms.MultipleChoiceField(required=False)
+ protocol = forms.MultipleChoiceField(required=False,
+ widget=CheckboxSelectMultiple)
ip_version = forms.MultipleChoiceField(required=False,
- label="IP version", choices=(('4','IPv4'), ('6','IPv6')))
+ label="IP version", choices=(('4','IPv4'), ('6','IPv6')),
+ widget=CheckboxSelectMultiple)
use_mirror_status = forms.BooleanField(required=False)
def __init__(self, *args, **kwargs):
super(MirrorlistForm, self).__init__(*args, **kwargs)
- countries = Mirror.objects.filter(active=True).values_list(
- 'country', flat=True).distinct().order_by('country')
- self.fields['country'].choices = [('all','All')] + make_choice(
- countries)
- self.fields['country'].initial = ['all']
- protos = make_choice(
- MirrorProtocol.objects.filter(is_download=True))
+ fields = self.fields
+ fields['country'].choices = [('all','All')] + self.get_countries()
+ fields['country'].initial = ['all']
+ protos = [(p.protocol, p.protocol) for p in
+ MirrorProtocol.objects.filter(is_download=True)]
initial = MirrorProtocol.objects.filter(is_download=True, default=True)
- self.fields['protocol'].choices = protos
- self.fields['protocol'].initial = [p.protocol for p in initial]
- self.fields['ip_version'].initial = ['4']
+ fields['protocol'].choices = protos
+ fields['protocol'].initial = [p.protocol for p in initial]
+ fields['ip_version'].initial = ['4']
+
+ def get_countries(self):
+ country_codes = set()
+ country_codes.update(Mirror.objects.filter(active=True).exclude(
+ country='').values_list(
+ 'country', flat=True).order_by().distinct())
+ country_codes.update(MirrorUrl.objects.filter(
+ mirror__active=True).exclude(country='').values_list(
+ 'country', flat=True).order_by().distinct())
+ countries = [(code, COUNTRY_LOOKUP[code]) for code in country_codes]
+ return sorted(countries, key=itemgetter(1))
+
+ def as_div(self):
+ "Returns this form rendered as HTML <divs>s."
+ return self._html_output(
+ normal_row = u'<div%(html_class_attr)s>%(label)s %(field)s%(help_text)s</div>',
+ error_row = u'%s',
+ row_ender = '</div>',
+ help_text_html = u' <span class="helptext">%s</span>',
+ errors_on_separate_row = True)
+
@csrf_exempt
def generate_mirrorlist(request):
@@ -49,9 +75,10 @@ def generate_mirrorlist(request):
else:
form = MirrorlistForm()
- return direct_to_template(request, 'mirrors/index.html',
+ return direct_to_template(request, 'mirrors/mirrorlist_generate.html',
{'mirrorlist_form': form})
+
def find_mirrors(request, countries=None, protocols=None, use_status=False,
ipv4_supported=True, ipv6_supported=True):
if not protocols:
@@ -74,7 +101,7 @@ def find_mirrors(request, countries=None, protocols=None, use_status=False,
if not use_status:
urls = qset.order_by('mirror__name', 'url')
- urls = sorted(urls, key=lambda x: x.real_country)
+ urls = sorted(urls, key=attrgetter('real_country'))
template = 'mirrors/mirrorlist.txt'
else:
status_info = get_mirror_statuses()
@@ -96,6 +123,7 @@ def find_mirrors(request, countries=None, protocols=None, use_status=False,
},
mimetype='text/plain')
+
def mirrors(request):
mirror_list = Mirror.objects.select_related().order_by('tier', 'country')
if not request.user.is_authenticated():
@@ -103,6 +131,7 @@ def mirrors(request):
return direct_to_template(request, 'mirrors/mirrors.html',
{'mirror_list': mirror_list})
+
def mirror_details(request, name):
mirror = get_object_or_404(Mirror, name=name)
if not request.user.is_authenticated() and \
@@ -116,13 +145,14 @@ def mirror_details(request, name):
# get each item from checked_urls and supplement with anything in all_urls
# if it wasn't there
all_urls = set(checked_urls).union(all_urls)
- all_urls = sorted(all_urls, key=lambda x: x.url)
+ all_urls = sorted(all_urls, key=attrgetter('url'))
return direct_to_template(request, 'mirrors/mirror_details.html',
{'mirror': mirror, 'urls': all_urls})
+
def status(request):
- bad_timedelta = datetime.timedelta(days=3)
+ bad_timedelta = timedelta(days=3)
status_info = get_mirror_statuses()
urls = status_info['urls']
@@ -137,12 +167,13 @@ def status(request):
context = status_info.copy()
context.update({
- 'good_urls': good_urls,
- 'bad_urls': bad_urls,
+ 'good_urls': sorted(good_urls, key=attrgetter('score')),
+ 'bad_urls': sorted(bad_urls, key=lambda u: u.delay or timedelta.max),
'error_logs': get_mirror_errors(),
})
return direct_to_template(request, 'mirrors/status.html', context)
+
class MirrorStatusJSONEncoder(DjangoJSONEncoder):
'''Base JSONEncoder extended to handle datetime.timedelta and MirrorUrl
serialization. The base class takes care of datetime.datetime types.'''
@@ -150,7 +181,7 @@ class MirrorStatusJSONEncoder(DjangoJSONEncoder):
'delay', 'duration_avg', 'duration_stddev', 'score']
def default(self, obj):
- if isinstance(obj, datetime.timedelta):
+ if isinstance(obj, timedelta):
# always returned as integer seconds
return obj.days * 24 * 3600 + obj.seconds
if hasattr(obj, '__iter__'):
@@ -159,17 +190,20 @@ class MirrorStatusJSONEncoder(DjangoJSONEncoder):
if isinstance(obj, MirrorUrl):
data = dict((attr, getattr(obj, attr))
for attr in self.url_attributes)
- # separate because it isn't on the URL directly
- data['country'] = obj.real_country
+ # get any override on the country attribute first
+ country = obj.real_country
+ data['country'] = unicode(country.name)
+ data['country_code'] = country.code
return data
if isinstance(obj, MirrorProtocol):
return unicode(obj)
return super(MirrorStatusJSONEncoder, self).default(obj)
+
def status_json(request):
status_info = get_mirror_statuses()
data = status_info.copy()
- data['version'] = 2
+ data['version'] = 3
to_json = simplejson.dumps(data, ensure_ascii=False,
cls=MirrorStatusJSONEncoder)
response = HttpResponse(to_json, mimetype='application/json')
diff --git a/public/views.py b/public/views.py
index e031201e..29fec470 100644
--- a/public/views.py
+++ b/public/views.py
@@ -1,4 +1,5 @@
from datetime import datetime
+from operator import attrgetter
from django.conf import settings
from django.contrib.auth.models import User
@@ -6,7 +7,6 @@ from django.db.models import Count, Q
from django.http import Http404
from django.shortcuts import redirect
from django.views.decorators.cache import cache_control
-from django.views.generic import list_detail
from django.views.generic.simple import direct_to_template
from devel.models import MasterKey, PGPSignature
@@ -61,6 +61,16 @@ def donate(request):
@cache_control(max_age=300)
def download(request):
+ mirror_urls = MirrorUrl.objects.select_related('mirror').filter(
+ protocol__default=True,
+ mirror__public=True, mirror__active=True, mirror__isos=True)
+ sort_by = attrgetter('real_country.name', 'mirror.name')
+ mirror_urls = sorted(mirror_urls, key=sort_by)
+ context = {
+ 'releng_iso_url': settings.ISO_LIST_URL,
+ 'releng_pxeboot_url': settings.PXEBOOT_URL,
+ 'mirror_urls': mirror_urls,
+ }
return redirect('//wiki.parabolagnulinux.org/get', permanent=True)
@cache_control(max_age=300)
diff --git a/requirements.txt b/requirements.txt
index aa424ec7..3efc73c2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,6 @@
Django==1.4
-Markdown>=2.1.1
-South>=0.7.4
-pgpdump>=1.1
-pytz>=2012b
+Markdown==2.1.1
+South==0.7.4
+django-countries==1.2
+pgpdump==1.1
+pytz>=2012c
diff --git a/requirements_prod.txt b/requirements_prod.txt
index bb67fc5b..39b9f734 100644
--- a/requirements_prod.txt
+++ b/requirements_prod.txt
@@ -1,8 +1,9 @@
-Django>=1.4
-Markdown>=2.1.1
-South>=0.7.4
-pgpdump>=1.1
-psycopg2>=2.4.4
-pyinotify>=0.9.2
-python-memcached>=1.48
-pytz>=2012b
+Django==1.4
+Markdown==2.1.1
+South==0.7.4
+django-countries==1.2
+pgpdump==1.1
+psycopg2==2.4.5
+pyinotify==0.9.3
+python-memcached==1.48
+pytz>=2012c
diff --git a/settings.py b/settings.py
index 431c5579..1202e836 100644
--- a/settings.py
+++ b/settings.py
@@ -111,6 +111,7 @@ INSTALLED_APPS = (
'django.contrib.markup',
'django.contrib.staticfiles',
'south',
+ 'django_countries',
'main',
'mirrors',
diff --git a/sitestatic/archweb.css b/sitestatic/archweb.css
index 9e531674..44f7169e 100644
--- a/sitestatic/archweb.css
+++ b/sitestatic/archweb.css
@@ -122,6 +122,16 @@ a {
color: #e90;
}
+/* special anchor elements */
+a.headerlink {
+ visibility: hidden;
+ padding-left: 0.5em;
+}
+
+h3:hover > a.headerlink {
+ visibility: visible;
+}
+
/* headings */
h2 {
font-size: 1.5em;
@@ -588,25 +598,6 @@ table#download-torrents .cpu-arch {
text-align: center;
}
-table#download-mirrors {
- width: auto;
- margin-bottom: 1em;
-}
-
- table#download-mirrors td.mirror-country {
- padding-top: 1em;
- }
-
- table#download-mirrors td.mirror-server {
- padding-right: 1em;
- }
-
- table#download-mirrors a {
- display: block;
- float: right;
- width: 4em;
- }
-
/* pkglists/devlists */
table.results {
font-size: 0.846em;
@@ -816,6 +807,28 @@ form#flag-pkg-form input[type=text] {
padding-top: 1em;
}
+ #pkgdetails #pkgfiles li.d {
+ color: #666;
+ }
+
+ #pkgdetails #pkgfiles li.f {
+ }
+
+/* mirror stuff */
+table td.country {
+ white-space: normal;
+}
+
+form#list-generator div ul {
+ list-style: none;
+ display: inline;
+ padding-left: 0;
+}
+
+ form#list-generator div ul li {
+ display: inline;
+ }
+
/* dev/TU biographies */
div#arch-bio-toc {
width: 75%;
@@ -827,33 +840,46 @@ div#arch-bio-toc {
white-space: nowrap;
}
-table.arch-bio-entry td.pic {
- vertical-align: top;
- padding-right: 15px;
- padding-top: 10px;
+table.arch-bio-entry {
+ width: 75%;
+ min-width: 640px;
+ margin: 0 auto;
}
- table.arch-bio-entry td.pic img {
- padding: 4px;
- border: 1px solid #ccc;
+ table.arch-bio-entry td.pic {
+ vertical-align: top;
+ padding-right: 15px;
+ padding-top: 2.25em;
}
-table.arch-bio-entry table.bio {
- margin-bottom: 2em;
-}
+ table.arch-bio-entry td.pic img {
+ padding: 4px;
+ border: 1px solid #ccc;
+ }
- table.arch-bio-entry table.bio th {
- text-align: left;
- padding-right: 0.5em;
- vertical-align: top;
- white-space: nowrap;
+ table.arch-bio-entry td h3 {
+ border-bottom: 1px dotted #ccc;
+ margin-bottom: 0.5em;
}
- table.arch-bio-entry table.bio td {
- width: 100%;
- padding-bottom: 0.25em;
+ table.arch-bio-entry table.bio {
+ margin-bottom: 2em;
}
+ table.arch-bio-entry table.bio th {
+ color: #666;
+ font-weight: normal;
+ text-align: right;
+ padding-right: 0.5em;
+ vertical-align: top;
+ white-space: nowrap;
+ }
+
+ table.arch-bio-entry table.bio td {
+ width: 100%;
+ padding-bottom: 0.25em;
+ }
+
/* dev: login/out */
table#dev-login {
width: auto;
diff --git a/templates/devel/clock.html b/templates/devel/clock.html
index f906800a..0cad9d1b 100644
--- a/templates/devel/clock.html
+++ b/templates/devel/clock.html
@@ -32,7 +32,7 @@
<td><a href="mailto:{{ dev.email }}">{{ dev.get_full_name }}</a></td>
<td>{{ dev.username }}</td>
<td>{{ dev.userprofile.alias }}</td>
- <td>{{ dev.userprofile.location }}</td>
+ <td>{% if dev.userprofile.country %}<img src="{{ dev.userprofile.country.flag }}" alt="{{ dev.userprofile.country.name }}"/> {% endif %}{{ dev.userprofile.location }}</td>
<td>{{ dev.userprofile.time_zone }}</td>
<td>{{ utc_now|timezone:dev.userprofile.time_zone|date:"Y-m-d H:i T" }}</td>
</tr>
diff --git a/templates/mirrors/mirror_details.html b/templates/mirrors/mirror_details.html
index 507b69bf..65f71cb7 100644
--- a/templates/mirrors/mirror_details.html
+++ b/templates/mirrors/mirror_details.html
@@ -21,7 +21,7 @@
</tr>
<tr>
<th>Country:</th>
- <td>{{ mirror.country }}</td>
+ <td>{% if mirror.country %}<img src="{{ mirror.country.flag }}" alt=""/> {% endif %}{{ mirror.country.name|default:'Worldwide' }}</td>
</tr>
<tr>
<th>Has ISOs:</th>
diff --git a/templates/mirrors/mirrorlist.txt b/templates/mirrors/mirrorlist.txt
index b91c52a2..3ea89417 100644
--- a/templates/mirrors/mirrorlist.txt
+++ b/templates/mirrors/mirrorlist.txt
@@ -8,6 +8,6 @@ content right, and then go back later to fix it all up.
## Generated on {% now "Y-m-d" %}
##{% for mirror_url in mirror_urls %}{% ifchanged %}
-## {{ mirror_url.real_country }}{% endifchanged %}
+## {{ mirror_url.real_country.name|default:'Worldwide' }}{% endifchanged %}
#Server = {{ mirror_url.url}}$repo/os/$arch{% endfor %}
{% endautoescape %}
diff --git a/templates/mirrors/index.html b/templates/mirrors/mirrorlist_generate.html
index 454fb201..35d84ddc 100644
--- a/templates/mirrors/index.html
+++ b/templates/mirrors/mirrorlist_generate.html
@@ -36,7 +36,7 @@
mirror list and used to pre-order the mirrors.</p>
<form id="list-generator" method="get">
- {{ mirrorlist_form.as_p }}
+ {{ mirrorlist_form.as_div }}
<p><label></label> <input type="submit" value="Generate List" /></p>
</form>
</div>
diff --git a/templates/mirrors/mirrorlist_status.txt b/templates/mirrors/mirrorlist_status.txt
index 5bf94287..34ed8fdc 100644
--- a/templates/mirrors/mirrorlist_status.txt
+++ b/templates/mirrors/mirrorlist_status.txt
@@ -7,7 +7,8 @@ content right, and then go back later to fix it all up.
## Parabola repository mirrorlist
## Sorted by mirror score from mirror status page
## Generated on {% now "Y-m-d" %}
+##
{% for mirror_url in mirror_urls %}
-## Score: {{ mirror_url.score|floatformat:1|default:'unknown' }}, {{ mirror_url.real_country }}
+## Score: {{ mirror_url.score|floatformat:1|default:'unknown' }}, {{ mirror_url.real_country.name|default:'Worldwide' }}
#Server = {{ mirror_url.url}}$repo/os/$arch{% endfor %}
{% endautoescape %}
diff --git a/templates/mirrors/mirrors.html b/templates/mirrors/mirrors.html
index 50f50bde..241c3557 100644
--- a/templates/mirrors/mirrors.html
+++ b/templates/mirrors/mirrors.html
@@ -26,15 +26,15 @@
<tr class="{% cycle 'odd' 'even' %}">
<td><a href="{{ mirror.get_absolute_url }}"
title="Mirror details for {{ mirror.name }}">{{ mirror.name }}</a></td>
- <td>{{mirror.get_tier_display}}</td>
- <td>{{mirror.country}}</td>
- <td>{{mirror.isos|yesno|capfirst}}</td>
- <td class="wrap">{{mirror.supported_protocols|join:", "}}</td>
+ <td>{{ mirror.get_tier_display }}</td>
+ <td>{% if mirror.country %}<img src="{{ mirror.country.flag }}" alt=""/> {% endif %}{{ mirror.country.name }}</td>
+ <td>{{ mirror.isos|yesno|capfirst }}</td>
+ <td class="wrap">{{ mirror.supported_protocols|join:", " }}</td>
{% if user.is_authenticated %}
- <td>{{mirror.public|yesno|capfirst}}</td>
- <td>{{mirror.active|yesno|capfirst}}</td>
- <td>{{mirror.admin_email}}</td>
- <td class="wrap">{{mirror.notes|linebreaks}}</td>
+ <td>{{ mirror.public|yesno|capfirst }}</td>
+ <td>{{ mirror.active|yesno|capfirst }}</td>
+ <td>{{ mirror.admin_email }}</td>
+ <td class="wrap">{{ mirror.notes|linebreaks }}</td>
{% endif %}
</tr>
{% endfor %}
diff --git a/templates/mirrors/status.html b/templates/mirrors/status.html
index cce6d983..e6861bfb 100644
--- a/templates/mirrors/status.html
+++ b/templates/mirrors/status.html
@@ -18,10 +18,6 @@
<ul>
<li><em>Mirror URL:</em> Mirrors are checked on a per-URL basis. If
both FTP and HTTP access are provided, both will be listed here.</li>
- <li><em>Last Sync:</em> The timestamp retrieved from the
- <tt>lastsync</tt> file on the mirror. If this file could not be
- retrieved or contained data we didn't recognize, this column will show
- 'unknown'.</li>
<li><em>Completion %:</em> The number of mirror checks that have
successfully connected and disconnected from the given URL. If this is
below 100%, the mirror may be unreliable.</li>
@@ -92,8 +88,8 @@
{% spaceless %}<tr class="{% cycle 'odd' 'even' %}">
<td>{{ log.url__url }}</td>
<td>{{ log.url__protocol__protocol }}</td>
- <td>{{ log.country }}</td>
- <td>{{ log.error }}</td>
+ <td class="country">{% if log.country %}<img src="{{ log.country.flag }}" alt=""/> {% endif %}{{ log.country.name }}</td>
+ <td class="wrap">{{ log.error }}</td>
<td>{{ log.last_occurred|date:'Y-m-d H:i' }}</td>
<td>{{ log.error_count }}</td>
</tr>
@@ -107,11 +103,11 @@
<script type="text/javascript" src="{% static "archweb.js" %}"></script>
<script type="text/javascript">
$(document).ready(function() {
- var headers = { 5: { sorter: 'duration' }, 6: { sorter: 'mostlydigit' }, 7: { sorter: 'mostlydigit' }, 8: { sorter: 'mostlydigit' } };
+ var headers = { 4: { sorter: 'duration' }, 5: { sorter: 'mostlydigit' }, 6: { sorter: 'mostlydigit' }, 7: { sorter: 'mostlydigit' } };
$("#outofsync_mirrors:has(tbody tr)").tablesorter(
- {widgets: ['zebra'], sortList: [[3,1]], headers: headers });
+ {widgets: ['zebra'], sortList: [[4,0]], headers: headers });
$("#successful_mirrors:has(tbody tr)").tablesorter(
- {widgets: ['zebra'], sortList: [[8,0]], headers: headers });
+ {widgets: ['zebra'], sortList: [[7,0]], headers: headers });
$("#errorlog_mirrors:has(tbody tr)").tablesorter(
{widgets: ['zebra'], sortList: [[4,1], [5,1]]});
});
diff --git a/templates/mirrors/status_table.html b/templates/mirrors/status_table.html
index bd70115c..1961d222 100644
--- a/templates/mirrors/status_table.html
+++ b/templates/mirrors/status_table.html
@@ -5,7 +5,6 @@
<th>Mirror URL</th>
<th>Protocol</th>
<th>Country</th>
- <th>Last Sync</th>
<th>Completion %</th>
<th>μ Delay (hh:mm)</th>
<th>μ Duration (secs)</th>
@@ -18,8 +17,7 @@
{% spaceless %}<tr class="{% cycle 'odd' 'even' %}">
<td>{{ m_url.url }}</td>
<td>{{ m_url.protocol }}</td>
- <td>{{ m_url.real_country }}</td>
- <td>{{ m_url.last_sync|date:'Y-m-d H:i'|default:'unknown' }}</td>
+ <td class="country">{% if m_url.real_country %}<img src="{{ m_url.real_country.flag }}" alt=""/> {% endif %}{{ m_url.real_country.name }}</td>
<td>{{ m_url.completion_pct|percentage:1 }}</td>
<td>{{ m_url.delay|duration|default:'unknown' }}</td>
<td>{{ m_url.duration_avg|floatformat:2 }}</td>
diff --git a/templates/packages/details.html b/templates/packages/details.html
index 8e4b2bb0..0369aa96 100644
--- a/templates/packages/details.html
+++ b/templates/packages/details.html
@@ -10,7 +10,7 @@
{% block content %}
<div id="pkgdetails" class="box">
- <h2>Package Details: {{ pkg.pkgname }} {{ pkg.full_version }}</h2>
+ <h2>{{ pkg.pkgname }} {{ pkg.full_version }}</h2>
<div id="detailslinks" class="listing">
<div id="actionlist">
diff --git a/templates/packages/files.html b/templates/packages/files.html
index 8cf6738d..46553b25 100644
--- a/templates/packages/files.html
+++ b/templates/packages/files.html
@@ -5,12 +5,12 @@
{% block content %}
<div id="pkgdetails" class="box">
- <h2>Package File List: {{ pkg.pkgname }} {{ pkg.full_version }}</h2>
- <div id="metadata">
- <p><a href="{{ pkg.get_absolute_url }}">Back to Package</a></p>
+ <h2>{{ pkg.pkgname }} {{ pkg.full_version }} File List</h2>
+ <div id="metadata"><div id="pkgfiles">
<p>Package has {{ files_count }} file{{ files_count|pluralize }} and {{ dir_count }} director{{ dir_count|pluralize:"y,ies" }}.</p>
+ <p><a href="{{ pkg.get_absolute_url }}">Back to Package</a></p>
{% include "packages/files_list.html" %}
- </div>
+ </div></div>
</div>
{% endblock %}
diff --git a/templates/packages/files_list.html b/templates/packages/files_list.html
index 156d8588..93a2c847 100644
--- a/templates/packages/files_list.html
+++ b/templates/packages/files_list.html
@@ -6,7 +6,7 @@ of the package; it may be out of date.</p>
{% if files|length %}
<ul>
{% for file in files %}
-<li>{{ file.directory }}{{ file.filename|default:'' }}</li>{% endfor %}
+<li class="{% if file.is_directory %}d{% else %}f{% endif %}">{{ file.directory }}{{ file.filename|default:'' }}</li>{% endfor %}
</ul>
{% else %}
<p class="message">Package has no files.</p>
diff --git a/templates/public/developer_list.html b/templates/public/developer_list.html
index 83c62952..376ab433 100644
--- a/templates/public/developer_list.html
+++ b/templates/public/developer_list.html
@@ -17,12 +17,10 @@
<img src="{{ prof.picture.url }}" height="125" width="125" alt="Image for {{ prof.alias }}"/>
</td>
<td>
- <a name="{{ dev.username }}"></a>
+ <h3>{{ dev.get_full_name }}{% if prof.latin_name %} ({{ prof.latin_name}}){% endif %}
+ <a class="headerlink" name="{{ dev.username }}" id="{{ dev.username }}" href="#{{ dev.username }}" title="Permalink">¶</a></h3>
<table class="bio bio-{{ dev.username }}">
<tr>
- <th>Name:</th>
- <td>{{ dev.get_full_name }}{% if prof.latin_name %} ({{ prof.latin_name}}){% endif %}</td>
- </tr><tr>
<th>Alias:</th>
<td>{{ prof.alias }}</td>
</tr><tr>
@@ -51,7 +49,7 @@
<td>{% if prof.yob %}{{ prof.yob }}{% endif %}</td>
</tr><tr>
<th>Location:</th>
- <td>{{ prof.location }}</td>
+ <td>{% if dev.userprofile.country %}<img src="{{ dev.userprofile.country.flag }}" alt="{{ dev.userprofile.country.name }}"/> {% endif %}{{ prof.location }}</td>
</tr><tr>
<th>Languages:</th>
<td>{{ prof.languages }}</td>