summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Wobrock <david.wobrock@gmail.com>2020-03-08 22:48:59 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-03-09 08:42:30 +0100
commitd88365708c554efe3c786c3be6da1d9de916360f (patch)
treecd78f461047e6bc75b8d285d68d5e6497122383b
parent271e108b29a1c280f20251b035fb8ca9a202b249 (diff)
Fixed #31318 -- Allowed sqlmigrate to inspect squashed migrations.
-rw-r--r--django/core/management/commands/sqlmigrate.py5
-rw-r--r--django/db/migrations/loader.py45
-rw-r--r--tests/migrations/test_commands.py8
3 files changed, 37 insertions, 21 deletions
diff --git a/django/core/management/commands/sqlmigrate.py b/django/core/management/commands/sqlmigrate.py
index 2acb789c00..aee793fc14 100644
--- a/django/core/management/commands/sqlmigrate.py
+++ b/django/core/management/commands/sqlmigrate.py
@@ -32,8 +32,9 @@ class Command(BaseCommand):
# Get the database we're operating from
connection = connections[options['database']]
- # Load up an loader to get all the migration data
- loader = MigrationLoader(connection)
+ # Load up an loader to get all the migration data, but don't replace
+ # migrations.
+ loader = MigrationLoader(connection, replace_migrations=False)
# Resolve command-line arguments into a migration
app_label, migration_name = options['app_label'], options['migration_name']
diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py
index d41f6d3606..80945d0ffd 100644
--- a/django/db/migrations/loader.py
+++ b/django/db/migrations/loader.py
@@ -40,11 +40,15 @@ class MigrationLoader:
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.disk_migrations = None
self.applied_migrations = None
self.ignore_no_migrations = ignore_no_migrations
+ self.replace_migrations = replace_migrations
if load:
self.build_graph()
@@ -223,24 +227,27 @@ class MigrationLoader:
# Add external dependencies now that the internal ones have been resolved.
for key, migration in self.disk_migrations.items():
self.add_external_dependencies(key, migration)
- # Carry out replacements where possible.
- for key, migration in self.replacements.items():
- # Get applied status of each of this migration's replacement targets.
- applied_statuses = [(target in self.applied_migrations) for target in migration.replaces]
- # Ensure the replacing migration is only marked as applied if all of
- # its replacement targets are.
- if all(applied_statuses):
- self.applied_migrations[key] = migration
- else:
- self.applied_migrations.pop(key, None)
- # A replacing migration can be used if either all or none of its
- # replacement targets have been applied.
- if all(applied_statuses) or (not any(applied_statuses)):
- self.graph.remove_replaced_nodes(key, migration.replaces)
- else:
- # 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)
+ # Carry out replacements where possible and if enabled.
+ if self.replace_migrations:
+ for key, migration in self.replacements.items():
+ # Get applied status of each of this migration's replacement
+ # targets.
+ applied_statuses = [(target in self.applied_migrations) for target in migration.replaces]
+ # The replacing migration is only marked as applied if all of
+ # its replacement targets are.
+ if all(applied_statuses):
+ self.applied_migrations[key] = migration
+ else:
+ self.applied_migrations.pop(key, None)
+ # A replacing migration can be used if either all or none of
+ # its replacement targets have been applied.
+ if all(applied_statuses) or (not any(applied_statuses)):
+ self.graph.remove_replaced_nodes(key, migration.replaces)
+ else:
+ # 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.
try:
self.graph.validate_consistency()
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 7fd1a68422..14c09c8f98 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -713,6 +713,14 @@ class MigrateTests(MigrationTestBase):
self.assertIn('-- create model book', 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'})
def test_migrations_no_operations(self):
err = io.StringIO()