From e071ebab294778a9197811b921ec458a61be7e7d Mon Sep 17 00:00:00 2001 From: Paul Eggleton Date: Wed, 18 Apr 2018 16:11:51 +1200 Subject: rrs: add flag to MaintenancePlan to specify layer-wide maintainers Most layers do not track maintenance on a per-recipe basis, and for those layers we will hide some of the per-recipe maintainer features and on the recipe detail show the layer maintainer(s) as the maintainer(s) of the recipe. Signed-off-by: Paul Eggleton --- .../0017_maintenanceplan_maintainer_style.py | 20 +++ rrs/models.py | 8 + rrs/tools/rrs_maintainer_history.py | 199 +++++++++++---------- rrs/views.py | 2 + templates/rrs/recipedetail.html | 8 +- templates/rrs/recipes.html | 6 + 6 files changed, 149 insertions(+), 94 deletions(-) create mode 100644 rrs/migrations/0017_maintenanceplan_maintainer_style.py diff --git a/rrs/migrations/0017_maintenanceplan_maintainer_style.py b/rrs/migrations/0017_maintenanceplan_maintainer_style.py new file mode 100644 index 0000000000..243d43a83f --- /dev/null +++ b/rrs/migrations/0017_maintenanceplan_maintainer_style.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.12 on 2018-04-18 02:26 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('rrs', '0016_rmh_layerbranch_nonnull'), + ] + + operations = [ + migrations.AddField( + model_name='maintenanceplan', + name='maintainer_style', + field=models.CharField(choices=[('I', 'Per-recipe - maintainers.inc'), ('L', 'Layer-wide')], default='L', help_text='Maintainer tracking style for the layers within this plan', max_length=1), + ), + ] diff --git a/rrs/models.py b/rrs/models.py index 6650da984b..2ae3353126 100644 --- a/rrs/models.py +++ b/rrs/models.py @@ -18,6 +18,10 @@ from django.core.exceptions import ObjectDoesNotExist class MaintenancePlan(models.Model): + MAINTENANCEPLAN_MAINTAINER_STYLE = ( + ('I', 'Per-recipe - maintainers.inc'), + ('L', 'Layer-wide'), + ) name = models.CharField(max_length=50, unique=True) description = models.TextField(blank=True) updates_enabled = models.BooleanField('Enable updates', default=True, help_text='Enable automatically updating metadata for this plan via the update scripts') @@ -26,10 +30,14 @@ class MaintenancePlan(models.Model): email_from = models.CharField(max_length=255, blank=True, help_text='Sender for automated emails') email_to = models.CharField(max_length=255, blank=True, help_text='Recipient for automated emails (separate multiple addresses with ;)') admin = models.ForeignKey(User, blank=True, null=True, help_text='Plan administrator') + maintainer_style = models.CharField(max_length=1, choices=MAINTENANCEPLAN_MAINTAINER_STYLE, default='L', help_text='Maintainer tracking style for the layers within this plan') def get_default_release(self): return self.release_set.last() + def per_recipe_maintainers(self): + return self.maintainer_style != 'L' + def __str__(self): return '%s' % (self.name) diff --git a/rrs/tools/rrs_maintainer_history.py b/rrs/tools/rrs_maintainer_history.py index e89042e68b..c4beaf1419 100755 --- a/rrs/tools/rrs_maintainer_history.py +++ b/rrs/tools/rrs_maintainer_history.py @@ -67,6 +67,104 @@ def get_commit_info(info, logger): return (author_name, author_email, date, title) + +def maintainers_inc_history(options, logger, maintplan, layerbranch, repodir, layerdir): + maintainers_full_path = os.path.join(layerdir, MAINTAINERS_INCLUDE_PATH) + if not os.path.exists(maintainers_full_path): + logger.warning('Maintainer style is maintainers.inc for plan %s but no maintainers.inc exists in for %s' % (maintplan, layerbranch)) + return + + logger.debug('Checking maintainers.inc history for %s' % layerbranch) + + commits = utils.runcmd("git log --format='%%H' --reverse --date=rfc origin/master %s" + % os.path.join(layerbranch.vcs_subdir, MAINTAINERS_INCLUDE_PATH), + repodir, logger=logger) + + no_maintainer, _ = Maintainer.objects.get_or_create(name='No maintainer') + + try: + with transaction.atomic(): + for commit in commits.strip().split("\n"): + if RecipeMaintainerHistory.objects.filter(layerbranch=layerbranch, sha1=commit): + continue + + logger.debug("Analysing commit %s ..." % (commit)) + + (author_name, author_email, date, title) = \ + get_commit_info(utils.runcmd("git show " + commit, repodir, + logger=logger), logger) + + author = Maintainer.create_or_update(author_name, author_email) + rms = RecipeMaintainerHistory(title=title, date=date, author=author, + sha1=commit, layerbranch=layerbranch) + rms.save() + + utils.runcmd("git checkout %s -f" % commit, + repodir, logger=logger) + + lines = [line.strip() for line in open(maintainers_full_path)] + for line in lines: + res = get_recipe_maintainer(line, logger) + if res: + (pn, name, email) = res + qry = Recipe.objects.filter(pn = pn, layerbranch = layerbranch) + + if qry: + m = Maintainer.create_or_update(name, email) + + rm = RecipeMaintainer() + rm.recipe = qry[0] + rm.maintainer = m + rm.history = rms + rm.save() + + logger.debug("%s: Change maintainer to %s in commit %s." % \ + (pn, m.name, commit)) + else: + logger.debug("%s: Not found in %s." % \ + (pn, layerbranch)) + + # set missing recipes to no maintainer + for recipe in layerbranch.recipe_set.all(): + if not RecipeMaintainer.objects.filter(recipe = recipe, history = rms): + rm = RecipeMaintainer() + rm.recipe = recipe + link_maintainer = RecipeMaintenanceLink.link_maintainer(recipe.pn, rms) + if link_maintainer: + rm.maintainer = link_maintainer.maintainer + else: + rm.maintainer = no_maintainer + rm.history = rms + rm.save() + if link_maintainer: + logger.debug("%s: linked to maintainer for %s" % (recipe.pn, link_maintainer.recipe.pn)) + else: + logger.debug("%s: Not found maintainer in commit %s set to 'No maintainer'." % \ + (recipe.pn, rms.sha1)) + + # set new recipes to no maintainer if don't have one + rms = RecipeMaintainerHistory.get_last(layerbranch) + for recipe in layerbranch.recipe_set.all(): + if not RecipeMaintainer.objects.filter(recipe = recipe, history = rms): + rm = RecipeMaintainer() + rm.recipe = recipe + link_maintainer = RecipeMaintenanceLink.link_maintainer(recipe.pn, rms) + if link_maintainer: + rm.maintainer = link_maintainer.maintainer + else: + rm.maintainer = no_maintainer + rm.history = rms + rm.save() + if link_maintainer: + logger.debug("%s: New recipe linked to maintainer for %s" % (recipe.pn, link_maintainer.recipe.pn)) + else: + logger.debug("%s: New recipe not found maintainer set to 'No maintainer'." % \ + (recipe.pn)) + if options.dry_run: + raise DryRunRollbackException + except DryRunRollbackException: + pass + """ Recreate Maintainership history from the beginning """ @@ -83,8 +181,6 @@ def maintainer_history(options, logger): logger.error('No enabled maintenance plans found') sys.exit(1) - no_maintainer, _ = Maintainer.objects.get_or_create(name='No maintainer') - lockfn = os.path.join(fetchdir, "layerindex.lock") lockfile = utils.lock_file(lockfn) if not lockfile: @@ -100,97 +196,14 @@ def maintainer_history(options, logger): repodir = os.path.join(fetchdir, urldir) layerdir = os.path.join(repodir, layerbranch.vcs_subdir) - maintainers_full_path = os.path.join(layerdir, MAINTAINERS_INCLUDE_PATH) - if not os.path.exists(maintainers_full_path): - logger.debug('No maintainers.inc for %s, skipping' % layerbranch) - continue - - commits = utils.runcmd("git log --format='%%H' --reverse --date=rfc origin/master %s" - % os.path.join(layerbranch.vcs_subdir, MAINTAINERS_INCLUDE_PATH), - repodir, logger=logger) - - try: - with transaction.atomic(): - for commit in commits.strip().split("\n"): - if RecipeMaintainerHistory.objects.filter(layerbranch=layerbranch, sha1=commit): - continue - - logger.debug("Analysing commit %s ..." % (commit)) - - (author_name, author_email, date, title) = \ - get_commit_info(utils.runcmd("git show " + commit, repodir, - logger=logger), logger) - - author = Maintainer.create_or_update(author_name, author_email) - rms = RecipeMaintainerHistory(title=title, date=date, author=author, - sha1=commit, layerbranch=layerbranch) - rms.save() - - utils.runcmd("git checkout %s -f" % commit, - repodir, logger=logger) - - lines = [line.strip() for line in open(maintainers_full_path)] - for line in lines: - res = get_recipe_maintainer(line, logger) - if res: - (pn, name, email) = res - qry = Recipe.objects.filter(pn = pn, layerbranch = layerbranch) - - if qry: - m = Maintainer.create_or_update(name, email) - - rm = RecipeMaintainer() - rm.recipe = qry[0] - rm.maintainer = m - rm.history = rms - rm.save() - - logger.debug("%s: Change maintainer to %s in commit %s." % \ - (pn, m.name, commit)) - else: - logger.debug("%s: Not found in %s." % \ - (pn, layerbranch)) - - # set missing recipes to no maintainer - for recipe in layerbranch.recipe_set.all(): - if not RecipeMaintainer.objects.filter(recipe = recipe, history = rms): - rm = RecipeMaintainer() - rm.recipe = recipe - link_maintainer = RecipeMaintenanceLink.link_maintainer(recipe.pn, rms) - if link_maintainer: - rm.maintainer = link_maintainer.maintainer - else: - rm.maintainer = no_maintainer - rm.history = rms - rm.save() - if link_maintainer: - logger.debug("%s: linked to maintainer for %s" % (recipe.pn, link_maintainer.recipe.pn)) - else: - logger.debug("%s: Not found maintainer in commit %s set to 'No maintainer'." % \ - (recipe.pn, rms.sha1)) - - # set new recipes to no maintainer if don't have one - rms = RecipeMaintainerHistory.get_last(layerbranch) - for recipe in layerbranch.recipe_set.all(): - if not RecipeMaintainer.objects.filter(recipe = recipe, history = rms): - rm = RecipeMaintainer() - rm.recipe = recipe - link_maintainer = RecipeMaintenanceLink.link_maintainer(recipe.pn, rms) - if link_maintainer: - rm.maintainer = link_maintainer.maintainer - else: - rm.maintainer = no_maintainer - rm.history = rms - rm.save() - if link_maintainer: - logger.debug("%s: New recipe linked to maintainer for %s" % (recipe.pn, link_maintainer.recipe.pn)) - else: - logger.debug("%s: New recipe not found maintainer set to 'No maintainer'." % \ - (recipe.pn)) - if options.dry_run: - raise DryRunRollbackException - except DryRunRollbackException: - pass + if maintplan.maintainer_style == 'I': + # maintainers.inc + maintainers_inc_history(options, logger, maintplan, layerbranch, repodir, layerdir) + elif maintplan.maintainer_style == 'L': + # Layer-wide, don't need to do anything + logger.debug('Skipping maintainer processing for %s - plan %s maintainer style is layer-wide' % (layerbranch, maintplan)) + else: + raise Exception('Unknown maintainer style %s for maintenance plan %s' % (maintplan.maintainer_style, maintplan)) finally: utils.unlock_file(lockfile) diff --git a/rrs/views.py b/rrs/views.py index cdecd188a5..03fe4740d1 100644 --- a/rrs/views.py +++ b/rrs/views.py @@ -536,6 +536,7 @@ class RecipeListView(ListView): context['all_maintplans'] = MaintenancePlan.objects.all() context['maintplan_name'] = self.maintplan_name maintplan = get_object_or_404(MaintenancePlan, name=self.maintplan_name) + context['maintplan'] = maintplan context['release_name'] = self.release_name context['all_releases'] = Release.objects.filter(plan=maintplan).order_by('-end_date') context['milestone_name'] = self.milestone_name @@ -676,6 +677,7 @@ class RecipeDetailView(DetailView): maintplan = get_object_or_404(MaintenancePlan, name=self.maintplan_name) context['maintplan_name'] = maintplan.name + context['maintplan'] = maintplan release = Release.get_current(maintplan) context['release_name'] = release.name milestone = Milestone.get_current(release) diff --git a/templates/rrs/recipedetail.html b/templates/rrs/recipedetail.html index e79852ce56..e6f51d0725 100644 --- a/templates/rrs/recipedetail.html +++ b/templates/rrs/recipedetail.html @@ -53,7 +53,13 @@
  • Upstream version: {{ upstream_version }}
  • {% endif %}
  • -
  • Maintainer: {{ maintainer_name }}
  • +
  • Maintainer: + {% if maintplan.per_recipe_maintainers %} + {{ maintainer_name }} + {% else %} + {% for maintainer in recipe.layerbranch.active_maintainers %}{{ maintainer.name }}{% if not forloop.last %}, {% endif %}{% endfor %} + {% endif %} +
  • diff --git a/templates/rrs/recipes.html b/templates/rrs/recipes.html index 30db1bf32e..af3c08d6e0 100644 --- a/templates/rrs/recipes.html +++ b/templates/rrs/recipes.html @@ -40,6 +40,7 @@ {% endfor %} + {% if maintplan.per_recipe_maintainers %}
  • and

  • + {% endif %}