aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--rrs/migrations/0017_maintenanceplan_maintainer_style.py20
-rw-r--r--rrs/models.py8
-rwxr-xr-xrrs/tools/rrs_maintainer_history.py199
-rw-r--r--rrs/views.py2
-rw-r--r--templates/rrs/recipedetail.html8
-rw-r--r--templates/rrs/recipes.html6
6 files changed, 149 insertions, 94 deletions
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 @@
<li class="lead">Upstream version: <span>{{ upstream_version }}</span></li>
{% endif %}
<li class="divider-vertical"></li>
- <li class="lead">Maintainer: <span><a href="{% url 'rrs_recipes' maintplan_name release_name milestone_name %}?maintainer_name={{ maintainer_name|urlencode }}">{{ maintainer_name }}</a></span></li>
+ <li class="lead">Maintainer:
+ {% if maintplan.per_recipe_maintainers %}
+ <span><a href="{% url 'rrs_recipes' maintplan_name release_name milestone_name %}?maintainer_name={{ maintainer_name|urlencode }}">{{ maintainer_name }}</a></span>
+ {% else %}
+ <span>{% for maintainer in recipe.layerbranch.active_maintainers %}{{ maintainer.name }}{% if not forloop.last %}, {% endif %}{% endfor %}</span>
+ {% endif %}
+ </li>
<li class="divider-vertical"></li>
</ul>
</div>
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 %}
</ul>
</li>
+ {% if maintplan.per_recipe_maintainers %}
<li><p>and</p></li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle" id="selected-maintainer">
@@ -56,6 +57,7 @@
{% endfor %}
</ul>
</li>
+ {% endif %}
</ul>
<form id="form-search" class="pull-right input-append">
@@ -80,7 +82,9 @@
<th class="upstream_status_column span2">Upstream status</th>
<th class="last_updated_column">Last Updated</th>
<th class="patches_column">Patches</th>
+ {% if maintplan.per_recipe_maintainers %}
<th class="maintainer_column">Maintainer</th>
+ {% endif %}
<th class="summary_column muted span5">Summary</th>
<th class="no_update_reason_column muted span5" style="display:none">No update reason</th>
</tr>
@@ -104,7 +108,9 @@
</td>
<td class="last_updated_column">{{r.outdated}}</td>
<td class="patches_column">{% if r.patches_total %}<span {% if not r.patches_pending %}class="muted"{% endif %}>{{ r.patches_pending }}<span class="muted"> / {{ r.patches_total }}</span>{% endif %}</td>
+ {% if maintplan.per_recipe_maintainers %}
<td class="maintainer_column">{{ r.maintainer_name }}</td>
+ {% endif %}
<td class="summary_column">{{ r.summary }}</td>
<td class="no_update_reason_column" style="display:none">{{ r.no_update_reason }}</td>
</tr>