Add knowledge of Django Migrations and tracking of the schema upgrade method.

Review Request #10550 — Created May 13, 2019 and submitted — Latest diff uploaded

Information

Django Evolution
master
a8e94ba...

Reviewers

One of the major pillars of Django Evolution 1.0 is compatibility with
Django's built-in schema migrations. Apps that use Migrations need to
not be tracked for evolutions, and legacy apps using evolutions need to
be able to transition to migrations.

This change adds the beginnings of the Migrations support. It introduces
a concept of an upgrade method (evolutions, migrations, or
undetermined), which can be computed from an app based on the presence
of evolutions or migrations submodules and whether an evolution
transitions the app to migrations.

Transitioning is done through a new MoveToDjangoMigrations mutation.
Once applied to an app, further evolutions are no longer allowed on that
app, only migrations. This allows a starting migration to be specified,
defaulting to the standard "0001_initial" used by migrations. This
is intended for theoretical specialized cases where an app may have
supported both migrations and evolutions, resulting in a common branch
point for further migrations. It's also intended for future work that
could allow an app to transition back to evolutions and then back to
migrations. Basically, future expansion.

This upgrade method is stored in the signature and included in diffs.
Apps that appear to have gone from evolutions to migrations will be
shown in hints. The signature also tracks the last migration ID applied
to an app using migrations. Currently, that's always going to be None,
but this will be used later when the evolver is ready to manage
migrations.

Unit tests pass for Django 1.6 and 1.11 and on Python 2.7 and 3.7.

Tested locally with an attempted upgrade simulation from Review Board
3.0 to 4.0 on Django 1.11. This included a mix of apps using evolutions
to upgrade, apps using migrations, and apps that were using evolutions
but move to migrations using MoveToDjangoMigrations. Saw the simulation
results I expected.