[Patchew-devel] [PATCH 14/16] model: Add and populate Message.maintainers
Fam Zheng
famz at redhat.com
Wed Nov 21 02:08:44 UTC 2018
This is a json field to store a list of str to represent concerned
maintainers by the changeset as per MAINTAINERS file in the project (to
be processed by appliers).
Collect and save maintainers info in applier: if a project has
'scripts/get_maintainer.pl' file, use it to get a list of names
associated with the touched files. This is purely ad-hoc (for QEMU) but
the logic is standalone and local so it's fairly easy to extend and
maybe parameterize later (e.g. add a command in git per-project config).
Signed-off-by: Fam Zheng <famz at redhat.com>
---
api/migrations/0043_message_maintainers.py | 22 +++++++++++++++
api/models.py | 2 ++
mods/git.py | 4 ++-
patchew-cli | 31 +++++++++++++++++++---
4 files changed, 54 insertions(+), 5 deletions(-)
create mode 100644 api/migrations/0043_message_maintainers.py
diff --git a/api/migrations/0043_message_maintainers.py b/api/migrations/0043_message_maintainers.py
new file mode 100644
index 0000000..c3d61b2
--- /dev/null
+++ b/api/migrations/0043_message_maintainers.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.16 on 2018-11-20 11:53
+from __future__ import unicode_literals
+
+from django.db import migrations
+import jsonfield.encoder
+import jsonfield.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0042_watchedquery'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='message',
+ name='maintainers',
+ field=jsonfield.fields.JSONField(blank=True, default=[], dump_kwargs={'cls': jsonfield.encoder.JSONEncoder, 'separators': (',', ':')}, load_kwargs={}),
+ ),
+ ]
diff --git a/api/models.py b/api/models.py
index 55b129e..67bf0ea 100644
--- a/api/models.py
+++ b/api/models.py
@@ -490,6 +490,8 @@ class Message(models.Model):
objects = MessageManager()
+ maintainers = jsonfield.JSONField(blank=True, default=[])
+
def save_mbox(self, mbox_blob):
save_blob(mbox_blob, self.message_id)
diff --git a/mods/git.py b/mods/git.py
index a37de57..a4290de 100644
--- a/mods/git.py
+++ b/mods/git.py
@@ -257,11 +257,13 @@ class ApplierReportView(APILoginRequiredView):
allowed_groups = ["importers"]
def handle(self, request, project, message_id, tag, url, base, repo,
- failed, log):
+ failed, log, maintainers=[]):
p = Project.objects.get(name=project)
r = Message.objects.series_heads().get(project=p,
message_id=message_id).git_result
r.log = log
+ r.message.maintainers = maintainers
+ r.message.save()
data = {}
if failed:
r.status = Result.FAILURE
diff --git a/patchew-cli b/patchew-cli
index b5d6ecb..154aadf 100755
--- a/patchew-cli
+++ b/patchew-cli
@@ -665,6 +665,20 @@ class ApplyCommand(SubCommand):
patch there. Implies --any, conflicts with -C, -b,
-B and -t.""")
+ def _get_maintainers(self, repo, fname):
+ script = os.path.join(repo, "scripts/get_maintainer.pl")
+ if not os.access(script, os.X_OK):
+ return []
+ try:
+ lines = subprocess.check_output([script, "--noroles", "--norolestats",
+ "--nogit", "--nogit-fallback", fname],
+ cwd=repo).decode('utf-8').splitlines()
+ # Only return entries in the form of "First Last <email at address.com>",
+ # excluding list addresses
+ return [x for x in lines if '<' in x and '>' in x]
+ except:
+ return []
+
def _apply(self, repo, s, branch, force_branch, tag, logf=None,
signoff=False):
msgid = s["message-id"]
@@ -679,15 +693,21 @@ class ApplyCommand(SubCommand):
bn = bn.replace("%m", msgid)
subprocess.check_call(["git", "checkout", bo, bn], cwd=repo,
stdout=logf, stderr=logf)
+ maintainers = set()
+ apply_failed = False
for p in s["patches"]:
patchf = tempfile.NamedTemporaryFile()
patchf.write(p["mbox"].encode('utf-8'))
patchf.flush()
+ maintainers = maintainers.union(self._get_maintainers(repo, patchf.name))
+ if apply_failed:
+ continue
if 0 != subprocess.call(["git", "am", "-m", "-3", patchf.name],
cwd=repo, stdout=logf, stderr=logf):
logf.flush()
logf.write("Failed to apply patch:\n%s" % p["subject"])
- raise ApplyFailedException()
+ apply_failed = True
+ continue
filter_cmd = ""
commit_message_lines = \
subprocess.check_output(["git", "log", "-n", "1",
@@ -711,10 +731,13 @@ class ApplyCommand(SubCommand):
subprocess.check_output(["git", "filter-branch", "-f",
"--msg-filter", "cat; " + filter_cmd,
"HEAD~1.."], cwd=repo)
- if tag:
+ if apply_failed:
+ raise ApplyFailedException()
+ elif tag:
subprocess.check_call(["git", "tag", "-f",
tag.replace("%m", msgid)], cwd=repo,
stdout=logf, stderr=logf)
+ return list(maintainers)
def _push(self, repo, remote, tag, logf):
subprocess.check_call(["git", "remote", "add", "push_to", remote],
@@ -749,7 +772,7 @@ class ApplyCommand(SubCommand):
base = subprocess.check_output(["git", "rev-parse", "HEAD"],
cwd=wd).decode('utf-8') \
.strip()
- self._apply(wd, toapply, branch, force_branch, tag, logf)
+ maintainers = self._apply(wd, toapply, branch, force_branch, tag, logf)
if push_repo:
self._push(wd, push_repo, tag, logf)
url = toapply.get("git.url_template", "").replace("%t", tag)
@@ -777,7 +800,7 @@ class ApplyCommand(SubCommand):
project=toapply["project"],
message_id=toapply["message-id"],
tag=tag, url=url, base=base, repo=public_repo,
- failed=False, log=log)
+ failed=False, log=log, maintainers=maintainers)
return 0
def do(self, args, argv):
--
2.17.2
More information about the Patchew-devel
mailing list