@@ -46,27 +46,43 @@ def handle(self, *args: Any, app_label: str, **options: Any) -> None:
46
46
if not max_migration_txt .exists ():
47
47
raise CommandError (f"{ app_label } does not have a max_migration.txt." )
48
48
49
- migration_names = find_migration_names (
50
- max_migration_txt .read_text ().splitlines ()
51
- )
49
+ migration_names = find_migration_names (max_migration_txt .read_text ())
52
50
if migration_names is None :
53
51
raise CommandError (
54
52
f"{ app_label } 's max_migration.txt does not seem to contain a"
55
53
+ " merge conflict."
56
54
)
57
- merged_migration_name , rebased_migration_name = migration_names
58
- if merged_migration_name not in migration_details .names :
59
- raise CommandError (
60
- f"Parsed { merged_migration_name !r} as the already-merged"
61
- + f" migration name from { app_label } 's max_migration.txt, but"
62
- + " this migration does not exist."
63
- )
64
- if rebased_migration_name not in migration_details .names :
65
- raise CommandError (
66
- f"Parsed { rebased_migration_name !r} as the rebased migration"
67
- + f" name from { app_label } 's max_migration.txt, but this"
68
- + " migration does not exist."
69
- )
55
+
56
+ merged_migration_names , rebased_migration_names = migration_names
57
+
58
+ for merged_migration_name in merged_migration_names :
59
+ if merged_migration_name not in migration_details .names :
60
+ raise CommandError (
61
+ f"Parsed { merged_migration_name !r} as the already-merged"
62
+ + f" migration name from { app_label } 's max_migration.txt, but"
63
+ + " this migration does not exist."
64
+ )
65
+
66
+ for rebased_migration_name in rebased_migration_names :
67
+ if rebased_migration_name not in migration_details .names :
68
+ raise CommandError (
69
+ f"Parsed { rebased_migration_name !r} as the rebased migration"
70
+ + f" name from { app_label } 's max_migration.txt, but this"
71
+ + " migration does not exist."
72
+ )
73
+
74
+ self .last_migration_name = merged_migration_names [- 1 ]
75
+
76
+ first_migration = True
77
+ for rebased_migration_name in rebased_migration_names :
78
+ self .rebase_migration (app_label , rebased_migration_name , first_migration )
79
+ first_migration = False
80
+
81
+ def rebase_migration (
82
+ self , app_label : str , rebased_migration_name : str , first_migration : bool
83
+ ) -> None :
84
+ migration_details = MigrationDetails (app_label )
85
+ max_migration_txt = migration_details .dir / "max_migration.txt"
70
86
71
87
rebased_migration_filename = f"{ rebased_migration_name } .py"
72
88
rebased_migration_path = migration_details .dir / rebased_migration_filename
@@ -136,7 +152,7 @@ def handle(self, *args: Any, app_label: str, **options: Any) -> None:
136
152
ast .Tuple (
137
153
elts = [
138
154
ast .Constant (app_label ),
139
- ast .Constant (merged_migration_name ),
155
+ ast .Constant (self . last_migration_name ),
140
156
]
141
157
)
142
158
)
@@ -152,16 +168,23 @@ def handle(self, *args: Any, app_label: str, **options: Any) -> None:
152
168
153
169
new_content = before_deps + ast_unparse (new_dependencies ) + after_deps
154
170
155
- merged_number , _merged_rest = merged_migration_name .split ("_" , 1 )
171
+ last_merged_number , _merged_rest = self . last_migration_name .split ("_" , 1 )
156
172
_rebased_number , rebased_rest = rebased_migration_name .split ("_" , 1 )
157
- new_number = int (merged_number ) + 1
173
+ new_number = int (last_merged_number ) + 1
158
174
new_name = str (new_number ).zfill (4 ) + "_" + rebased_rest
159
175
new_path_parts = rebased_migration_path .parts [:- 1 ] + (f"{ new_name } .py" ,)
160
176
new_path = Path (* new_path_parts )
161
177
162
178
rebased_migration_path .rename (new_path )
163
179
new_path .write_text (new_content )
164
- max_migration_txt .write_text (f"{ new_name } \n " )
180
+
181
+ if first_migration :
182
+ max_migration_txt .write_text (f"{ new_name } \n " )
183
+ else :
184
+ current_version_migrations = max_migration_txt .read_text ()
185
+ max_migration_txt .write_text (current_version_migrations + f"{ new_name } \n " )
186
+
187
+ self .last_migration_name = new_name
165
188
166
189
black_path = shutil .which ("black" )
167
190
if black_path : # pragma: no cover
@@ -176,19 +199,45 @@ def handle(self, *args: Any, app_label: str, **options: Any) -> None:
176
199
)
177
200
178
201
179
- def find_migration_names (max_migration_lines : list [str ]) -> tuple [str , str ] | None :
180
- lines = max_migration_lines
181
- if len (lines ) <= 1 :
202
+ def find_migration_names (
203
+ current_version_migrations : str ,
204
+ ) -> tuple [list [str ], list [str ]] | None :
205
+ migrations_lines = current_version_migrations .strip ().splitlines ()
206
+
207
+ if len (migrations_lines ) <= 1 :
182
208
return None
183
- if not lines [0 ].startswith ("<<<<<<<" ):
209
+ if not migrations_lines [0 ].startswith ("<<<<<<<" ):
184
210
return None
185
- if not lines [- 1 ].startswith (">>>>>>>" ):
211
+ if not migrations_lines [- 1 ].startswith (">>>>>>>" ):
186
212
return None
187
- migration_names = (lines [1 ].strip (), lines [- 2 ].strip ())
213
+
214
+ merged_migration_names = []
215
+ rebased_migration_names = []
216
+
217
+ index = 0
218
+ while index < len (migrations_lines ):
219
+ if migrations_lines [index ].startswith ("<<<<<<<" ):
220
+ index += 1
221
+ while not migrations_lines [index ].startswith ("=======" ):
222
+ if migrations_lines [index ] == "|||||||" :
223
+ while not migrations_lines [index ].startswith ("=======" ):
224
+ index += 1
225
+ else :
226
+ merged_migration_names .append (migrations_lines [index ])
227
+ index += 1
228
+
229
+ index += 1
230
+
231
+ else :
232
+ while not migrations_lines [index ].startswith (">>>>>>>" ):
233
+ rebased_migration_names .append (migrations_lines [index ])
234
+ index += 1
235
+ break
236
+
188
237
if is_merge_in_progress ():
189
238
# During the merge 'ours' and 'theirs' are swapped in comparison with rebase
190
- migration_names = ( migration_names [ 1 ], migration_names [ 0 ] )
191
- return migration_names
239
+ return ( rebased_migration_names , merged_migration_names )
240
+ return ( merged_migration_names , rebased_migration_names )
192
241
193
242
194
243
def is_merge_in_progress () -> bool :
0 commit comments