summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHuu Nguyen <whoshuu@gmail.com>2014-06-19 12:24:59 -0700
committerTim Graham <timograham@gmail.com>2014-07-14 11:00:49 -0400
commitf7a78f9bba4efd0231aec0326a73fdbd004d1faa (patch)
treededeef3777a304482d88ff119712d30e3e9db0e4
parentefe87d3e48df9b7470a3006eeb7322f12b368fdf (diff)
Fixed #22791 -- Invoke interactive questioner only for conflicts in specified apps.
Thanks bendavis78 for the report and Tim Graham for the review.
-rw-r--r--django/core/management/commands/makemigrations.py9
-rw-r--r--tests/migrations/migrations_test_apps/unspecified_app_with_conflict/__init__.py0
-rw-r--r--tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0001_initial.py30
-rw-r--r--tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_conflicting_second.py20
-rw-r--r--tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_second.py26
-rw-r--r--tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/__init__.py0
-rw-r--r--tests/migrations/migrations_test_apps/unspecified_app_with_conflict/models.py0
-rw-r--r--tests/migrations/test_commands.py46
8 files changed, 131 insertions, 0 deletions
diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py
index 42e57cd17d..b1a9e0c017 100644
--- a/django/core/management/commands/makemigrations.py
+++ b/django/core/management/commands/makemigrations.py
@@ -10,6 +10,7 @@ from django.db.migrations.autodetector import MigrationAutodetector
from django.db.migrations.questioner import MigrationQuestioner, InteractiveMigrationQuestioner
from django.db.migrations.state import ProjectState
from django.db.migrations.writer import MigrationWriter
+from django.utils.six import iteritems
from django.utils.six.moves import reduce
@@ -56,6 +57,14 @@ class Command(BaseCommand):
# 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()
+
+ # If app_labels is specified, filter out conflicting migrations for unspecified apps
+ if app_labels:
+ conflicts = dict(
+ (app_label, conflict) for app_label, conflict in iteritems(conflicts)
+ if app_label in app_labels
+ )
+
if conflicts and not self.merge:
name_str = "; ".join(
"%s in %s" % (", ".join(names), app)
diff --git a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/__init__.py b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/__init__.py
diff --git a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0001_initial.py
new file mode 100644
index 0000000000..581d536814
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0001_initial.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ operations = [
+
+ migrations.CreateModel(
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=255)),
+ ("slug", models.SlugField(null=True)),
+ ("age", models.IntegerField(default=0)),
+ ("silly_field", models.BooleanField(default=False)),
+ ],
+ ),
+
+ migrations.CreateModel(
+ "Tribble",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("fluffy", models.BooleanField(default=True)),
+ ],
+ )
+
+ ]
diff --git a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_conflicting_second.py b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_conflicting_second.py
new file mode 100644
index 0000000000..43e03165e8
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_conflicting_second.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [("unspecified_app_with_conflict", "0001_initial")]
+
+ operations = [
+
+ migrations.CreateModel(
+ "Something",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
+
+ ]
diff --git a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_second.py b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_second.py
new file mode 100644
index 0000000000..cb8cfc96d2
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_second.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [("unspecified_app_with_conflict", "0001_initial")]
+
+ operations = [
+
+ migrations.DeleteModel("Tribble"),
+
+ migrations.RemoveField("Author", "silly_field"),
+
+ migrations.AddField("Author", "rating", models.IntegerField(default=0)),
+
+ migrations.CreateModel(
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
+
+ ]
diff --git a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/__init__.py b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/__init__.py
diff --git a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/models.py b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/models.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/models.py
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 54d18ef371..2090135ffc 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -493,3 +493,49 @@ class MakeMigrationsTests(MigrationTestBase):
if os.path.exists(merge_file):
os.remove(merge_file)
self.assertNotIn("Created new merge migration", stdout.getvalue())
+
+ @override_system_checks([])
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_no_changes"},
+ INSTALLED_APPS=[
+ "migrations",
+ "migrations.migrations_test_apps.unspecified_app_with_conflict"])
+ def test_makemigrations_unspecified_app_with_conflict_no_merge(self):
+ """
+ Makes sure that makemigrations does not raise a CommandError when an
+ unspecified app has conflicting migrations.
+ """
+ try:
+ call_command("makemigrations", "migrations", merge=False, verbosity=0)
+ except CommandError:
+ self.fail("Makemigrations fails resolving conflicts in an unspecified app")
+
+ @override_system_checks([])
+ @override_settings(
+ INSTALLED_APPS=[
+ "migrations.migrations_test_apps.migrated_app",
+ "migrations.migrations_test_apps.unspecified_app_with_conflict"])
+ def test_makemigrations_unspecified_app_with_conflict_merge(self):
+ """
+ Makes sure that makemigrations does not create a merge for an
+ unspecified app even if it has conflicting migrations.
+ """
+ # Monkeypatch interactive questioner to auto accept
+ old_input = questioner.input
+ questioner.input = lambda _: "y"
+ stdout = six.StringIO()
+ merge_file = os.path.join(self.test_dir,
+ 'migrations_test_apps',
+ 'unspecified_app_with_conflict',
+ 'migrations',
+ '0003_merge.py')
+ try:
+ call_command("makemigrations", "migrated_app", merge=True, interactive=True, stdout=stdout)
+ self.assertFalse(os.path.exists(merge_file))
+ self.assertIn("No conflicts detected to merge.", stdout.getvalue())
+ except CommandError:
+ self.fail("Makemigrations fails resolving conflicts in an unspecified app")
+ finally:
+ questioner.input = old_input
+ if os.path.exists(merge_file):
+ os.remove(merge_file)