33import django .db .models .deletion
44
55
6- def merge_duplicate_series (apps , schema_editor ):
7- SeriesReference = apps .get_model ('patchwork' , 'SeriesReference' )
8- Patch = apps .get_model ('patchwork' , 'Patch' )
9-
10- msgid_seriesrefs = {}
11-
12- # find all SeriesReference that share a msgid but point to different series
13- # and decide which of the series is going to be the authoritative one
14- msgid_counts = (
15- SeriesReference .objects .values ('msgid' )
16- .annotate (count = Count ('msgid' ))
17- .filter (count__gt = 1 )
18- )
19- for msgid_count in msgid_counts :
20- msgid = msgid_count ['msgid' ]
21- chosen_ref = None
22- for series_ref in SeriesReference .objects .filter (msgid = msgid ):
23- if series_ref .series .cover_letter :
24- if chosen_ref :
25- # I don't think this can happen, but explode if it does
26- raise Exception (
27- "Looks like you've got two or more series that share "
28- "some patches but do not share a cover letter. Unable "
29- "to auto-resolve."
30- )
31-
32- # if a series has a cover letter, that's the one we'll group
33- # everything under
34- chosen_ref = series_ref
35-
36- if not chosen_ref :
37- # if none of the series have cover letters, simply use the last
38- # one (hint: this relies on Python's weird scoping for for loops
39- # where 'series_ref' is still accessible outside the loop)
40- chosen_ref = series_ref
41-
42- msgid_seriesrefs [msgid ] = chosen_ref
43-
44- # reassign any patches referring to non-authoritative series to point to
45- # the authoritative one, and delete the other series; we do this separately
46- # to allow us a chance to raise the exception above if necessary
47- for msgid , chosen_ref in msgid_seriesrefs .items ():
48- for series_ref in SeriesReference .objects .filter (msgid = msgid ):
49- if series_ref == chosen_ref :
50- continue
51-
52- # update the patches to point to our chosen series instead, on the
53- # assumption that all other metadata is correct
54- for patch in Patch .objects .filter (series = series_ref .series ):
55- patch .series = chosen_ref .series
56- patch .save ()
57-
58- # delete the other series (which will delete the series ref)
59- series_ref .series .delete ()
60-
61-
626def copy_project_field (apps , schema_editor ):
637 if connection .vendor == 'postgresql' :
648 schema_editor .execute (
@@ -67,15 +11,15 @@ def copy_project_field(apps, schema_editor):
6711 SET project_id = patchwork_series.project_id
6812 FROM patchwork_series
6913 WHERE patchwork_seriesreference.series_id = patchwork_series.id
70- """
14+ """
7115 )
7216 elif connection .vendor == 'mysql' :
7317 schema_editor .execute (
7418 """
7519 UPDATE patchwork_seriesreference, patchwork_series
7620 SET patchwork_seriesreference.project_id = patchwork_series.project_id
7721 WHERE patchwork_seriesreference.series_id = patchwork_series.id
78- """ # noqa
22+ """ # noqa
7923 )
8024 else :
8125 SeriesReference = apps .get_model ('patchwork' , 'SeriesReference' )
@@ -87,14 +31,49 @@ def copy_project_field(apps, schema_editor):
8731 series_ref .save ()
8832
8933
34+ def delete_duplicate_series (apps , schema_editor ):
35+ if connection .vendor == 'postgresql' :
36+ schema_editor .execute (
37+ """
38+ DELETE
39+ FROM
40+ patchwork_seriesreference a
41+ USING patchwork_seriesreference b
42+ WHERE
43+ a.id < b.id
44+ AND a.project_id = b.project_id
45+ AND a.msgid = b.msgid
46+ """
47+ )
48+ elif connection .vendor == 'mysql' :
49+ schema_editor .execute (
50+ """
51+ DELETE a FROM patchwork_seriesreference a
52+ INNER JOIN patchwork_seriesreference b
53+ WHERE
54+ a.id < b.id
55+ AND a.project_id = b.project_id
56+ AND a.msgid = b.msgid
57+ """
58+ )
59+ else :
60+ Project = apps .get_model ('patchwork' , 'Project' )
61+ SeriesReference = apps .get_model ('patchwork' , 'SeriesReference' )
62+
63+ for project in Project .objects .all ():
64+ (
65+ SeriesReference .objects .filter (project = project )
66+ .annotate (count = Count ('msgid' ))
67+ .filter (count__gt = 1 )
68+ .delete ()
69+ )
70+
71+
9072class Migration (migrations .Migration ):
9173
9274 dependencies = [('patchwork' , '0038_state_slug' )]
9375
9476 operations = [
95- migrations .RunPython (
96- merge_duplicate_series , migrations .RunPython .noop , atomic = False
97- ),
9877 migrations .AddField (
9978 model_name = 'seriesreference' ,
10079 name = 'project' ,
@@ -104,12 +83,12 @@ class Migration(migrations.Migration):
10483 to = 'patchwork.Project' ,
10584 ),
10685 ),
107- migrations .AlterUniqueTogether (
108- name = 'seriesreference' , unique_together = {('project' , 'msgid' )}
109- ),
11086 migrations .RunPython (
11187 copy_project_field , migrations .RunPython .noop , atomic = False
11288 ),
89+ migrations .RunPython (
90+ delete_duplicate_series , migrations .RunPython .noop , atomic = False
91+ ),
11392 migrations .AlterField (
11493 model_name = 'seriesreference' ,
11594 name = 'project' ,
@@ -118,4 +97,7 @@ class Migration(migrations.Migration):
11897 to = 'patchwork.Project' ,
11998 ),
12099 ),
100+ migrations .AlterUniqueTogether (
101+ name = 'seriesreference' , unique_together = {('project' , 'msgid' )}
102+ ),
121103 ]
0 commit comments