Passed around the state between migrations

Refs #23745.
This commit is contained in:
Claude Paroz 2014-10-26 18:30:58 +01:00
parent 285bd02c92
commit 2a9c4b4901
2 changed files with 17 additions and 10 deletions

View File

@ -63,11 +63,14 @@ class MigrationExecutor(object):
""" """
if plan is None: if plan is None:
plan = self.migration_plan(targets) plan = self.migration_plan(targets)
state = None
for migration, backwards in plan: for migration, backwards in plan:
if state is None:
state = self.loader.project_state((migration.app_label, migration.name), at_end=False)
if not backwards: if not backwards:
self.apply_migration(migration, fake=fake) state = self.apply_migration(state, migration, fake=fake)
else: else:
self.unapply_migration(migration, fake=fake) state = self.unapply_migration(state, migration, fake=fake)
def collect_sql(self, plan): def collect_sql(self, plan):
""" """
@ -75,17 +78,19 @@ class MigrationExecutor(object):
statements that represent the best-efforts version of that plan. statements that represent the best-efforts version of that plan.
""" """
statements = [] statements = []
state = None
for migration, backwards in plan: for migration, backwards in plan:
with self.connection.schema_editor(collect_sql=True) as schema_editor: with self.connection.schema_editor(collect_sql=True) as schema_editor:
project_state = self.loader.project_state((migration.app_label, migration.name), at_end=False) if state is None:
state = self.loader.project_state((migration.app_label, migration.name), at_end=False)
if not backwards: if not backwards:
migration.apply(project_state, schema_editor, collect_sql=True) state = migration.apply(state, schema_editor, collect_sql=True)
else: else:
migration.unapply(project_state, schema_editor, collect_sql=True) state = migration.unapply(state, schema_editor, collect_sql=True)
statements.extend(schema_editor.collected_sql) statements.extend(schema_editor.collected_sql)
return statements return statements
def apply_migration(self, migration, fake=False): def apply_migration(self, state, migration, fake=False):
""" """
Runs a migration forwards. Runs a migration forwards.
""" """
@ -93,7 +98,7 @@ class MigrationExecutor(object):
self.progress_callback("apply_start", migration, fake) self.progress_callback("apply_start", migration, fake)
if not fake: if not fake:
# Test to see if this is an already-applied initial migration # Test to see if this is an already-applied initial migration
if self.detect_soft_applied(migration): if self.detect_soft_applied(state, migration):
fake = True fake = True
else: else:
# Alright, do it normally # Alright, do it normally
@ -109,8 +114,9 @@ class MigrationExecutor(object):
# Report progress # Report progress
if self.progress_callback: if self.progress_callback:
self.progress_callback("apply_success", migration, fake) self.progress_callback("apply_success", migration, fake)
return state
def unapply_migration(self, migration, fake=False): def unapply_migration(self, state, migration, fake=False):
""" """
Runs a migration backwards. Runs a migration backwards.
""" """
@ -129,8 +135,9 @@ class MigrationExecutor(object):
# Report progress # Report progress
if self.progress_callback: if self.progress_callback:
self.progress_callback("unapply_success", migration, fake) self.progress_callback("unapply_success", migration, fake)
return state
def detect_soft_applied(self, migration): def detect_soft_applied(self, project_state, migration):
""" """
Tests whether a migration has been implicitly applied - that the Tests whether a migration has been implicitly applied - that the
tables it would create exist. This is intended only for use tables it would create exist. This is intended only for use

View File

@ -223,7 +223,7 @@ class ExecutorTests(MigrationTestBase):
global_apps.get_app_config("migrations").models["author"] = migrations_apps.get_model("migrations", "author") global_apps.get_app_config("migrations").models["author"] = migrations_apps.get_model("migrations", "author")
try: try:
migration = executor.loader.get_migration("auth", "0001_initial") migration = executor.loader.get_migration("auth", "0001_initial")
self.assertEqual(executor.detect_soft_applied(migration), True) self.assertEqual(executor.detect_soft_applied(None, migration), True)
finally: finally:
connection.introspection.table_names = old_table_names connection.introspection.table_names = old_table_names
del global_apps.get_app_config("migrations").models["author"] del global_apps.get_app_config("migrations").models["author"]