Fixed #22791 -- Invoke interactive questioner only for conflicts in specified apps.
Thanks bendavis78 for the report and Tim Graham for the review.
This commit is contained in:
parent
efe87d3e48
commit
f7a78f9bba
|
@ -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)
|
||||
|
|
|
@ -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)),
|
||||
],
|
||||
)
|
||||
|
||||
]
|
|
@ -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)),
|
||||
],
|
||||
)
|
||||
|
||||
]
|
|
@ -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)),
|
||||
],
|
||||
)
|
||||
|
||||
]
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue