[RFC PATCH 4/4] patch-detail: add functionality to add/remove related patches

Raxel Gutierrez raxel at google.com
Tue Aug 24 08:50:51 AEST 2021


Made a mistake with making update_patch_relations modular [1]. Tests
are failing. The following changes should be made to this patch to
fix:

diff --git a/patchwork/views/patch.py b/patchwork/views/patch.py
index 92f9038a..e1f2846d 100644
--- a/patchwork/views/patch.py
+++ b/patchwork/views/patch.py
@@ -106,7 +106,7 @@ def patch_detail(request, project_id, msgid):
                 patch, action, request.POST
             )

-            if data['related']:  # check if any ids matched
+            if data['related']['patches']:  # check if any ids matched
                 if action == 'add-related':
                     update_errors = update_patch_relations(
                         request.user.profile, patch, data
@@ -115,11 +115,13 @@ def patch_detail(request, project_id, msgid):
                     if not update_errors:
                         changed_relations += 1
                 elif action == 'remove-related':
-                    for rp in data['related']:
+                    for rp in data['related']['patches']:
                         # for removal, to-be removed patch(es)'
                         # relations are emptied
                         update_errors = update_patch_relations(
-                            request.user.profile, rp, {'related': []}
+                           request.user.profile, rp,
+                           {'related': {'patches': []}}

[1] https://lists.ozlabs.org/pipermail/patchwork/2021-August/007171.html

On Mon, Aug 23, 2021 at 10:58 AM Raxel Gutierrez <raxel at google.com> wrote:
>
> 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