Fixed #27044 -- Included already applied migration changes in the post-migrate state when the execution plan is empty.
Refs #24100. Thanks tkhyn for the report and Tim for the review.
This commit is contained in:
parent
ad25fe7350
commit
d1757d8df4
|
@ -175,7 +175,6 @@ class Command(BaseCommand):
|
||||||
if self.verbosity >= 1:
|
if self.verbosity >= 1:
|
||||||
self.stdout.write(self.style.MIGRATE_HEADING("Running migrations:"))
|
self.stdout.write(self.style.MIGRATE_HEADING("Running migrations:"))
|
||||||
if not plan:
|
if not plan:
|
||||||
executor.check_replacements()
|
|
||||||
if self.verbosity >= 1:
|
if self.verbosity >= 1:
|
||||||
self.stdout.write(" No migrations to apply.")
|
self.stdout.write(" No migrations to apply.")
|
||||||
# If there's changes that aren't in migrations yet, tell them how to fix it.
|
# If there's changes that aren't in migrations yet, tell them how to fix it.
|
||||||
|
@ -194,14 +193,15 @@ class Command(BaseCommand):
|
||||||
"migrations, and then re-run 'manage.py migrate' to "
|
"migrations, and then re-run 'manage.py migrate' to "
|
||||||
"apply them."
|
"apply them."
|
||||||
))
|
))
|
||||||
post_migrate_apps = pre_migrate_apps
|
fake = False
|
||||||
|
fake_initial = False
|
||||||
else:
|
else:
|
||||||
fake = options['fake']
|
fake = options['fake']
|
||||||
fake_initial = options['fake_initial']
|
fake_initial = options['fake_initial']
|
||||||
post_migrate_project_state = executor.migrate(
|
post_migrate_project_state = executor.migrate(
|
||||||
targets, plan, fake=fake, fake_initial=fake_initial
|
targets, plan, fake=fake, fake_initial=fake_initial
|
||||||
)
|
)
|
||||||
post_migrate_apps = post_migrate_project_state.apps
|
post_migrate_apps = post_migrate_project_state.apps
|
||||||
|
|
||||||
# Re-render models of real apps to include relationships now that
|
# Re-render models of real apps to include relationships now that
|
||||||
# we've got a final state. This wouldn't be necessary if real apps
|
# we've got a final state. This wouldn't be necessary if real apps
|
||||||
|
|
|
@ -82,9 +82,15 @@ class MigrationExecutor(object):
|
||||||
all_backwards = all(backwards for mig, backwards in plan)
|
all_backwards = all(backwards for mig, backwards in plan)
|
||||||
|
|
||||||
if not plan:
|
if not plan:
|
||||||
# Nothing to do for an empty plan, except for building the post
|
# The resulting state should include applied migrations.
|
||||||
# migrate project state
|
|
||||||
state = self._create_project_state()
|
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 migration in applied_migrations:
|
||||||
|
migration.mutate_state(state, preserve=False)
|
||||||
elif all_forwards == all_backwards:
|
elif all_forwards == all_backwards:
|
||||||
# This should only happen if there's a mixed plan
|
# This should only happen if there's a mixed plan
|
||||||
raise InvalidMigrationPlan(
|
raise InvalidMigrationPlan(
|
||||||
|
|
|
@ -68,3 +68,7 @@ Bugfixes
|
||||||
|
|
||||||
* Added the database alias to the ``InconsistentMigrationHistory`` message
|
* Added the database alias to the ``InconsistentMigrationHistory`` message
|
||||||
raised by ``makemigrations`` and ``migrate`` (:ticket:`27089`).
|
raised by ``makemigrations`` and ``migrate`` (:ticket:`27089`).
|
||||||
|
|
||||||
|
* Fixed the creation of ``ContentType`` and ``Permission`` objects for models
|
||||||
|
of applications without migrations when calling the ``migrate`` command with
|
||||||
|
no migrations to apply (:ticket:`27044`).
|
||||||
|
|
|
@ -113,3 +113,13 @@ class MigrateSignalTests(TransactionTestCase):
|
||||||
[model._meta.label for model in post_migrate_receiver.call_args['apps'].get_models()],
|
[model._meta.label for model in post_migrate_receiver.call_args['apps'].get_models()],
|
||||||
['migrate_signals.Signal']
|
['migrate_signals.Signal']
|
||||||
)
|
)
|
||||||
|
# Migrating with an empty plan.
|
||||||
|
post_migrate_receiver = Receiver(signals.post_migrate)
|
||||||
|
management.call_command(
|
||||||
|
'migrate', database=MIGRATE_DATABASE, verbosity=MIGRATE_VERBOSITY,
|
||||||
|
interactive=MIGRATE_INTERACTIVE, stdout=stdout,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
[model._meta.label for model in post_migrate_receiver.call_args['apps'].get_models()],
|
||||||
|
['migrate_signals.Signal']
|
||||||
|
)
|
||||||
|
|
|
@ -168,6 +168,14 @@ class ExecutorTests(MigrationTestBase):
|
||||||
("migrations2", "0001_initial"),
|
("migrations2", "0001_initial"),
|
||||||
])
|
])
|
||||||
self.assertEqual(plan, [])
|
self.assertEqual(plan, [])
|
||||||
|
# The resulting state should include applied migrations.
|
||||||
|
state = executor.migrate([
|
||||||
|
("migrations", "0002_second"),
|
||||||
|
("migrations2", "0001_initial"),
|
||||||
|
])
|
||||||
|
self.assertIn(('migrations', 'book'), state.models)
|
||||||
|
self.assertIn(('migrations', 'author'), state.models)
|
||||||
|
self.assertIn(('migrations2', 'otherauthor'), state.models)
|
||||||
# Erase all the fake records
|
# Erase all the fake records
|
||||||
executor.recorder.record_unapplied("migrations2", "0001_initial")
|
executor.recorder.record_unapplied("migrations2", "0001_initial")
|
||||||
executor.recorder.record_unapplied("migrations", "0002_second")
|
executor.recorder.record_unapplied("migrations", "0002_second")
|
||||||
|
|
Loading…
Reference in New Issue