diff --git a/django/core/management/commands/migrate.py b/django/core/management/commands/migrate.py index 1541843066c..3a0e9e87ff8 100644 --- a/django/core/management/commands/migrate.py +++ b/django/core/management/commands/migrate.py @@ -195,8 +195,11 @@ class Command(BaseCommand): ) if self.verbosity > 0: self.stdout.write("Pruning migrations:", self.style.MIGRATE_HEADING) - to_prune = set(executor.loader.applied_migrations) - set( - executor.loader.disk_migrations + to_prune = sorted( + migration + for migration in set(executor.loader.applied_migrations) + - set(executor.loader.disk_migrations) + if migration[0] == app_label ) squashed_migrations_with_deleted_replaced_migrations = [ migration_key @@ -222,9 +225,6 @@ class Command(BaseCommand): ) ) else: - to_prune = sorted( - migration for migration in to_prune if migration[0] == app_label - ) if to_prune: for migration in to_prune: app, name = migration diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index 1f8b3fb0114..6ef172ee6fa 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -1427,6 +1427,53 @@ class MigrateTests(MigrationTestBase): with self.assertRaisesMessage(CommandError, msg): call_command("migrate", prune=True) + @override_settings( + MIGRATION_MODULES={ + "migrations": "migrations.test_migrations_squashed_no_replaces", + "migrations2": "migrations2.test_migrations_2_squashed_with_replaces", + }, + INSTALLED_APPS=["migrations", "migrations2"], + ) + def test_prune_respect_app_label(self): + recorder = MigrationRecorder(connection) + recorder.record_applied("migrations", "0001_initial") + recorder.record_applied("migrations", "0002_second") + recorder.record_applied("migrations", "0001_squashed_0002") + # Second app has squashed migrations with replaces. + recorder.record_applied("migrations2", "0001_initial") + recorder.record_applied("migrations2", "0002_second") + recorder.record_applied("migrations2", "0001_squashed_0002") + out = io.StringIO() + try: + call_command("migrate", "migrations", prune=True, stdout=out, no_color=True) + self.assertEqual( + out.getvalue(), + "Pruning migrations:\n" + " Pruning migrations.0001_initial OK\n" + " Pruning migrations.0002_second OK\n", + ) + applied_migrations = [ + migration + for migration in recorder.applied_migrations() + if migration[0] in ["migrations", "migrations2"] + ] + self.assertEqual( + applied_migrations, + [ + ("migrations", "0001_squashed_0002"), + ("migrations2", "0001_initial"), + ("migrations2", "0002_second"), + ("migrations2", "0001_squashed_0002"), + ], + ) + finally: + recorder.record_unapplied("migrations", "0001_initial") + recorder.record_unapplied("migrations", "0001_second") + recorder.record_unapplied("migrations", "0001_squashed_0002") + recorder.record_unapplied("migrations2", "0001_initial") + recorder.record_unapplied("migrations2", "0002_second") + recorder.record_unapplied("migrations2", "0001_squashed_0002") + class MakeMigrationsTests(MigrationTestBase): """ diff --git a/tests/migrations2/test_migrations_2_squashed_with_replaces/0001_squashed_0002.py b/tests/migrations2/test_migrations_2_squashed_with_replaces/0001_squashed_0002.py new file mode 100644 index 00000000000..30700e5eb6e --- /dev/null +++ b/tests/migrations2/test_migrations_2_squashed_with_replaces/0001_squashed_0002.py @@ -0,0 +1,30 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + replaces = [ + ("migrations2", "0001_initial"), + ("migrations2", "0002_second"), + ] + + operations = [ + migrations.CreateModel( + "OtherAuthor", + [ + ("id", models.AutoField(primary_key=True)), + ("name", models.CharField(max_length=255)), + ], + ), + migrations.CreateModel( + "OtherBook", + [ + ("id", models.AutoField(primary_key=True)), + ( + "author", + models.ForeignKey( + "migrations2.OtherAuthor", models.SET_NULL, null=True + ), + ), + ], + ), + ] diff --git a/tests/migrations2/test_migrations_2_squashed_with_replaces/__init__.py b/tests/migrations2/test_migrations_2_squashed_with_replaces/__init__.py new file mode 100644 index 00000000000..e69de29bb2d