Fixed #29063 -- Fixed migrate crash when specifying a name of partially applied squashed migrations.

This commit is contained in:
Jacob Walls 2021-08-02 11:07:58 -04:00 committed by Mariusz Felisiak
parent 202d3e193a
commit 910ecd1b8d
2 changed files with 38 additions and 1 deletions

View File

@ -140,7 +140,16 @@ class Command(BaseCommand):
except KeyError: except KeyError:
raise CommandError("Cannot find a migration matching '%s' from app '%s'." % ( raise CommandError("Cannot find a migration matching '%s' from app '%s'." % (
migration_name, app_label)) migration_name, app_label))
targets = [(app_label, migration.name)] target = (app_label, migration.name)
# Partially applied squashed migrations are not included in the
# graph, use the last replacement instead.
if (
target not in executor.loader.graph.nodes and
target in executor.loader.replacements
):
incomplete_migration = executor.loader.replacements[target]
target = incomplete_migration.replaces[-1]
targets = [target]
target_app_labels_only = False target_app_labels_only = False
elif options['app_label']: elif options['app_label']:
targets = [key for key in executor.loader.graph.leaf_nodes() if key[0] == app_label] targets = [key for key in executor.loader.graph.leaf_nodes() if key[0] == app_label]

View File

@ -951,6 +951,34 @@ class MigrateTests(MigrationTestBase):
) )
# No changes were actually applied so there is nothing to rollback # No changes were actually applied so there is nothing to rollback
def test_migrate_partially_applied_squashed_migration(self):
"""
Migrating to a squashed migration specified by name should succeed
even if it is partially applied.
"""
with self.temporary_migration_module(module='migrations.test_migrations'):
recorder = MigrationRecorder(connection)
try:
call_command('migrate', 'migrations', '0001_initial', verbosity=0)
call_command(
'squashmigrations',
'migrations',
'0002',
interactive=False,
verbosity=0,
)
call_command(
'migrate',
'migrations',
'0001_squashed_0002_second',
verbosity=0,
)
applied_migrations = recorder.applied_migrations()
self.assertIn(('migrations', '0002_second'), applied_migrations)
finally:
# Unmigrate everything.
call_command('migrate', 'migrations', 'zero', verbosity=0)
@override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'}) @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'})
def test_migrate_inconsistent_history(self): def test_migrate_inconsistent_history(self):
""" """