From dcbee21c1ba281b061db302056c771936925c824 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 21 Jun 2011 08:56:50 -0500 Subject: Nicer formatting of PGP key display value Signed-off-by: Dan McGee --- main/templatetags/pgp.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'main') diff --git a/main/templatetags/pgp.py b/main/templatetags/pgp.py index d9126dbd..956de892 100644 --- a/main/templatetags/pgp.py +++ b/main/templatetags/pgp.py @@ -3,6 +3,17 @@ register = template.Library() +def format_key(key_id): + print len(key_id) + if len(key_id) in (8, 20): + return u'0x%s' % key_id + elif len(key_id) == 40: + # normal display format is 5 groups of 4 hex chars seperated by spaces, + # double space, then 5 more groups of 4 hex chars + split = tuple(key_id[i:i+4] for i in range(0, 40, 4)) + return u'%s  %s' % (' '.join(split[0:5]), ' '.join(split[5:10])) + return u'0x%s' % key_id + @register.simple_tag def pgp_key_link(key_id): if not key_id: @@ -10,10 +21,10 @@ def pgp_key_link(key_id): # Something like 'pgp.mit.edu:11371' pgp_server = getattr(settings, 'PGP_SERVER', None) if not pgp_server: - return "0x%s" % key_id + return format_key(key_id) url = 'http://%s/pks/lookup?op=vindex&fingerprint=on&exact=on&search=0x%s' % \ (pgp_server, key_id) - values = (url, key_id, key_id) - return '0x%s' % values + values = (url, key_id, format_key(key_id)) + return '%s' % values # vim: set ts=4 sw=4 et: -- cgit v1.2.3-54-g00ecf From 388973d6fd082148c85db0df44e0ee5ed3b6a54b Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 23 Jun 2011 18:48:39 -0500 Subject: Revert "Remove unused flagged() manager method" Far from unneeded, this is used on the developer dashboard. Silly me. Document this fact as well in the code so we don't screw it up again. This reverts commit 2a44855556531a27e949884d4084c6e5d37082e1. --- main/models.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'main') diff --git a/main/models.py b/main/models.py index a5d6c42e..05e63fed 100644 --- a/main/models.py +++ b/main/models.py @@ -73,6 +73,10 @@ def incomplete(self): return self.filter(todolistpkg__complete=False).distinct() class PackageManager(models.Manager): + def flagged(self): + """Used by dev dashboard.""" + return self.filter(flag_date__isnull=False) + def normal(self): return self.select_related('arch', 'repo') -- cgit v1.2.3-54-g00ecf From 55f6ad0c95323a5bfeca2c322918d21f413d1075 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 23 Jun 2011 20:19:49 -0500 Subject: Set up queries for staging repos This treats repo.staging special in much the way we already have to treat repo.testing as special. Signed-off-by: Dan McGee --- main/models.py | 17 +++++++++++------ packages/views.py | 13 ++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) (limited to 'main') diff --git a/main/models.py b/main/models.py index 05e63fed..e0017069 100644 --- a/main/models.py +++ b/main/models.py @@ -226,6 +226,7 @@ def get_requiredby(self): groupby(requiredby, lambda x: x.pkg.id)] # find another package by this name in the opposite testing setup + # TODO: figure out staging exclusions too if not Package.objects.filter(pkgname=self.pkgname, arch=self.arch).exclude(id=self.id).exclude( repo__testing=self.repo.testing).exists(): @@ -241,7 +242,8 @@ def get_requiredby(self): dep = dep_pkgs[0] if len(dep_pkgs) > 1: dep_pkgs = [d for d in dep_pkgs - if d.pkg.repo.testing == self.repo.testing] + if d.pkg.repo.testing == self.repo.testing and + d.pkg.repo.staging = self.repo.staging] if len(dep_pkgs) > 0: dep = dep_pkgs[0] trimmed.append(dep) @@ -273,7 +275,8 @@ def get_depends(self): # grab the first though in case we fail pkg = pkgs[0] # prevents yet more DB queries, these lists should be short - pkgs = [p for p in pkgs if p.repo.testing == self.repo.testing] + pkgs = [p for p in pkgs if p.repo.testing == self.repo.testing + and p.repo.staging = self.repo.staging] if len(pkgs) > 0: pkg = pkgs[0] deps.append({'dep': dep, 'pkg': pkg}) @@ -293,7 +296,8 @@ def base_package(self): # this package might be split across repos? just find one # that matches the correct [testing] repo flag pkglist = Package.objects.filter(arch=self.arch, - repo__testing=self.repo.testing, pkgname=self.pkgbase) + repo__testing=self.repo.testing, + repo__staging=self.repo.staging, pkgname=self.pkgbase) if len(pkglist) > 0: return pkglist[0] return None @@ -303,11 +307,12 @@ def split_packages(self): Return all packages that were built with this one (e.g. share a pkgbase value). The package this method is called on will never be in the list, and we will never return a package that does not have the same - repo.testing flag. For any non-split packages, the return value will be - an empty list. + repo.testing and repo.staging flags. For any non-split packages, the + return value will be an empty list. """ return Package.objects.filter(arch__in=self.applicable_arches(), - repo__testing=self.repo.testing, pkgbase=self.pkgbase).exclude(id=self.id) + repo__testing=self.repo.testing, repo__staging=self.repo.staging, + pkgbase=self.pkgbase).exclude(id=self.id) def is_same_version(self, other): 'is this package similar, name and version-wise, to another' diff --git a/packages/views.py b/packages/views.py index 02b9f93b..01d01e20 100644 --- a/packages/views.py +++ b/packages/views.py @@ -118,7 +118,8 @@ def details(request, name='', repo='', arch=''): arches.extend(Arch.objects.filter(agnostic=True)) repo = get_object_or_404(Repo, name__iexact=repo) pkgs = Package.objects.normal().filter(pkgbase=name, - repo__testing=repo.testing, arch__in=arches).order_by('pkgname') + repo__testing=repo.testing, repo__staging=repo.staging, + arch__in=arches).order_by('pkgname') if len(pkgs) == 0: raise Http404 context = { @@ -343,8 +344,8 @@ def unflag_all(request, name, repo, arch): pkg = get_object_or_404(Package, pkgname=name, repo__name__iexact=repo, arch__name=arch) # find all packages from (hopefully) the same PKGBUILD - pkgs = Package.objects.filter( - pkgbase=pkg.pkgbase, repo__testing=pkg.repo.testing) + pkgs = Package.objects.filter(pkgbase=pkg.pkgbase, + repo__testing=pkg.repo.testing, repo__staging=pkg.repo.staging) pkgs.update(flag_date=None) return redirect(pkg) @@ -416,7 +417,8 @@ def flag(request, name, repo, arch): # find all packages from (hopefully) the same PKGBUILD pkgs = Package.objects.normal().filter( pkgbase=pkg.pkgbase, flag_date__isnull=True, - repo__testing=pkg.repo.testing).order_by( + repo__testing=pkg.repo.testing, + repo__staging=pkg.repo.staging).order_by( 'pkgname', 'repo__name', 'arch__name') if request.POST: @@ -471,7 +473,8 @@ def flag_confirmed(request, name, repo, arch): pkgname=name, repo__name__iexact=repo, arch__name=arch) pkgs = Package.objects.normal().filter( pkgbase=pkg.pkgbase, flag_date=pkg.flag_date, - repo__testing=pkg.repo.testing).order_by( + repo__testing=pkg.repo.testing, + repo__staging=pkg.repo.staging).order_by( 'pkgname', 'repo__name', 'arch__name') context = {'package': pkg, 'packages': pkgs} -- cgit v1.2.3-54-g00ecf From 5bf28d1cabc54dfa68ff64804a31ead419780fdf Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 23 Jun 2011 20:24:15 -0500 Subject: Add Package.in_staging method Signed-off-by: Dan McGee --- main/models.py | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'main') diff --git a/main/models.py b/main/models.py index e0017069..b52c45fb 100644 --- a/main/models.py +++ b/main/models.py @@ -332,6 +332,17 @@ def in_testing(self): except Package.DoesNotExist: return None + def in_staging(self): + '''attempt to locate this package in a staging repo; if we are in + a staging repo we will always return None.''' + if self.repo.staging: + return None + try: + return Package.objects.normal().get(repo__staging=True, + pkgname=self.pkgname, arch=self.arch) + except Package.DoesNotExist: + return None + def elsewhere(self): '''attempt to locate this package anywhere else, regardless of architecture or repository. Excludes this package from the list.''' -- cgit v1.2.3-54-g00ecf From c584ffc9b6bc9bdab1616b096ccaa1c1cd762f69 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 23 Jun 2011 20:30:31 -0500 Subject: Fix syntax errors, == not = Signed-off-by: Dan McGee --- main/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/models.py b/main/models.py index b52c45fb..9010817b 100644 --- a/main/models.py +++ b/main/models.py @@ -243,7 +243,7 @@ def get_requiredby(self): if len(dep_pkgs) > 1: dep_pkgs = [d for d in dep_pkgs if d.pkg.repo.testing == self.repo.testing and - d.pkg.repo.staging = self.repo.staging] + d.pkg.repo.staging == self.repo.staging] if len(dep_pkgs) > 0: dep = dep_pkgs[0] trimmed.append(dep) @@ -276,7 +276,7 @@ def get_depends(self): pkg = pkgs[0] # prevents yet more DB queries, these lists should be short pkgs = [p for p in pkgs if p.repo.testing == self.repo.testing - and p.repo.staging = self.repo.staging] + and p.repo.staging == self.repo.staging] if len(pkgs) > 0: pkg = pkgs[0] deps.append({'dep': dep, 'pkg': pkg}) -- cgit v1.2.3-54-g00ecf From 5e85c5ac9ed09551d65ec07767094770d248f3b1 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 29 Jun 2011 10:52:30 -0500 Subject: Move set_created_field() to shared utils class Signed-off-by: Dan McGee --- main/utils.py | 10 ++++++++++ packages/models.py | 10 ++-------- releng/models.py | 13 +++---------- 3 files changed, 15 insertions(+), 18 deletions(-) (limited to 'main') diff --git a/main/utils.py b/main/utils.py index 12d12503..2ca69bcb 100644 --- a/main/utils.py +++ b/main/utils.py @@ -2,6 +2,9 @@ import cPickle as pickle except ImportError: import pickle + +from datetime import datetime + from django.core.cache import cache from django.utils.hashcompat import md5_constructor @@ -81,4 +84,11 @@ def retrieve_latest(sender): pass return None +def set_created_field(sender, **kwargs): + '''This will set the 'created' field on any object to datetime.utcnow() if + it is unset. For use as a pre_save signal handler.''' + obj = kwargs['instance'] + if hasattr(obj, 'created') and not obj.created: + obj.created = datetime.utcnow() + # vim: set ts=4 sw=4 et: diff --git a/packages/models.py b/packages/models.py index a950bddb..0983c642 100644 --- a/packages/models.py +++ b/packages/models.py @@ -1,9 +1,9 @@ -from datetime import datetime - from django.db import models from django.db.models.signals import pre_save, post_save from django.contrib.auth.models import User +from main.utils import set_created_field + class PackageRelation(models.Model): ''' Represents maintainership (or interest) in a package by a given developer. @@ -112,12 +112,6 @@ def remove_inactive_maintainers(sender, instance, created, **kwargs): type=PackageRelation.MAINTAINER) maint_relations.delete() -def set_created_field(sender, **kwargs): - # We use this same callback for both Isos and Tests - obj = kwargs['instance'] - if not obj.created: - obj.created = datetime.utcnow() - post_save.connect(remove_inactive_maintainers, sender=User, dispatch_uid="packages.models") pre_save.connect(set_created_field, sender=PackageRelation, diff --git a/releng/models.py b/releng/models.py index 07ede1c5..5510db6a 100644 --- a/releng/models.py +++ b/releng/models.py @@ -1,6 +1,7 @@ -from datetime import datetime - from django.db import models +from django.db.models.signals import pre_save + +from main.utils import set_created_field class IsoOption(models.Model): name = models.CharField(max_length=200) @@ -104,14 +105,6 @@ class Test(models.Model): success = models.BooleanField() comments = models.TextField(null=True, blank=True) -def set_created_field(sender, **kwargs): - # We use this same callback for both Isos and Tests - obj = kwargs['instance'] - if not obj.created: - obj.created = datetime.utcnow() - -from django.db.models.signals import pre_save - pre_save.connect(set_created_field, sender=Iso, dispatch_uid="releng.models") pre_save.connect(set_created_field, sender=Test, -- cgit v1.2.3-54-g00ecf From e37d465c4eb03259b3ce0c89e43c2c21badb0063 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 1 Jul 2011 18:59:28 -0500 Subject: Allow more lenient data entry for PGP key field Don't allow the max_length parameter to make it through to the HTML form, silently cutting off HTML cut and pastes. Trim out spaces automatically, as well as '0x' and '2048R/' type prefixes. Signed-off-by: Dan McGee --- .../0051_auto__chg_field_userprofile_pgp_key.py | 160 +++++++++++++++++++++ main/models.py | 21 ++- 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 main/migrations/0051_auto__chg_field_userprofile_pgp_key.py (limited to 'main') diff --git a/main/migrations/0051_auto__chg_field_userprofile_pgp_key.py b/main/migrations/0051_auto__chg_field_userprofile_pgp_key.py new file mode 100644 index 00000000..6b8abf6e --- /dev/null +++ b/main/migrations/0051_auto__chg_field_userprofile_pgp_key.py @@ -0,0 +1,160 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + db.alter_column('user_profiles', 'pgp_key', self.gf('main.models.PGPKeyField')(max_length=40, null=True)) + + + def backwards(self, orm): + db.alter_column('user_profiles', 'pgp_key', self.gf('django.db.models.fields.CharField')(max_length=40, null=True)) + + 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'}) + }, + 'main.arch': { + 'Meta': {'ordering': "['name']", 'object_name': 'Arch', 'db_table': "'arches'"}, + 'agnostic': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + 'main.donor': { + 'Meta': {'ordering': "['name']", 'object_name': 'Donor', 'db_table': "'donors'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'main.package': { + 'Meta': {'ordering': "('pkgname',)", 'object_name': 'Package', 'db_table': "'packages'"}, + 'arch': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'packages'", 'to': "orm['main.Arch']"}), + 'build_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'compressed_size': ('main.models.PositiveBigIntegerField', [], {}), + 'epoch': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'files_last_update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'flag_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'installed_size': ('main.models.PositiveBigIntegerField', [], {}), + 'last_update': ('django.db.models.fields.DateTimeField', [], {}), + 'packager': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'packager_str': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'pkgbase': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'pkgdesc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'pkgname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'pkgrel': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'pkgver': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'repo': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'packages'", 'to': "orm['main.Repo']"}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}) + }, + 'main.packagedepend': { + 'Meta': {'object_name': 'PackageDepend', 'db_table': "'package_depends'"}, + 'depname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'depvcmp': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}) + }, + 'main.packagefile': { + 'Meta': {'object_name': 'PackageFile', 'db_table': "'package_files'"}, + 'directory': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_directory': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}) + }, + 'main.repo': { + 'Meta': {'ordering': "['name']", 'object_name': 'Repo', 'db_table': "'repos'"}, + 'bugs_category': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + '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'}) + }, + 'main.signoff': { + 'Meta': {'object_name': 'Signoff'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'packager': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}), + 'pkgrel': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'pkgver': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'main.todolist': { + 'Meta': {'object_name': 'Todolist', 'db_table': "'todolists'"}, + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'date_added': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'main.todolistpkg': { + 'Meta': {'unique_together': "(('list', 'pkg'),)", 'object_name': 'TodolistPkg', 'db_table': "'todolist_pkgs'"}, + 'complete': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Todolist']"}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}) + }, + 'main.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'}), + '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'}), + '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': ('main.models.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'}) + } + } + + complete_apps = ['main'] diff --git a/main/models.py b/main/models.py index 9010817b..2f549081 100644 --- a/main/models.py +++ b/main/models.py @@ -22,6 +22,25 @@ def formfield(self, **kwargs): defaults.update(kwargs) return super(PositiveBigIntegerField, self).formfield(**defaults) +class PGPKeyField(models.CharField): + _south_introspects = True + + def to_python(self, value): + if value == '': + return None + value = super(PGPKeyField, self).to_python(value) + # remove all spaces + value = value.replace(' ', '') + # prune prefixes, either 0x or 2048R/ type + if value.startswith('0x'): + value = value[2:] + value = value.split('/')[-1] + return value + + def formfield(self, **kwargs): + # override so we don't set max_length form field attribute + return models.Field.formfield(self, **kwargs) + def validate_pgp_key_length(value): if len(value) not in (8, 16, 40): raise ValidationError( @@ -45,7 +64,7 @@ class UserProfile(models.Model): max_length=50, help_text="Required field") other_contact = models.CharField(max_length=100, null=True, blank=True) - pgp_key = models.CharField(max_length=40, null=True, blank=True, + pgp_key = PGPKeyField(max_length=40, null=True, blank=True, verbose_name="PGP key", validators=[RegexValidator(r'^[0-9A-F]+$', "Ensure this value consists of only hex characters.", 'hex_char'), validate_pgp_key_length], -- cgit v1.2.3-54-g00ecf From c5308b75837dfcbb851bcf9e93553c72e4b8996e Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 29 Jun 2011 12:05:07 -0500 Subject: Recent updates refactor Pull out a few helpful objects and functions for use later elsewhere. Signed-off-by: Dan McGee --- main/utils.py | 35 +++++++++++++++++++++++++++++++++++ public/utils.py | 38 +++++++++++++------------------------- 2 files changed, 48 insertions(+), 25 deletions(-) (limited to 'main') diff --git a/main/utils.py b/main/utils.py index 2ca69bcb..81f689e7 100644 --- a/main/utils.py +++ b/main/utils.py @@ -91,4 +91,39 @@ def set_created_field(sender, **kwargs): if hasattr(obj, 'created') and not obj.created: obj.created = datetime.utcnow() +def groupby_preserve_order(iterable, keyfunc): + '''Take an iterable and regroup using keyfunc to determine whether items + belong to the same group. The order of the iterable is preserved and + similar keys do not have to be consecutive. This means the earliest + occurrence of a given key will determine the order of the lists in the + returned list.''' + seen_keys = {} + result = [] + for item in iterable: + key = keyfunc(item) + + group = seen_keys.get(key, None) + if group is None: + group = [] + seen_keys[key] = group + result.append(group) + + group.append(item) + + return result + +class PackageStandin(object): + '''Resembles a Package object, and has a few of the same fields, but is + really a link to a pkgbase that has no package with matching pkgname.''' + def __init__(self, package): + self.package = package + self.pkgname = package.pkgbase + + def __getattr__(self, name): + return getattr(self.package, name) + + def get_absolute_url(self): + return '/packages/%s/%s/%s/' % ( + self.repo.name.lower(), self.arch.name, self.pkgbase) + # vim: set ts=4 sw=4 et: diff --git a/public/utils.py b/public/utils.py index 0be3ebaa..5900c674 100644 --- a/public/utils.py +++ b/public/utils.py @@ -1,7 +1,7 @@ from operator import attrgetter from main.models import Arch, Package, Repo -from main.utils import cache_function +from main.utils import cache_function, groupby_preserve_order, PackageStandin class RecentUpdate(object): def __init__(self, packages): @@ -35,18 +35,12 @@ def package_links(self): for package in self.packages: yield package else: - # time to fake out the template, this is a tad dirty - arches = set(pkg.arch for pkg in self.others) - for arch in arches: - url = '/packages/%s/%s/%s/' % ( - self.repo.name.lower(), arch.name, self.pkgbase) - package_stub = { - 'pkgname': self.pkgbase, - 'arch': arch, - 'repo': self.repo, - 'get_absolute_url': url - } - yield package_stub + # fake out the template- this is slightly hacky but yields one + # 'package-like' object per arch which is what the normal loop does + arches = set() + for package in self.others: + if package.arch not in arches and not arches.add(package.arch): + yield PackageStandin(package) @cache_function(300) def get_recent_updates(number=15): @@ -59,20 +53,14 @@ def get_recent_updates(number=15): for arch in Arch.objects.all(): pkgs += list(Package.objects.normal().filter( arch=arch).order_by('-last_update')[:fetch]) - pkgs.sort(key=attrgetter('last_update')) + pkgs.sort(key=attrgetter('last_update'), reverse=True) - updates = [] - while len(pkgs) > 0: - pkg = pkgs.pop() - - in_group = lambda x: pkg.repo == x.repo and pkg.pkgbase == x.pkgbase - samepkgs = [other for other in pkgs if in_group(other)] - samepkgs.append(pkg) + same_pkgbase_key = lambda x: (x.repo.name, x.pkgbase) + grouped = groupby_preserve_order(pkgs, same_pkgbase_key) - # now remove all the packages we just pulled out - pkgs = [other for other in pkgs if other not in samepkgs] - - update = RecentUpdate(samepkgs) + updates = [] + for group in grouped: + update = RecentUpdate(group) updates.append(update) return updates[:number] -- cgit v1.2.3-54-g00ecf From f95abca269aec1409ec1e57de4c6cb5ba1da6369 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 6 Jul 2011 12:05:19 -0500 Subject: Refactor code to use new signoff model This moves signoff creation and display to the new packages.Signoff model. Signed-off-by: Dan McGee --- main/models.py | 14 ++--- packages/models.py | 2 + packages/views.py | 120 ++++++++++++++++++++++++++++++--------- templates/packages/signoffs.html | 25 ++++---- 4 files changed, 115 insertions(+), 46 deletions(-) (limited to 'main') diff --git a/main/models.py b/main/models.py index 2f549081..473144da 100644 --- a/main/models.py +++ b/main/models.py @@ -6,6 +6,7 @@ from main.utils import cache_function, make_choice from packages.models import PackageRelation +from packages.models import Signoff as PackageSignoff from datetime import datetime from itertools import groupby @@ -206,16 +207,13 @@ def maintainers(self): @property def signoffs(self): - if 'signoffs_cache' in dir(self): - return self.signoffs_cache - self.signoffs_cache = list(Signoff.objects.filter( - pkg=self, - pkgver=self.pkgver, - pkgrel=self.pkgrel)) - return self.signoffs_cache + return PackageSignoff.objects.select_related('user').filter( + pkgbase=self.pkgbase, pkgver=self.pkgver, pkgrel=self.pkgrel, + epoch=self.epoch, arch=self.arch, repo=self.repo) def approved_for_signoff(self): - return len(self.signoffs) >= 2 + count = self.signoffs.filter(revoked__isnull=True).count() + return count >= PackageSignoff.REQUIRED @cache_function(300) def applicable_arches(self): diff --git a/packages/models.py b/packages/models.py index 55725e8e..7ae2d57a 100644 --- a/packages/models.py +++ b/packages/models.py @@ -55,6 +55,8 @@ class Signoff(models.Model): revoked = models.DateTimeField(null=True) comments = models.TextField(null=True, blank=True) + REQUIRED = 2 + @property def packages(self): # TODO: delayed import to avoid circular reference diff --git a/packages/views.py b/packages/views.py index d12583f0..3d9032e6 100644 --- a/packages/views.py +++ b/packages/views.py @@ -8,7 +8,7 @@ from django.core.serializers.json import DjangoJSONEncoder from django.db.models import Q from django.http import HttpResponse, Http404 -from django.shortcuts import get_object_or_404, redirect +from django.shortcuts import get_object_or_404, get_list_or_404, redirect from django.template import loader, Context from django.utils import simplejson from django.views.decorators.cache import never_cache @@ -18,15 +18,16 @@ from django.views.generic.simple import direct_to_template from datetime import datetime +from operator import attrgetter import string from urllib import urlencode -from main.models import Package, PackageFile -from main.models import Arch, Repo, Signoff -from main.utils import make_choice +from main.models import Package, PackageFile, Arch, Repo +from main.utils import make_choice, groupby_preserve_order, PackageStandin from mirrors.models import MirrorUrl -from .models import PackageRelation, PackageGroup -from .utils import get_group_info, get_differences_info, get_wrong_permissions +from .models import PackageRelation, PackageGroup, Signoff +from .utils import (get_group_info, get_differences_info, + get_wrong_permissions, get_current_signoffs) class PackageJSONEncoder(DjangoJSONEncoder): pkg_attributes = [ 'pkgname', 'pkgbase', 'repo', 'arch', 'pkgver', @@ -349,38 +350,101 @@ def unflag_all(request, name, repo, arch): pkgs.update(flag_date=None) return redirect(pkg) +class PackageSignoffGroup(object): + '''Encompasses all packages in testing with the same pkgbase.''' + def __init__(self, packages, target_repo=None, signoffs=None): + if len(packages) == 0: + raise Exception + self.packages = packages + self.target_repo = target_repo + self.signoffs = signoffs + + first = packages[0] + self.pkgbase = first.pkgbase + self.arch = first.arch + self.repo = first.repo + self.version = '' + + version = first.full_version + if all(version == pkg.full_version for pkg in packages): + self.version = version + + @property + def package(self): + '''Try and return a relevant single package object representing this + group. Start by seeing if there is only one package, then look for the + matching package by name, finally falling back to a standin package + object.''' + if len(self.packages) == 1: + return self.packages[0] + + same_pkgs = [p for p in self.packages if p.pkgname == p.pkgbase] + if same_pkgs: + return same_pkgs[0] + + return PackageStandin(self.packages[0]) + + def find_signoffs(self, all_signoffs): + '''Look through a list of Signoff objects for ones matching this + particular group and store them on the object.''' + if self.signoffs is None: + self.signoffs = [] + for s in all_signoffs: + if s.pkgbase != self.pkgbase: + continue + if self.version and not s.full_version == self.version: + continue + if s.arch_id == self.arch.id and s.repo_id == self.repo.id: + self.signoffs.append(s) + + def approved(self): + if self.signoffs: + good_signoffs = [s for s in self.signoffs if not s.revoked] + return len(good_signoffs) >= Signoff.REQUIRED + return False + @permission_required('main.change_package') @never_cache def signoffs(request): - packages = Package.objects.select_related('arch', 'repo', 'signoffs').filter(repo__testing=True).order_by("pkgname") - package_list = [] - - q_pkgname = Package.objects.filter(repo__testing=True).values('pkgname').distinct().query - package_repos = Package.objects.values('pkgname', 'repo__name').exclude(repo__testing=True).filter(pkgname__in=q_pkgname) - pkgtorepo = dict() - for pr in package_repos: - pkgtorepo[pr['pkgname']] = pr['repo__name'] - - for package in packages: - if package.pkgname in pkgtorepo: - repo = pkgtorepo[package.pkgname] - else: - repo = "Unknown" - package_list.append((package, repo)) + test_pkgs = Package.objects.normal().filter(repo__testing=True) + packages = test_pkgs.order_by('pkgname') + + # Collect all pkgbase values in testing repos + q_pkgbase = test_pkgs.values('pkgbase') + package_repos = Package.objects.order_by().values_list( + 'pkgbase', 'repo__name').filter( + repo__testing=False, repo__staging=False, + pkgbase__in=q_pkgbase).distinct() + pkgtorepo = dict(package_repos) + + # Collect all existing signoffs for these packages + signoffs = get_current_signoffs() + + same_pkgbase_key = lambda x: (x.repo.name, x.arch.name, x.pkgbase) + grouped = groupby_preserve_order(packages, same_pkgbase_key) + signoff_groups = [] + for group in grouped: + signoff_group = PackageSignoffGroup(group) + signoff_group.target_repo = pkgtorepo.get(signoff_group.pkgbase, + "Unknown") + signoff_group.find_signoffs(signoffs) + signoff_groups.append(signoff_group) + + signoff_groups.sort(key=attrgetter('pkgbase')) + return direct_to_template(request, 'packages/signoffs.html', - {'packages': package_list}) + {'signoff_groups': signoff_groups}) @permission_required('main.change_package') @never_cache def signoff_package(request, name, repo, arch): - pkg = get_object_or_404(Package, - pkgname=name, repo__name__iexact=repo, arch__name=arch) + packages = get_list_or_404(Package, pkgbase=name, + arch__name=arch, repo__name__iexact=repo, repo__testing=True) + pkg = packages[0] signoff, created = Signoff.objects.get_or_create( - pkg=pkg, - pkgver=pkg.pkgver, - pkgrel=pkg.pkgrel, - packager=request.user) + pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel, + epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo, user=request.user) if request.is_ajax(): data = { diff --git a/templates/packages/signoffs.html b/templates/packages/signoffs.html index b1153d7c..6014396c 100644 --- a/templates/packages/signoffs.html +++ b/templates/packages/signoffs.html @@ -7,13 +7,15 @@

Package Signoffs

-

{{ packages|length }} package{{ packages|pluralize }} found.

+

{{ signoff_groups|length }} signoff group{{ signoff_groups|pluralize }} found. + A "signoff group" consists of packages grouped by pkgbase, architecture, and repository.

- + + @@ -22,28 +24,31 @@

Package Signoffs

- {% for pkg,target in packages %} + {% for group in signoff_groups %} + {% with group.package as pkg %} + - - + + + {% endwith %} {% endfor %}
ArchPackagePackage Base# of Packages Version Last Updated Target Repo
{{ pkg.arch.name }} {{ pkg.pkgname }}{{ group.packages|length }} {{ pkg.full_version }} {{ pkg.last_update|date }}{{ target }} - {{ pkg.approved_for_signoff|yesno:"Yes,No" }}{{ group.target_repo }} + {{ group.approved|yesno:"Yes,No" }}
  • Signoff + title="Signoff {{ pkg.pkgname }} for {{ pkg.arch }}">Signoff
  • - {% for signoff in pkg.signoffs %} -
  • - {{signoff.packager}}
  • + {% for signoff in group.signoffs %} +
  • + {{ signoff.user }}{% if signoff.revoked %} (revoked){% endif %}
  • {% endfor %}
-- cgit v1.2.3-54-g00ecf From d8e089fd30ac2dacac54c444cc522ee44ee332ed Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 6 Jul 2011 12:08:42 -0500 Subject: Delete old signoff model Signed-off-by: Dan McGee --- main/migrations/0052_auto__del_signoff.py | 166 ++++++++++++++++++++++++++++++ main/models.py | 6 -- 2 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 main/migrations/0052_auto__del_signoff.py (limited to 'main') diff --git a/main/migrations/0052_auto__del_signoff.py b/main/migrations/0052_auto__del_signoff.py new file mode 100644 index 00000000..8da6becc --- /dev/null +++ b/main/migrations/0052_auto__del_signoff.py @@ -0,0 +1,166 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + depends_on = ( + ('packages', '0008_add_signoff_model'), + ) + + def forwards(self, orm): + # Deleting model 'Signoff' + db.delete_table('main_signoff') + + + def backwards(self, orm): + # Adding model 'Signoff' + db.create_table('main_signoff', ( + ('pkgrel', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('packager', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('pkg', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['main.Package'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('pkgver', self.gf('django.db.models.fields.CharField')(max_length=255)), + )) + db.send_create_signal('main', ['Signoff']) + + + 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'}) + }, + 'main.arch': { + 'Meta': {'ordering': "['name']", 'object_name': 'Arch', 'db_table': "'arches'"}, + 'agnostic': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + 'main.donor': { + 'Meta': {'ordering': "['name']", 'object_name': 'Donor', 'db_table': "'donors'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'main.package': { + 'Meta': {'ordering': "('pkgname',)", 'object_name': 'Package', 'db_table': "'packages'"}, + 'arch': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'packages'", 'to': "orm['main.Arch']"}), + 'build_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'compressed_size': ('main.models.PositiveBigIntegerField', [], {}), + 'epoch': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'files_last_update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'flag_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'installed_size': ('main.models.PositiveBigIntegerField', [], {}), + 'last_update': ('django.db.models.fields.DateTimeField', [], {}), + 'packager': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'packager_str': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'pkgbase': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'pkgdesc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'pkgname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'pkgrel': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'pkgver': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'repo': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'packages'", 'to': "orm['main.Repo']"}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}) + }, + 'main.packagedepend': { + 'Meta': {'object_name': 'PackageDepend', 'db_table': "'package_depends'"}, + 'depname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'depvcmp': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}) + }, + 'main.packagefile': { + 'Meta': {'object_name': 'PackageFile', 'db_table': "'package_files'"}, + 'directory': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_directory': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}) + }, + 'main.repo': { + 'Meta': {'ordering': "['name']", 'object_name': 'Repo', 'db_table': "'repos'"}, + 'bugs_category': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + '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'}) + }, + 'main.todolist': { + 'Meta': {'object_name': 'Todolist', 'db_table': "'todolists'"}, + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'date_added': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'main.todolistpkg': { + 'Meta': {'unique_together': "(('list', 'pkg'),)", 'object_name': 'TodolistPkg', 'db_table': "'todolist_pkgs'"}, + 'complete': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Todolist']"}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}) + }, + 'main.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'}), + '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'}), + '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': ('main.models.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'}) + } + } + + complete_apps = ['main'] diff --git a/main/models.py b/main/models.py index 473144da..6e134810 100644 --- a/main/models.py +++ b/main/models.py @@ -367,12 +367,6 @@ def elsewhere(self): pkgname=self.pkgname).exclude(id=self.id).order_by( 'arch__name', 'repo__name') -class Signoff(models.Model): - pkg = models.ForeignKey(Package) - pkgver = models.CharField(max_length=255) - pkgrel = models.CharField(max_length=255) - packager = models.ForeignKey(User) - class PackageFile(models.Model): pkg = models.ForeignKey(Package) is_directory = models.BooleanField(default=False) -- cgit v1.2.3-54-g00ecf From 2a73675f0ed894d57ed13c5799e988f8d10ccfe2 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 29 Jul 2011 23:08:33 -0500 Subject: Select arch/repo for split package related fields Signed-off-by: Dan McGee --- main/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'main') diff --git a/main/models.py b/main/models.py index 6e134810..70372823 100644 --- a/main/models.py +++ b/main/models.py @@ -307,12 +307,12 @@ def base_package(self): """ try: # start by looking for something in this repo - return Package.objects.get(arch=self.arch, + return Package.objects.normal().get(arch=self.arch, repo=self.repo, pkgname=self.pkgbase) except Package.DoesNotExist: # this package might be split across repos? just find one # that matches the correct [testing] repo flag - pkglist = Package.objects.filter(arch=self.arch, + pkglist = Package.objects.normal().filter(arch=self.arch, repo__testing=self.repo.testing, repo__staging=self.repo.staging, pkgname=self.pkgbase) if len(pkglist) > 0: @@ -327,7 +327,7 @@ def split_packages(self): repo.testing and repo.staging flags. For any non-split packages, the return value will be an empty list. """ - return Package.objects.filter(arch__in=self.applicable_arches(), + return Package.objects.normal().filter(arch__in=self.applicable_arches(), repo__testing=self.repo.testing, repo__staging=self.repo.staging, pkgbase=self.pkgbase).exclude(id=self.id) -- cgit v1.2.3-54-g00ecf