|
@@ -63,6 +63,9 @@ class MigrationExecutor(object):
|
|
|
applied.add(migration)
|
|
|
return plan
|
|
|
|
|
|
+ def _create_project_state(self):
|
|
|
+ return ProjectState(real_apps=list(self.loader.unmigrated_apps))
|
|
|
+
|
|
|
def migrate(self, targets, plan=None, fake=False, fake_initial=False):
|
|
|
"""
|
|
|
Migrates the database up to the given targets.
|
|
@@ -79,7 +82,9 @@ class MigrationExecutor(object):
|
|
|
all_backwards = all(backwards for mig, backwards in plan)
|
|
|
|
|
|
if not plan:
|
|
|
- pass
|
|
|
+
|
|
|
+
|
|
|
+ state = self._create_project_state()
|
|
|
elif all_forwards == all_backwards:
|
|
|
|
|
|
raise InvalidMigrationPlan(
|
|
@@ -89,21 +94,27 @@ class MigrationExecutor(object):
|
|
|
plan
|
|
|
)
|
|
|
elif all_forwards:
|
|
|
- self._migrate_all_forwards(plan, full_plan, fake=fake, fake_initial=fake_initial)
|
|
|
+ state = self._migrate_all_forwards(plan, full_plan, fake=fake, fake_initial=fake_initial)
|
|
|
else:
|
|
|
|
|
|
|
|
|
- self._migrate_all_backwards(plan, full_plan, fake=fake)
|
|
|
+ state = self._migrate_all_backwards(plan, full_plan, fake=fake)
|
|
|
|
|
|
self.check_replacements()
|
|
|
|
|
|
+ return state
|
|
|
+
|
|
|
def _migrate_all_forwards(self, plan, full_plan, fake, fake_initial):
|
|
|
"""
|
|
|
Take a list of 2-tuples of the form (migration instance, False) and
|
|
|
apply them in the order they occur in the full_plan.
|
|
|
"""
|
|
|
migrations_to_run = {m[0] for m in plan}
|
|
|
- state = ProjectState(real_apps=list(self.loader.unmigrated_apps))
|
|
|
+ state = self._create_project_state()
|
|
|
+ applied_migrations = {
|
|
|
+ self.loader.graph.nodes[key] for key in self.loader.applied_migrations
|
|
|
+ if key in self.loader.graph.nodes
|
|
|
+ }
|
|
|
for migration, _ in full_plan:
|
|
|
if not migrations_to_run:
|
|
|
|
|
@@ -120,9 +131,14 @@ class MigrationExecutor(object):
|
|
|
self.progress_callback("render_success")
|
|
|
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
|
|
|
migrations_to_run.remove(migration)
|
|
|
- else:
|
|
|
+ elif migration in applied_migrations:
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
migration.mutate_state(state, preserve=False)
|
|
|
|
|
|
+ return state
|
|
|
+
|
|
|
def _migrate_all_backwards(self, plan, full_plan, fake):
|
|
|
"""
|
|
|
Take a list of 2-tuples of the form (migration instance, True) and
|
|
@@ -136,7 +152,11 @@ class MigrationExecutor(object):
|
|
|
migrations_to_run = {m[0] for m in plan}
|
|
|
|
|
|
states = {}
|
|
|
- state = ProjectState(real_apps=list(self.loader.unmigrated_apps))
|
|
|
+ state = self._create_project_state()
|
|
|
+ applied_migrations = {
|
|
|
+ self.loader.graph.nodes[key] for key in self.loader.applied_migrations
|
|
|
+ if key in self.loader.graph.nodes
|
|
|
+ }
|
|
|
if self.progress_callback:
|
|
|
self.progress_callback("render_start")
|
|
|
for migration, _ in full_plan:
|
|
@@ -154,13 +174,31 @@ class MigrationExecutor(object):
|
|
|
|
|
|
state = migration.mutate_state(state, preserve=True)
|
|
|
migrations_to_run.remove(migration)
|
|
|
- else:
|
|
|
+ elif migration in applied_migrations:
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
migration.mutate_state(state, preserve=False)
|
|
|
if self.progress_callback:
|
|
|
self.progress_callback("render_success")
|
|
|
|
|
|
for migration, _ in plan:
|
|
|
self.unapply_migration(states[migration], migration, fake=fake)
|
|
|
+ applied_migrations.remove(migration)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ last_unapplied_migration = plan[-1][0]
|
|
|
+ state = states[last_unapplied_migration]
|
|
|
+ for index, (migration, _) in enumerate(full_plan):
|
|
|
+ if migration == last_unapplied_migration:
|
|
|
+ for migration, _ in full_plan[index:]:
|
|
|
+ if migration in applied_migrations:
|
|
|
+ migration.mutate_state(state, preserve=False)
|
|
|
+ break
|
|
|
+
|
|
|
+ return state
|
|
|
|
|
|
def collect_sql(self, plan):
|
|
|
"""
|