Skip to content

Commit b07298a

Browse files
Fixed #36141 -- Checked for applied replaced migrations recursively.
Regression in 64b1ac7.
1 parent 3c005b5 commit b07298a

3 files changed

Lines changed: 71 additions & 7 deletions

File tree

django/db/migrations/executor.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,7 @@ def check_replacements(self):
304304
"""
305305
applied = self.recorder.applied_migrations()
306306
for key, migration in self.loader.replacements.items():
307-
all_applied = all(m in applied for m in migration.replaces)
308-
if all_applied and key not in applied:
307+
if key not in applied and self.loader.all_replaced_applied(key, applied):
309308
self.recorder.record_applied(*key)
310309

311310
def detect_soft_applied(self, project_state, migration):

django/db/migrations/loader.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,11 +356,8 @@ def check_consistent_history(self, connection):
356356
if parent not in applied:
357357
# Skip unapplied squashed migrations that have all of their
358358
# `replaces` applied.
359-
if parent in self.replacements:
360-
if all(
361-
m in applied for m in self.replacements[parent].replaces
362-
):
363-
continue
359+
if self.all_replaced_applied(parent.key, applied):
360+
continue
364361
raise InconsistentMigrationHistory(
365362
"Migration {}.{} is applied before its dependency "
366363
"{}.{} on database '{}'.".format(
@@ -372,6 +369,20 @@ def check_consistent_history(self, connection):
372369
)
373370
)
374371

372+
def all_replaced_applied(self, migration_key, applied):
373+
"""
374+
Checks (recursively) whether all replaced migrations are applied.
375+
"""
376+
if migration_key in self.replacements:
377+
for replaced_key in self.replacements[migration_key].replaces:
378+
if replaced_key not in applied and not self.all_replaced_applied(
379+
replaced_key, applied
380+
):
381+
return False
382+
return True
383+
384+
return False
385+
375386
def detect_conflicts(self):
376387
"""
377388
Look through the loaded graph and detect any conflicts - apps

tests/migrations/test_commands.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3161,6 +3161,60 @@ def test_double_replaced_migrations_are_recorded(self):
31613161
]
31623162
self.assertNotIn("migrations", applied_app_labels)
31633163

3164+
def test_double_replaced_migrations_are_checked_correctly(self):
3165+
"""
3166+
If replaced migrations are already applied and replacing migrations
3167+
are not, then migrate should not fail with
3168+
InconsistentMigrationHistory.
3169+
"""
3170+
with self.temporary_migration_module():
3171+
call_command(
3172+
"makemigrations",
3173+
"migrations",
3174+
"--empty",
3175+
interactive=False,
3176+
verbosity=0,
3177+
)
3178+
call_command(
3179+
"makemigrations",
3180+
"migrations",
3181+
"--empty",
3182+
interactive=False,
3183+
verbosity=0,
3184+
)
3185+
call_command(
3186+
"makemigrations",
3187+
"migrations",
3188+
"--empty",
3189+
interactive=False,
3190+
verbosity=0,
3191+
)
3192+
call_command(
3193+
"makemigrations",
3194+
"migrations",
3195+
"--empty",
3196+
interactive=False,
3197+
verbosity=0,
3198+
)
3199+
call_command("migrate", "migrations", interactive=False, verbosity=0)
3200+
call_command(
3201+
"squashmigrations",
3202+
"migrations",
3203+
"0001",
3204+
"0002",
3205+
interactive=False,
3206+
verbosity=0,
3207+
)
3208+
call_command(
3209+
"squashmigrations",
3210+
"migrations",
3211+
"0001_initial_squashed",
3212+
"0003",
3213+
interactive=False,
3214+
verbosity=0,
3215+
)
3216+
call_command("migrate", "migrations", interactive=False, verbosity=0)
3217+
31643218
def test_squashmigrations_initial_attribute(self):
31653219
with self.temporary_migration_module(
31663220
module="migrations.test_migrations"

0 commit comments

Comments
 (0)