summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2014-07-29 10:22:00 -0700
committerAndrew Godwin <andrew@aeracode.org>2014-07-29 10:22:30 -0700
commit8e7fdfdb6fb0e910d5b507ba2da56a297bfba25c (patch)
tree11be4d2a845e9c0fa45b4a656b24c7dd26213790
parentcc875e94cf6c18530595a59e91ecd23f5c961146 (diff)
[1.7.x] Fixed #23092: Squashing handles external dependencies
-rw-r--r--django/core/management/commands/squashmigrations.py17
-rw-r--r--django/db/migrations/migration.py14
2 files changed, 28 insertions, 3 deletions
diff --git a/django/core/management/commands/squashmigrations.py b/django/core/management/commands/squashmigrations.py
index 8795947296..ece5acb69e 100644
--- a/django/core/management/commands/squashmigrations.py
+++ b/django/core/management/commands/squashmigrations.py
@@ -3,11 +3,13 @@ from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from django.utils import six
+from django.conf import settings
from django.db import connections, DEFAULT_DB_ALIAS, migrations
from django.db.migrations.loader import AmbiguityError
from django.db.migrations.executor import MigrationExecutor
from django.db.migrations.writer import MigrationWriter
from django.db.migrations.optimizer import MigrationOptimizer
+from django.db.migrations.migration import SwappableTuple
class Command(BaseCommand):
@@ -67,12 +69,23 @@ class Command(BaseCommand):
if answer != "y":
return
- # Load the operations from all those migrations and concat together
+ # Load the operations from all those migrations and concat together,
+ # along with collecting external dependencies and detecting
+ # double-squashing
operations = []
+ dependencies = set()
for smigration in migrations_to_squash:
if smigration.replaces:
raise CommandError("You cannot squash squashed migrations! Please transition it to a normal migration first: https://docs.djangoproject.com/en/1.7/topics/migrations/#squashing-migrations")
operations.extend(smigration.operations)
+ for dependency in smigration.dependencies:
+ if isinstance(dependency, SwappableTuple):
+ if settings.AUTH_USER_MODEL == dependency.setting:
+ dependencies.add(("__setting__", "AUTH_USER_MODEL"))
+ else:
+ dependencies.add(dependency)
+ elif dependency[0] != smigration.app_label:
+ dependencies.add(dependency)
if self.verbosity > 0:
self.stdout.write(self.style.MIGRATE_HEADING("Optimizing..."))
@@ -97,7 +110,7 @@ class Command(BaseCommand):
# Make a new migration with those operations
subclass = type("Migration", (migrations.Migration, ), {
- "dependencies": [],
+ "dependencies": dependencies,
"operations": new_operations,
"replaces": replaces,
})
diff --git a/django/db/migrations/migration.py b/django/db/migrations/migration.py
index 708de5393d..34878b459e 100644
--- a/django/db/migrations/migration.py
+++ b/django/db/migrations/migration.py
@@ -146,8 +146,20 @@ class Migration(object):
return project_state
+class SwappableTuple(tuple):
+ """
+ Subclass of tuple so Django can tell this was originally a swappable
+ dependency when it reads the migration file.
+ """
+
+ def __new__(cls, value, setting):
+ self = tuple.__new__(cls, value)
+ self.setting = setting
+ return self
+
+
def swappable_dependency(value):
"""
Turns a setting value into a dependency.
"""
- return (value.split(".", 1)[0], "__first__")
+ return SwappableTuple((value.split(".", 1)[0], "__first__"), value)