aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--patchwork/migrations/0039_unique_series_references.py110
1 files changed, 46 insertions, 64 deletions
diff --git a/patchwork/migrations/0039_unique_series_references.py b/patchwork/migrations/0039_unique_series_references.py
index 99b10fc..3a10172 100644
--- a/patchwork/migrations/0039_unique_series_references.py
+++ b/patchwork/migrations/0039_unique_series_references.py
@@ -3,62 +3,6 @@ from django.db.models import Count
import django.db.models.deletion
-def merge_duplicate_series(apps, schema_editor):
- SeriesReference = apps.get_model('patchwork', 'SeriesReference')
- Patch = apps.get_model('patchwork', 'Patch')
-
- msgid_seriesrefs = {}
-
- # find all SeriesReference that share a msgid but point to different series
- # and decide which of the series is going to be the authoritative one
- msgid_counts = (
- SeriesReference.objects.values('msgid')
- .annotate(count=Count('msgid'))
- .filter(count__gt=1)
- )
- for msgid_count in msgid_counts:
- msgid = msgid_count['msgid']
- chosen_ref = None
- for series_ref in SeriesReference.objects.filter(msgid=msgid):
- if series_ref.series.cover_letter:
- if chosen_ref:
- # I don't think this can happen, but explode if it does
- raise Exception(
- "Looks like you've got two or more series that share "
- "some patches but do not share a cover letter. Unable "
- "to auto-resolve."
- )
-
- # if a series has a cover letter, that's the one we'll group
- # everything under
- chosen_ref = series_ref
-
- if not chosen_ref:
- # if none of the series have cover letters, simply use the last
- # one (hint: this relies on Python's weird scoping for for loops
- # where 'series_ref' is still accessible outside the loop)
- chosen_ref = series_ref
-
- msgid_seriesrefs[msgid] = chosen_ref
-
- # reassign any patches referring to non-authoritative series to point to
- # the authoritative one, and delete the other series; we do this separately
- # to allow us a chance to raise the exception above if necessary
- for msgid, chosen_ref in msgid_seriesrefs.items():
- for series_ref in SeriesReference.objects.filter(msgid=msgid):
- if series_ref == chosen_ref:
- continue
-
- # update the patches to point to our chosen series instead, on the
- # assumption that all other metadata is correct
- for patch in Patch.objects.filter(series=series_ref.series):
- patch.series = chosen_ref.series
- patch.save()
-
- # delete the other series (which will delete the series ref)
- series_ref.series.delete()
-
-
def copy_project_field(apps, schema_editor):
if connection.vendor == 'postgresql':
schema_editor.execute(
@@ -67,7 +11,7 @@ def copy_project_field(apps, schema_editor):
SET project_id = patchwork_series.project_id
FROM patchwork_series
WHERE patchwork_seriesreference.series_id = patchwork_series.id
- """
+ """
)
elif connection.vendor == 'mysql':
schema_editor.execute(
@@ -75,7 +19,7 @@ def copy_project_field(apps, schema_editor):
UPDATE patchwork_seriesreference, patchwork_series
SET patchwork_seriesreference.project_id = patchwork_series.project_id
WHERE patchwork_seriesreference.series_id = patchwork_series.id
- """ # noqa
+ """ # noqa
)
else:
SeriesReference = apps.get_model('patchwork', 'SeriesReference')
@@ -87,14 +31,49 @@ def copy_project_field(apps, schema_editor):
series_ref.save()
+def delete_duplicate_series(apps, schema_editor):
+ if connection.vendor == 'postgresql':
+ schema_editor.execute(
+ """
+ DELETE
+ FROM
+ patchwork_seriesreference a
+ USING patchwork_seriesreference b
+ WHERE
+ a.id < b.id
+ AND a.project_id = b.project_id
+ AND a.msgid = b.msgid
+ """
+ )
+ elif connection.vendor == 'mysql':
+ schema_editor.execute(
+ """
+ DELETE a FROM patchwork_seriesreference a
+ INNER JOIN patchwork_seriesreference b
+ WHERE
+ a.id < b.id
+ AND a.project_id = b.project_id
+ AND a.msgid = b.msgid
+ """
+ )
+ else:
+ Project = apps.get_model('patchwork', 'Project')
+ SeriesReference = apps.get_model('patchwork', 'SeriesReference')
+
+ for project in Project.objects.all():
+ (
+ SeriesReference.objects.filter(project=project)
+ .annotate(count=Count('msgid'))
+ .filter(count__gt=1)
+ .delete()
+ )
+
+
class Migration(migrations.Migration):
dependencies = [('patchwork', '0038_state_slug')]
operations = [
- migrations.RunPython(
- merge_duplicate_series, migrations.RunPython.noop, atomic=False
- ),
migrations.AddField(
model_name='seriesreference',
name='project',
@@ -104,12 +83,12 @@ class Migration(migrations.Migration):
to='patchwork.Project',
),
),
- migrations.AlterUniqueTogether(
- name='seriesreference', unique_together={('project', 'msgid')}
- ),
migrations.RunPython(
copy_project_field, migrations.RunPython.noop, atomic=False
),
+ migrations.RunPython(
+ delete_duplicate_series, migrations.RunPython.noop, atomic=False
+ ),
migrations.AlterField(
model_name='seriesreference',
name='project',
@@ -118,4 +97,7 @@ class Migration(migrations.Migration):
to='patchwork.Project',
),
),
+ migrations.AlterUniqueTogether(
+ name='seriesreference', unique_together={('project', 'msgid')}
+ ),
]