diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py index d6af5cd4dc..db011f9802 100644 --- a/django/core/management/commands/makemigrations.py +++ b/django/core/management/commands/makemigrations.py @@ -1,5 +1,6 @@ import os import sys +import warnings from itertools import takewhile from django.apps import apps @@ -13,6 +14,7 @@ from django.db.migrations.questioner import ( ) from django.db.migrations.state import ProjectState from django.db.migrations.writer import MigrationWriter +from django.utils.deprecation import RemovedInDjango20Warning from django.utils.six import iteritems from django.utils.six.moves import zip @@ -35,10 +37,12 @@ class Command(BaseCommand): parser.add_argument('-n', '--name', action='store', dest='name', default=None, help="Use this name for migration file(s).") parser.add_argument('-e', '--exit', action='store_true', dest='exit_code', default=False, - help='Exit with error code 1 if no changes needing migrations are found.') + help='Exit with error code 1 if no changes needing migrations are found. ' + 'Deprecated, use the --check option instead.') + parser.add_argument('--check', action='store_true', dest='check_changes', + help='Exit with a non-zero status if model changes are missing migrations.') def handle(self, *app_labels, **options): - self.verbosity = options.get('verbosity') self.interactive = options.get('interactive') self.dry_run = options.get('dry_run', False) @@ -46,6 +50,13 @@ class Command(BaseCommand): self.empty = options.get('empty', False) self.migration_name = options.get('name') self.exit_code = options.get('exit_code', False) + check_changes = options['check_changes'] + + if self.exit_code: + warnings.warn( + "The --exit option is deprecated in favor of the --check option.", + RemovedInDjango20Warning + ) # Make sure the app they asked for exists app_labels = set(app_labels) @@ -144,10 +155,10 @@ class Command(BaseCommand): if self.exit_code: sys.exit(1) - else: - return - - self.write_migration_files(changes) + else: + self.write_migration_files(changes) + if check_changes: + sys.exit(1) def write_migration_files(self, changes): """ diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 5a4d2c6526..39daa0c002 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -104,6 +104,11 @@ details on these changes. ``django.template.base.StringOrigin`` aliases for ``django.template.base.Origin`` will be removed. +See the :ref:`Django 1.10 release notes ` for more +details on these changes. + +* The ``makemigrations --exit`` option will be removed. + .. _deprecation-removed-in-1.10: 1.10 diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 27a1a31423..8d45439300 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -699,10 +699,21 @@ of a generated one. .. django-admin-option:: --exit, -e +.. deprecated:: 1.10 + + Use the :djadminopt:`--check` option instead. + The ``--exit`` option will cause ``makemigrations`` to exit with error code 1 when no migrations are created (or would have been created, if combined with ``--dry-run``). +.. django-admin-option:: --check + +.. versionadded:: 1.10 + +The ``--check`` option makes ``makemigrations`` exit with a non-zero status +when model changes without migrations are detected. + migrate [ []] --------------------------------------- diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index c955b7764d..16e7d2ea28 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -157,6 +157,10 @@ Management Commands allows specifying the message level that will cause the command to exit with a non-zero status. +* The new :djadminopt:`makemigrations --check <--check>` option makes the + command exit with a non-zero status when model changes without migrations are + detected. + Migrations ^^^^^^^^^^ @@ -268,7 +272,8 @@ Features deprecated in 1.10 Miscellaneous ~~~~~~~~~~~~~ -* ... +* The ``makemigrations --exit`` option is deprecated in favor of the + :djadminopt:`--check` option. .. _removed-features-1.10: diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index 465152a8e0..a95d26b071 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -9,8 +9,9 @@ from django.apps import apps from django.core.management import CommandError, call_command from django.db import DatabaseError, connection, models from django.db.migrations.recorder import MigrationRecorder -from django.test import mock, override_settings +from django.test import ignore_warnings, mock, override_settings from django.utils import six +from django.utils.deprecation import RemovedInDjango20Warning from django.utils.encoding import force_text from .models import UnicodeModel, UnserializableModel @@ -983,6 +984,7 @@ class MakeMigrationsTests(MigrationTestBase): self.assertIn("dependencies=[\n('migrations','0001_%s'),\n]" % migration_name_0001, content) self.assertIn("operations=[\n]", content) + @ignore_warnings(category=RemovedInDjango20Warning) def test_makemigrations_exit(self): """ makemigrations --exit should exit with sys.exit(1) when there are no @@ -995,6 +997,18 @@ class MakeMigrationsTests(MigrationTestBase): with self.assertRaises(SystemExit): call_command("makemigrations", "--exit", "migrations", verbosity=0) + def test_makemigrations_check(self): + """ + makemigrations --check should exit with a non-zero status when + there are changes to an app requiring migrations. + """ + with self.temporary_migration_module(): + with self.assertRaises(SystemExit): + call_command("makemigrations", "--check", "migrations", verbosity=0) + + with self.temporary_migration_module(module="migrations.test_migrations_no_changes"): + call_command("makemigrations", "--check", "migrations", verbosity=0) + class SquashMigrationsTests(MigrationTestBase): """