Commit 02ae5fd3 authored by Attila Tovt's avatar Attila Tovt Committed by Tim Graham
Browse files

Fixed #25850 -- Made migrate/makemigrations error on inconsistent history.

parent 64488731
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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()
+3 −0
Original line number Diff line number Diff line
@@ -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()
+7 −0
Original line number Diff line number Diff line
@@ -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.
+23 −1
Original line number Diff line number Diff line
@@ -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
+4 −0
Original line number Diff line number Diff line
@@ -323,6 +323,10 @@ Migrations
* Added support for :ref:`non-atomic migrations <non-atomic-migrations>` by
  setting the ``atomic`` attribute on a ``Migration``.

* The ``migrate`` and ``makemigrations`` commands now check for a consistent
  migration history. If they find some unapplied dependencies of an applied
  migration, ``InconsistentMigrationHistory`` is raised.

Models
~~~~~~

Loading