mirror of https://github.com/django/django.git
Fixed #31318 -- Allowed sqlmigrate to inspect squashed migrations.
This commit is contained in:
parent
271e108b29
commit
d88365708c
|
@ -32,8 +32,9 @@ class Command(BaseCommand):
|
||||||
# Get the database we're operating from
|
# Get the database we're operating from
|
||||||
connection = connections[options['database']]
|
connection = connections[options['database']]
|
||||||
|
|
||||||
# Load up an loader to get all the migration data
|
# Load up an loader to get all the migration data, but don't replace
|
||||||
loader = MigrationLoader(connection)
|
# migrations.
|
||||||
|
loader = MigrationLoader(connection, replace_migrations=False)
|
||||||
|
|
||||||
# Resolve command-line arguments into a migration
|
# Resolve command-line arguments into a migration
|
||||||
app_label, migration_name = options['app_label'], options['migration_name']
|
app_label, migration_name = options['app_label'], options['migration_name']
|
||||||
|
|
|
@ -40,11 +40,15 @@ class MigrationLoader:
|
||||||
in memory.
|
in memory.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, connection, load=True, ignore_no_migrations=False):
|
def __init__(
|
||||||
|
self, connection, load=True, ignore_no_migrations=False,
|
||||||
|
replace_migrations=True,
|
||||||
|
):
|
||||||
self.connection = connection
|
self.connection = connection
|
||||||
self.disk_migrations = None
|
self.disk_migrations = None
|
||||||
self.applied_migrations = None
|
self.applied_migrations = None
|
||||||
self.ignore_no_migrations = ignore_no_migrations
|
self.ignore_no_migrations = ignore_no_migrations
|
||||||
|
self.replace_migrations = replace_migrations
|
||||||
if load:
|
if load:
|
||||||
self.build_graph()
|
self.build_graph()
|
||||||
|
|
||||||
|
@ -223,24 +227,27 @@ class MigrationLoader:
|
||||||
# Add external dependencies now that the internal ones have been resolved.
|
# Add external dependencies now that the internal ones have been resolved.
|
||||||
for key, migration in self.disk_migrations.items():
|
for key, migration in self.disk_migrations.items():
|
||||||
self.add_external_dependencies(key, migration)
|
self.add_external_dependencies(key, migration)
|
||||||
# Carry out replacements where possible.
|
# Carry out replacements where possible and if enabled.
|
||||||
for key, migration in self.replacements.items():
|
if self.replace_migrations:
|
||||||
# Get applied status of each of this migration's replacement targets.
|
for key, migration in self.replacements.items():
|
||||||
applied_statuses = [(target in self.applied_migrations) for target in migration.replaces]
|
# Get applied status of each of this migration's replacement
|
||||||
# Ensure the replacing migration is only marked as applied if all of
|
# targets.
|
||||||
# its replacement targets are.
|
applied_statuses = [(target in self.applied_migrations) for target in migration.replaces]
|
||||||
if all(applied_statuses):
|
# The replacing migration is only marked as applied if all of
|
||||||
self.applied_migrations[key] = migration
|
# its replacement targets are.
|
||||||
else:
|
if all(applied_statuses):
|
||||||
self.applied_migrations.pop(key, None)
|
self.applied_migrations[key] = migration
|
||||||
# A replacing migration can be used if either all or none of its
|
else:
|
||||||
# replacement targets have been applied.
|
self.applied_migrations.pop(key, None)
|
||||||
if all(applied_statuses) or (not any(applied_statuses)):
|
# A replacing migration can be used if either all or none of
|
||||||
self.graph.remove_replaced_nodes(key, migration.replaces)
|
# its replacement targets have been applied.
|
||||||
else:
|
if all(applied_statuses) or (not any(applied_statuses)):
|
||||||
# This replacing migration cannot be used because it is partially applied.
|
self.graph.remove_replaced_nodes(key, migration.replaces)
|
||||||
# Remove it from the graph and remap dependencies to it (#25945).
|
else:
|
||||||
self.graph.remove_replacement_node(key, migration.replaces)
|
# This replacing migration cannot be used because it is
|
||||||
|
# partially applied. Remove it from the graph and remap
|
||||||
|
# dependencies to it (#25945).
|
||||||
|
self.graph.remove_replacement_node(key, migration.replaces)
|
||||||
# Ensure the graph is consistent.
|
# Ensure the graph is consistent.
|
||||||
try:
|
try:
|
||||||
self.graph.validate_consistency()
|
self.graph.validate_consistency()
|
||||||
|
|
|
@ -713,6 +713,14 @@ class MigrateTests(MigrationTestBase):
|
||||||
self.assertIn('-- create model book', output)
|
self.assertIn('-- create model book', output)
|
||||||
self.assertNotIn('-- create model tribble', output)
|
self.assertNotIn('-- create model tribble', output)
|
||||||
|
|
||||||
|
@override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'})
|
||||||
|
def test_sqlmigrate_replaced_migration(self):
|
||||||
|
out = io.StringIO()
|
||||||
|
call_command('sqlmigrate', 'migrations', '0001_initial', stdout=out)
|
||||||
|
output = out.getvalue().lower()
|
||||||
|
self.assertIn('-- create model author', output)
|
||||||
|
self.assertIn('-- create model tribble', output)
|
||||||
|
|
||||||
@override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_no_operations'})
|
@override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_no_operations'})
|
||||||
def test_migrations_no_operations(self):
|
def test_migrations_no_operations(self):
|
||||||
err = io.StringIO()
|
err = io.StringIO()
|
||||||
|
|
Loading…
Reference in New Issue