summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Holtermann <info@markusholtermann.eu>2015-08-09 23:53:09 +1000
committerMarkus Holtermann <info@markusholtermann.eu>2015-08-18 18:33:14 +1000
commit0271a11ba5df58b449a3f968ec57fb1a090c5726 (patch)
tree68a03645f73048f3a6dc5c1ee7173068d38c2b2f
parent75b5de8d5f73fcf52a05cd2f82125d7e27bda93b (diff)
Fixed #24755 -- Hid operations from dependency apps when merging migrations
Thanks Carl Meyer for the report and Tim Graham for the review.
-rw-r--r--django/core/management/commands/makemigrations.py6
-rw-r--r--tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/__init__.py0
-rw-r--r--tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0001_initial.py27
-rw-r--r--tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_conflicting_second.py20
-rw-r--r--tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_second.py24
-rw-r--r--tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/__init__.py0
-rw-r--r--tests/migrations/test_commands.py33
7 files changed, 109 insertions, 1 deletions
diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py
index 4cd36f3c8a..f218c417c0 100644
--- a/django/core/management/commands/makemigrations.py
+++ b/django/core/management/commands/makemigrations.py
@@ -194,13 +194,17 @@ class Command(BaseCommand):
questioner = InteractiveMigrationQuestioner()
else:
questioner = MigrationQuestioner(defaults={'ask_merge': True})
+
for app_label, migration_names in conflicts.items():
# Grab out the migrations in question, and work out their
# common ancestor.
merge_migrations = []
for migration_name in migration_names:
migration = loader.get_migration(app_label, migration_name)
- migration.ancestry = loader.graph.forwards_plan((app_label, migration_name))
+ migration.ancestry = [
+ mig for mig in loader.graph.forwards_plan((app_label, migration_name))
+ if mig[0] == migration.app_label
+ ]
merge_migrations.append(migration)
all_items_equal = lambda seq: all(item == seq[0] for item in seq[1:])
merge_migrations_generations = zip(*[m.ancestry for m in merge_migrations])
diff --git a/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/__init__.py b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/__init__.py
diff --git a/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0001_initial.py
new file mode 100644
index 0000000000..146d6cee3e
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0001_initial.py
@@ -0,0 +1,27 @@
+# -*- 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/conflicting_app_with_dependencies/migrations/0002_conflicting_second.py b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_conflicting_second.py
new file mode 100644
index 0000000000..cbe5bfb13e
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/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 = [
+ ("conflicting_app_with_dependencies", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ "Something",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
+ ]
diff --git a/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_second.py b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_second.py
new file mode 100644
index 0000000000..16d42f8736
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_second.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("conflicting_app_with_dependencies", "0001_initial"),
+ ("migrated_app", "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/conflicting_app_with_dependencies/migrations/__init__.py b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/__init__.py
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 8ca47aec2d..67fc57faa1 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -920,6 +920,39 @@ class MakeMigrationsTests(MigrationTestBase):
except CommandError:
self.fail("Makemigrations fails resolving conflicts in an unspecified app")
+ @override_settings(
+ INSTALLED_APPS=[
+ "migrations.migrations_test_apps.migrated_app",
+ "migrations.migrations_test_apps.conflicting_app_with_dependencies"])
+ def test_makemigrations_merge_dont_output_dependency_operations(self):
+ """
+ Makes sure that makemigrations --merge does not output any operations
+ from apps that don't belong to a given app.
+ """
+ # Monkeypatch interactive questioner to auto accept
+ with mock.patch('django.db.migrations.questioner.input', mock.Mock(return_value='N')):
+ out = six.StringIO()
+ with mock.patch('django.core.management.color.supports_color', lambda *args: False):
+ call_command(
+ "makemigrations", "conflicting_app_with_dependencies",
+ merge=True, interactive=True, stdout=out
+ )
+ val = out.getvalue().lower()
+ self.assertIn('merging conflicting_app_with_dependencies\n', val)
+ self.assertIn(
+ ' branch 0002_conflicting_second\n'
+ ' - create model something\n',
+ val
+ )
+ self.assertIn(
+ ' branch 0002_second\n'
+ ' - delete model tribble\n'
+ ' - remove field silly_field from author\n'
+ ' - add field rating to author\n'
+ ' - create model book\n',
+ val
+ )
+
def test_makemigrations_with_custom_name(self):
"""
Makes sure that makemigrations generate a custom migration.