[RFC PATCH 4/4] patch-detail: add functionality to add/remove related patches
Raxel Gutierrez
raxel at google.com
Tue Aug 24 00:58:47 AEST 2021
Currently, patch relations can be modified using the REST API, but the
Patchwork UI provides no tools that allow users to create and edit patch
relations. This patch adds that as part of the patch relations table.
The changes involve the following details:
Add handling of user input to the add/remove related patches as such:
- Parse user input of ids and msgids by commas and whitespace
- Match parsed ids to patches in the db
- Record invalid ids to report back to the user
- Update patch relations based on selected option to add/remove
- Add update/error messages to web page as feedback
In the future, an automated system to relate patches together would be
ideal, meaning that this functionality should be considered a fallback
option when the automated system has faults. At the very least, this
manual option serves as the basic function to create and modify patch
relations.
Signed-off-by: Raxel Gutierrez <raxel at google.com>
---
patchwork/views/__init__.py | 33 +++++++++++++++++++++++++++++++
patchwork/views/patch.py | 39 +++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+)
diff --git a/patchwork/views/__init__.py b/patchwork/views/__init__.py
index 3efe90cd..35c9c23c 100644
--- a/patchwork/views/__init__.py
+++ b/patchwork/views/__init__.py
@@ -6,6 +6,7 @@
from django.contrib import messages
from django.shortcuts import get_object_or_404
from django.db.models import Prefetch
+from django.core.exceptions import ObjectDoesNotExist
from patchwork.filters import Filters
from patchwork.forms import MultiplePatchForm
@@ -323,3 +324,35 @@ def process_multiplepatch_form(request, form, action, patches, context):
messages.warning(request, 'No patches updated')
return errors
+
+
+def get_patch_relations_data(patch, action, data):
+ related_input = data.get('related_input', '').strip()
+ related_ids = [id.strip('<> ') for id in related_input.split(",")]
+ # patches that match the parsed user input ids and ids that did not match
+ related_patches, invalid_ids = get_patches_id_msgid(related_ids)
+
+ if action == 'remove-related':
+ related_patches = [
+ p for p in patch.related.patches.all()
+ if p in related_patches
+ ]
+ return ({'related': related_patches}, invalid_ids)
+
+
+def get_patches_id_msgid(ids):
+ patches = []
+ invalid_ids = []
+ for str_id in ids:
+ try:
+ id = int(str_id)
+ try:
+ patches.append(Patch.objects.get(id=id))
+ except ObjectDoesNotExist:
+ invalid_ids.append(id)
+ except ValueError:
+ try:
+ patches.append(Patch.objects.get(msgid='<' + str_id + '>'))
+ except ObjectDoesNotExist:
+ invalid_ids.append(str_id)
+ return (patches, invalid_ids)
diff --git a/patchwork/views/patch.py b/patchwork/views/patch.py
index 8e685add..92f9038a 100644
--- a/patchwork/views/patch.py
+++ b/patchwork/views/patch.py
@@ -19,8 +19,10 @@ from patchwork.models import Cover
from patchwork.models import Patch
from patchwork.models import Project
from patchwork.views import generic_list
+from patchwork.views import get_patch_relations_data
from patchwork.views.utils import patch_to_mbox
from patchwork.views.utils import series_patch_to_mbox
+from patchwork.api.patch import update_patch_relations
def patch_list(request, project_id):
@@ -64,6 +66,7 @@ def patch_detail(request, project_id, msgid):
form = None
createbundleform = None
+ errors = []
if editable:
form = PatchForm(instance=patch)
@@ -97,6 +100,41 @@ def patch_detail(request, project_id, msgid):
'Failed to add patch "%s" to bundle "%s": '
'patch is already in bundle' % (
patch.name, bundle.name))
+ elif action in ('add-related', 'remove-related'):
+ changed_relations = 0 # used for update message count
+ data, invalid_ids = get_patch_relations_data(
+ patch, action, request.POST
+ )
+
+ if data['related']: # check if any ids matched
+ if action == 'add-related':
+ update_errors = update_patch_relations(
+ request.user.profile, patch, data
+ )
+ errors.extend(update_errors)
+ if not update_errors:
+ changed_relations += 1
+ elif action == 'remove-related':
+ for rp in data['related']:
+ # for removal, to-be removed patch(es)'
+ # relations are emptied
+ update_errors = update_patch_relations(
+ request.user.profile, rp, {'related': []}
+ )
+ errors.extend(update_errors)
+ if not update_errors:
+ changed_relations += 1
+
+ errors.extend(
+ ['%s is not a valid patch/msg id' % pid for pid in invalid_ids]
+ )
+ if changed_relations >= 1:
+ messages.success(
+ request,
+ '%d patch relation(s) updated' % changed_relations
+ )
+ else:
+ messages.warning(request, 'No patch relations updated')
# all other actions require edit privs
elif not editable:
@@ -150,6 +188,7 @@ def patch_detail(request, project_id, msgid):
context['related_same_project'] = related_same_project
context['related_ids'] = related_ids
context['related_different_project'] = related_different_project
+ context['errors'] = errors
return render(request, 'patchwork/submission.html', context)
--
2.33.0.rc2.250.ged5fa647cd-goog
More information about the Patchwork
mailing list