mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
Fixed #25850 -- Made migrate/makemigrations error on inconsistent history.
This commit is contained in:
@@ -5,6 +5,7 @@ from itertools import takewhile
|
||||
|
||||
from django.apps import apps
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db import connections
|
||||
from django.db.migrations import Migration
|
||||
from django.db.migrations.autodetector import MigrationAutodetector
|
||||
from django.db.migrations.loader import MigrationLoader
|
||||
@@ -75,6 +76,10 @@ class Command(BaseCommand):
|
||||
# the loader doesn't try to resolve replaced migrations from DB.
|
||||
loader = MigrationLoader(None, ignore_no_migrations=True)
|
||||
|
||||
# Raise an error if any migrations are applied before their dependencies.
|
||||
for db in connections:
|
||||
loader.check_consistent_history(connections[db])
|
||||
|
||||
# Before anything else, see if there's conflicting apps and drop out
|
||||
# hard if there are any and they don't want to merge
|
||||
conflicts = loader.detect_conflicts()
|
||||
|
||||
@@ -65,6 +65,9 @@ class Command(BaseCommand):
|
||||
# Work out which apps have migrations and which do not
|
||||
executor = MigrationExecutor(connection, self.migration_progress_callback)
|
||||
|
||||
# Raise an error if any migrations are applied before their dependencies.
|
||||
executor.loader.check_consistent_history(connection)
|
||||
|
||||
# Before anything else, see if there's conflicting apps and drop out
|
||||
# hard if there are any
|
||||
conflicts = executor.loader.detect_conflicts()
|
||||
|
||||
@@ -25,6 +25,13 @@ class CircularDependencyError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class InconsistentMigrationHistory(Exception):
|
||||
"""
|
||||
Raised when an applied migration has some of its dependencies not applied.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidBasesError(ValueError):
|
||||
"""
|
||||
Raised when a model's base classes can't be resolved.
|
||||
|
||||
@@ -10,7 +10,10 @@ from django.db.migrations.graph import MigrationGraph
|
||||
from django.db.migrations.recorder import MigrationRecorder
|
||||
from django.utils import six
|
||||
|
||||
from .exceptions import AmbiguityError, BadMigrationError, NodeNotFoundError
|
||||
from .exceptions import (
|
||||
AmbiguityError, BadMigrationError, InconsistentMigrationHistory,
|
||||
NodeNotFoundError,
|
||||
)
|
||||
|
||||
MIGRATIONS_MODULE_NAME = 'migrations'
|
||||
|
||||
@@ -318,6 +321,25 @@ class MigrationLoader(object):
|
||||
# "child" is not in there.
|
||||
_reraise_missing_dependency(migration, child, e)
|
||||
|
||||
def check_consistent_history(self, connection):
|
||||
"""
|
||||
Raise InconsistentMigrationHistory if any applied migrations have
|
||||
unapplied dependencies.
|
||||
"""
|
||||
recorder = MigrationRecorder(connection)
|
||||
applied = recorder.applied_migrations()
|
||||
for migration in applied:
|
||||
# If the migration is unknown, skip it.
|
||||
if migration not in self.graph.nodes:
|
||||
continue
|
||||
for parent in self.graph.node_map[migration].parents:
|
||||
if parent not in applied:
|
||||
raise InconsistentMigrationHistory(
|
||||
"Migration {}.{} is applied before its dependency {}.{}".format(
|
||||
migration[0], migration[1], parent[0], parent[1],
|
||||
)
|
||||
)
|
||||
|
||||
def detect_conflicts(self):
|
||||
"""
|
||||
Looks through the loaded graph and detects any conflicts - apps
|
||||
|
||||
Reference in New Issue
Block a user