Handles merging together conflicted migrations interactively, if it's safe; otherwise, advises on how to fix it.
(self, loader, conflicts)
| 407 | return migration_string |
| 408 | |
| 409 | def handle_merge(self, loader, conflicts): |
| 410 | """ |
| 411 | Handles merging together conflicted migrations interactively, |
| 412 | if it's safe; otherwise, advises on how to fix it. |
| 413 | """ |
| 414 | if self.interactive: |
| 415 | questioner = InteractiveMigrationQuestioner(prompt_output=self.log_output) |
| 416 | else: |
| 417 | questioner = MigrationQuestioner(defaults={"ask_merge": True}) |
| 418 | |
| 419 | for app_label, migration_names in conflicts.items(): |
| 420 | # Grab out the migrations in question, and work out their |
| 421 | # common ancestor. |
| 422 | merge_migrations = [] |
| 423 | for migration_name in migration_names: |
| 424 | migration = loader.get_migration(app_label, migration_name) |
| 425 | migration.ancestry = [ |
| 426 | mig |
| 427 | for mig in loader.graph.forwards_plan((app_label, migration_name)) |
| 428 | if mig[0] == migration.app_label |
| 429 | ] |
| 430 | merge_migrations.append(migration) |
| 431 | |
| 432 | def all_items_equal(seq): |
| 433 | return all(item == seq[0] for item in seq[1:]) |
| 434 | |
| 435 | merge_migrations_generations = zip(*(m.ancestry for m in merge_migrations)) |
| 436 | common_ancestor_count = sum( |
| 437 | 1 |
| 438 | for common_ancestor_generation in takewhile( |
| 439 | all_items_equal, merge_migrations_generations |
| 440 | ) |
| 441 | ) |
| 442 | if not common_ancestor_count: |
| 443 | raise ValueError( |
| 444 | "Could not find common ancestor of %s" % migration_names |
| 445 | ) |
| 446 | # Now work out the operations along each divergent branch |
| 447 | for migration in merge_migrations: |
| 448 | migration.branch = migration.ancestry[common_ancestor_count:] |
| 449 | migrations_ops = ( |
| 450 | loader.get_migration(node_app, node_name).operations |
| 451 | for node_app, node_name in migration.branch |
| 452 | ) |
| 453 | migration.merged_operations = sum(migrations_ops, []) |
| 454 | # In future, this could use some of the Optimizer code |
| 455 | # (can_optimize_through) to automatically see if they're |
| 456 | # mergeable. For now, we always just prompt the user. |
| 457 | if self.verbosity > 0: |
| 458 | self.log(self.style.MIGRATE_HEADING("Merging %s" % app_label)) |
| 459 | for migration in merge_migrations: |
| 460 | self.log(self.style.MIGRATE_LABEL(" Branch %s" % migration.name)) |
| 461 | for operation in migration.merged_operations: |
| 462 | self.log(" %s" % operation.formatted_description()) |
| 463 | if questioner.ask_merge(app_label): |
| 464 | # If they still want to merge it, then write out an empty |
| 465 | # file depending on the migrations needing merging. |
| 466 | numbers = [ |
no test coverage detected