#23733: Following #23556: manage multi-apps dependencies when squashing
----------------------------+--------------------------------------
     Reporter:  Twidi       |                    Owner:  nobody
         Type:  Bug         |                   Status:  new
    Component:  Migrations  |                  Version:  master
     Severity:  Normal      |               Resolution:
     Keywords:              |             Triage Stage:  Unreviewed
    Has patch:  1           |      Needs documentation:  0
  Needs tests:  0           |  Patch needs improvement:  0
Easy pickings:  0           |                    UI/UX:  0
----------------------------+--------------------------------------
Description changed by Twidi:

Old description:

> Following ticket #23556 and PR #3280, I found a problem with squashing on
> different apps, each one depending on the other at different step
>
> `app1`:
>   - `1_auto`
>   - `2_auto`
>   - `3_auto`, with dependency on `('app2', '2_auto')`
>   - `4_auto`
>
> With this squash:
>
>   - `2_squashed_3` (squash of `2_auto` and `3_auto`)
>

> And `app2`:
>
>   - `1_auto`, with dependency on `('app1', '1_auto')`
>   - `2_auto`
>
> With this squash:
>
>   - `1_squashed_2` (squash of `1_auto` and `2_auto`)
>

> With this configuration, there is an error in `build_graph`:
>
> {{{
> #!python
> File "django/db/migrations/loader.py", line 224, in build_graph
>     normal[child_key].dependencies.remove(replaced)
> KeyError: ('app1', '3_auto')
> }}}
>

> The reason is simple, `('app1', '3_auto')` where replaced by `('app1',
> '2_squashed_3')`
>
> So I came up with this patch:
>
> {{{
> #!diff
> diff --git a/django/db/migrations/loader.py
> b/django/db/migrations/loader.py
> index 9f8be33..0ee3794 100644
> --- a/django/db/migrations/loader.py
> +++ b/django/db/migrations/loader.py
> @@ -219,8 +219,15 @@ class MigrationLoader(object):
>                  for child_key in reverse_dependencies.get(replaced,
> set()):
>                      if child_key in migration.replaces:
>                          continue
> -                    normal[child_key].dependencies.remove(replaced)
> -                    normal[child_key].dependencies.append(key)
> +                    # child_key may appear in a replacement
> +                    if child_key in reverse_replacements:
> +                        for replaced_child_key in
> reverse_replacements[child_key]:
> +                            if replaced in
> replacing[replaced_child_key].dependencies:
> +
> replacing[replaced_child_key].dependencies.remove(replaced)
> +
> replacing[replaced_child_key].dependencies.append(key)
> +                    else:
> +                        normal[child_key].dependencies.remove(replaced)
> +                        normal[child_key].dependencies.append(key)
>              normal[key] = migration
>              # Mark the replacement as applied if all its replaced ones
> are
>              if all(applied_statuses):
> }}}
>
> Note that I loop on reverse_replacements[child_key], but I'm not sure how
> we can have many entries here
>
> I'll provide a PR with two commits:
>
> - one with a test showing the failure
> - one with the patch

New description:

 Following ticket #23556 and PR #3280, I found a problem with squashing on
 different apps, each one depending on the other at different step

 `app1`:
   - `1_auto`
   - `2_auto`
   - `3_auto`, with dependency on `('app2', '2_auto')`
   - `4_auto`

 With this squash:

   - `2_squashed_3` (squash of `2_auto` and `3_auto`)


 And `app2`:

   - `1_auto`, with dependency on `('app1', '1_auto')`
   - `2_auto`

 With this squash:

   - `1_squashed_2` (squash of `1_auto` and `2_auto`)


 With this configuration, there is an error in `build_graph`:

 {{{
 #!python
 File "django/db/migrations/loader.py", line 224, in build_graph
     normal[child_key].dependencies.remove(replaced)
 KeyError: ('app1', '3_auto')
 }}}


 The reason is simple, `('app1', '3_auto')` where replaced by `('app1',
 '2_squashed_3')`

 So I came up with this patch:

 {{{
 #!diff
 diff --git a/django/db/migrations/loader.py
 b/django/db/migrations/loader.py
 index 9f8be33..0ee3794 100644
 --- a/django/db/migrations/loader.py
 +++ b/django/db/migrations/loader.py
 @@ -219,8 +219,15 @@ class MigrationLoader(object):
                  for child_key in reverse_dependencies.get(replaced,
 set()):
                      if child_key in migration.replaces:
                          continue
 -                    normal[child_key].dependencies.remove(replaced)
 -                    normal[child_key].dependencies.append(key)
 +                    # child_key may appear in a replacement
 +                    if child_key in reverse_replacements:
 +                        for replaced_child_key in
 reverse_replacements[child_key]:
 +                            if replaced in
 replacing[replaced_child_key].dependencies:
 +
 replacing[replaced_child_key].dependencies.remove(replaced)
 +
 replacing[replaced_child_key].dependencies.append(key)
 +                    else:
 +                        normal[child_key].dependencies.remove(replaced)
 +                        normal[child_key].dependencies.append(key)
              normal[key] = migration
              # Mark the replacement as applied if all its replaced ones
 are
              if all(applied_statuses):
 }}}

 Note that I loop on `reverse_replacements[child_key]`, but I'm not sure
 how we can have many entries here

 I'll provide a PR with two commits:

 - one with a test showing the failure
 - one with the patch

--

--
Ticket URL: <https://code.djangoproject.com/ticket/23733#comment:3>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/063.ff9f7d7332c22cff198e9a297d90d194%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to