From 2a651efc9a6c4fb5f7618c9b2f9ce1e8690cebc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C3=ADbal=20Lim=C3=B3n?= Date: Tue, 20 Jan 2015 17:46:53 -0600 Subject: [PATCH] rrs: Add support for store RecipeUpstreamHistory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To provide statistics about RecipeUpstream information based on Milestones we need to store RecipeUpstreamHistory that contains when the update script was executed. rrs/admin.py: Add admin page for RecipeUpstreamHistory. rrs/models.py: Add model for RecipeUpstreamHistory with helper functions for get last and last by date range also add migration. Signed-off-by: Aníbal Limón --- rrs/admin.py | 12 +- ...story__add_field_recipeupstream_history.py | 149 ++++++++++++++++++ rrs/models.py | 27 ++++ 3 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 rrs/migrations/0002_auto__add_recipeupstreamhistory__add_field_recipeupstream_history.py diff --git a/rrs/admin.py b/rrs/admin.py index fa7dec0..04b04c0 100644 --- a/rrs/admin.py +++ b/rrs/admin.py @@ -8,7 +8,7 @@ from django.contrib import admin from django.contrib.admin import DateFieldListFilter from rrs.models import Milestone, Maintainer, RecipeMaintainer, RecipeDistro, \ - RecipeUpgrade, RecipeUpstream + RecipeUpgrade, RecipeUpstream, RecipeUpstreamHistory class MilestoneAdmin(admin.ModelAdmin): search_fields = ['name'] @@ -34,10 +34,17 @@ class RecipeUpgradeAdmin(admin.ModelAdmin): ('commit_date', DateFieldListFilter), 'maintainer__name'] model = RecipeUpgrade +class RecipeUpstreamHistoryAdmin(admin.ModelAdmin): + list_filter = [ + ('start_date', DateFieldListFilter), + ('end_date', DateFieldListFilter) + ] + model = RecipeUpstreamHistory + class RecipeUpstreamAdmin(admin.ModelAdmin): search_fields = ['recipe__pn'] list_filter = ['recipe__layerbranch__layer__name', 'status', - 'type', ('date', DateFieldListFilter)] + 'type', ('date', DateFieldListFilter), 'history'] model = RecipeUpstream admin.site.register(Milestone, MilestoneAdmin) @@ -45,4 +52,5 @@ admin.site.register(Maintainer, MaintainerAdmin) admin.site.register(RecipeMaintainer, RecipeMaintainerAdmin) admin.site.register(RecipeDistro, RecipeDistroAdmin) admin.site.register(RecipeUpgrade, RecipeUpgradeAdmin) +admin.site.register(RecipeUpstreamHistory, RecipeUpstreamHistoryAdmin) admin.site.register(RecipeUpstream, RecipeUpstreamAdmin) diff --git a/rrs/migrations/0002_auto__add_recipeupstreamhistory__add_field_recipeupstream_history.py b/rrs/migrations/0002_auto__add_recipeupstreamhistory__add_field_recipeupstream_history.py new file mode 100644 index 0000000..17ad0ce --- /dev/null +++ b/rrs/migrations/0002_auto__add_recipeupstreamhistory__add_field_recipeupstream_history.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'RecipeUpstreamHistory' + db.create_table('rrs_recipeupstreamhistory', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('start_date', self.gf('django.db.models.fields.DateTimeField')()), + ('end_date', self.gf('django.db.models.fields.DateTimeField')()), + )) + db.send_create_signal('rrs', ['RecipeUpstreamHistory']) + + # Adding field 'RecipeUpstream.history' + db.add_column('rrs_recipeupstream', 'history', + self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rrs.RecipeUpstreamHistory'], null=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting model 'RecipeUpstreamHistory' + db.delete_table('rrs_recipeupstreamhistory') + + # Deleting field 'RecipeUpstream.history' + db.delete_column('rrs_recipeupstream', 'history_id') + + + models = { + 'layerindex.branch': { + 'Meta': {'object_name': 'Branch'}, + 'bitbake_branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'sort_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}) + }, + 'layerindex.layerbranch': { + 'Meta': {'object_name': 'LayerBranch'}, + 'actual_branch': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}), + 'branch': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['layerindex.Branch']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['layerindex.LayerItem']"}), + 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'vcs_last_commit': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'vcs_last_fetch': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'vcs_last_rev': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}), + 'vcs_subdir': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}) + }, + 'layerindex.layeritem': { + 'Meta': {'object_name': 'LayerItem'}, + 'classic': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index_preference': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'layer_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'mailing_list_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'usage_url': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'vcs_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'vcs_web_file_base_url': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'vcs_web_tree_base_url': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'vcs_web_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'layerindex.recipe': { + 'Meta': {'object_name': 'Recipe'}, + 'bbclassextend': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'depends': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'filepath': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'layerbranch': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['layerindex.LayerBranch']"}), + 'license': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'pn': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'provides': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'pv': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'src_uri': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + 'rrs.maintainer': { + 'Meta': {'ordering': "['name']", 'object_name': 'Maintainer'}, + 'email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + 'rrs.milestone': { + 'Meta': {'object_name': 'Milestone'}, + 'end_date': ('django.db.models.fields.DateField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'start_date': ('django.db.models.fields.DateField', [], {}) + }, + 'rrs.recipedistro': { + 'Meta': {'object_name': 'RecipeDistro'}, + 'alias': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['layerindex.Recipe']"}) + }, + 'rrs.recipemaintainer': { + 'Meta': {'object_name': 'RecipeMaintainer'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rrs.Maintainer']"}), + 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['layerindex.Recipe']"}) + }, + 'rrs.recipeupgrade': { + 'Meta': {'object_name': 'RecipeUpgrade'}, + 'author_date': ('django.db.models.fields.DateTimeField', [], {}), + 'commit_date': ('django.db.models.fields.DateTimeField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rrs.Maintainer']", 'null': 'True', 'blank': 'True'}), + 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['layerindex.Recipe']"}), + 'sha1': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}) + }, + 'rrs.recipeupstream': { + 'Meta': {'object_name': 'RecipeUpstream'}, + 'date': ('django.db.models.fields.DateTimeField', [], {}), + 'history': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rrs.RecipeUpstreamHistory']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'no_update_reason': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['layerindex.Recipe']"}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '1', 'blank': 'True'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '1', 'blank': 'True'}), + 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}) + }, + 'rrs.recipeupstreamhistory': { + 'Meta': {'object_name': 'RecipeUpstreamHistory'}, + 'end_date': ('django.db.models.fields.DateTimeField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'start_date': ('django.db.models.fields.DateTimeField', [], {}) + } + } + + complete_apps = ['rrs'] \ No newline at end of file diff --git a/rrs/models.py b/rrs/models.py index e9dbcdc..3f73e4a 100644 --- a/rrs/models.py +++ b/rrs/models.py @@ -68,6 +68,32 @@ class RecipeMaintainer(models.Model): return "%s: %s <%s>" % (self.recipe.pn, self.maintainer.name, self.maintainer.email) +class RecipeUpstreamHistory(models.Model): + start_date = models.DateTimeField() + end_date = models.DateTimeField() + + @staticmethod + def get_last_by_date_range(start, end): + history = RecipeUpstreamHistory.objects.filter(start_date__gte = start, + start_date__lte = end).order_by('-id') + + if history: + return history[0] + else: + return None + + @staticmethod + def get_last(): + history = RecipeUpstreamHistory.objects.filter().order_by('-id') + + if history: + return history[0] + else: + return None + + def __unicode__(self): + return '%s: %s' % (self.id, self.start_date) + class RecipeUpstream(models.Model): RECIPE_UPSTREAM_STATUS_CHOICES = ( ('N', 'Not updated'), @@ -82,6 +108,7 @@ class RecipeUpstream(models.Model): ) recipe = models.ForeignKey(Recipe) + history = models.ForeignKey(RecipeUpstreamHistory, null=True) version = models.CharField(max_length=100, blank=True) type = models.CharField(max_length=1, choices=RECIPE_UPSTREAM_TYPE_CHOICES, blank=True) status = models.CharField(max_length=1, choices=RECIPE_UPSTREAM_STATUS_CHOICES, blank=True)