- {
- struct edit *edit = diffs.edits[e];
- switch (edit->type)
- {
- case ADDITION:
- if (edit->j1 == 0)
- {
- /* An addition to the top of modified_file.
- Apply it to the top of mainstream_file. */
- ssize_t j;
- for (j = edit->j2; j >= edit->j1; j--)
- {
- struct entry *added_entry = modified_file.entries[j];
- gl_list_add_first (result_entries, added_entry);
- }
- }
- else
- {
- ssize_t i_before;
- ssize_t i_after;
- ssize_t k_before;
- ssize_t k_after;
- i_before = diffs.index_mapping_reverse[edit->j1 - 1];
- ASSERT (i_before >= 0);
- i_after = (edit->j2 + 1 == modified_file.num_entries
- ? ancestor_file.num_entries
- : diffs.index_mapping_reverse[edit->j2 + 1]);
- ASSERT (i_after >= 0);
- ASSERT (i_after == i_before + 1);
- /* An addition between ancestor_file.entries[i_before] and
- ancestor_file.entries[i_after]. See whether these two
- entries still exist in mainstream_file and are still
- consecutive. */
- k_before = index_mapping[i_before];
- k_after = (i_after == ancestor_file.num_entries
- ? mainstream_file.num_entries
- : index_mapping[i_after]);
- if (k_before >= 0 && k_after >= 0 && k_after == k_before + 1)
- {
- /* Yes, the entry before and after are still neighbours
- in mainstream_file. Apply the addition between
- them. */
- if (k_after == mainstream_file.num_entries)
- {
- size_t j;
- for (j = edit->j1; j <= edit->j2; j++)
- {
- struct entry *added_entry = modified_file.entries[j];
- gl_list_add_last (result_entries, added_entry);
- }
- }
- else
- {
- gl_list_node_t node_k_after = result_entries_pointers[k_after];
- size_t j;
- for (j = edit->j1; j <= edit->j2; j++)
- {
- struct entry *added_entry = modified_file.entries[j];
- gl_list_add_before (result_entries, node_k_after, added_entry);
- }
- }
- }
- else
- {
- /* It's not clear where the additions should be applied.
- Let the user decide. */
- struct conflict *c = XMALLOC (struct conflict);
- size_t j;
- c->num_old_entries = 0;
- c->old_entries = NULL;
- c->num_modified_entries = edit->j2 - edit->j1 + 1;
- c->modified_entries =
- XNMALLOC (c->num_modified_entries, struct entry *);
- for (j = edit->j1; j <= edit->j2; j++)
- c->modified_entries[j - edit->j1] = modified_file.entries[j];
- gl_list_add_last (result_conflicts, c);
- }
- }
- break;
- case REMOVAL:
- {
- /* Apply the removals one by one. */
- size_t i;
- for (i = edit->i1; i <= edit->i2; i++)
- {
- struct entry *removed_entry = ancestor_file.entries[i];
- ssize_t k = index_mapping[i];
- if (k >= 0
- && entry_equals (removed_entry,
- mainstream_file.entries[k]))
- {
- /* The entry to be removed still exists in
- mainstream_file. Remove it. */
- gl_list_node_set_value (result_entries,
- result_entries_pointers[k],
- &empty_entry);
- }
- else
- {
- /* The entry to be removed was already removed or was
- modified. This is a conflict. */
- struct conflict *c = XMALLOC (struct conflict);
- c->num_old_entries = 1;
- c->old_entries =
- XNMALLOC (c->num_old_entries, struct entry *);
- c->old_entries[0] = removed_entry;
- c->num_modified_entries = 0;
- c->modified_entries = NULL;
- gl_list_add_last (result_conflicts, c);
- }
- }
- }
- break;
- case CHANGE:
- {
- bool done = false;
- /* When the user usually merges entries from the same day,
- and this edit is at the top of the file: */
- if (split_merged_entry && edit->j1 == 0)
- {
- /* Test whether the change is "simple merged", i.e. whether
- it consists of additions, followed by an augmentation of
- the first changed entry, followed by small changes of the
- remaining entries:
- entry_1
- entry_2
- ...
- entry_n
- are mapped to
- added_entry
- ...
- added_entry
- augmented_entry_1
- modified_entry_2
- ...
- modified_entry_n. */
- if (edit->i2 - edit->i1 <= edit->j2 - edit->j1)
- {
- struct entry *split[2];
- bool simple_merged =
- try_split_merged_entry (ancestor_file.entries[edit->i1],
- modified_file.entries[edit->i1 + edit->j2 - edit->i2],
- split);
- if (simple_merged)
- {
- size_t i;
- for (i = edit->i1 + 1; i <= edit->i2; i++)
- if (entry_fstrcmp (ancestor_file.entries[i],
- modified_file.entries[i + edit->j2 - edit->i2])
- < FSTRCMP_THRESHOLD)
- {
- simple_merged = false;
- break;
- }
- }
- if (simple_merged)
- {
- /* Apply the additions at the top of modified_file.
- Apply each of the single-entry changes
- separately. */
- size_t num_changed = edit->i2 - edit->i1 + 1; /* > 0 */
- size_t num_added = (edit->j2 - edit->j1 + 1) - num_changed;
- ssize_t j;
- /* First part of the split modified_file.entries[edit->j2 - edit->i2 + edit->i1]: */
- gl_list_add_first (result_entries, split[0]);
- /* The additions. */
- for (j = edit->j1 + num_added - 1; j >= edit->j1; j--)
- {
- struct entry *added_entry = modified_file.entries[j];
- gl_list_add_first (result_entries, added_entry);
- }
- /* Now the single-entry changes. */
- for (j = edit->j1 + num_added; j <= edit->j2; j++)
- {
- struct entry *changed_entry =
- (j == edit->j1 + num_added
- ? split[1]
- : modified_file.entries[j]);
- size_t i = j + edit->i2 - edit->j2;
- ssize_t k = index_mapping[i];
- if (k >= 0
- && entry_equals (ancestor_file.entries[i],
- mainstream_file.entries[k]))
- {
- gl_list_node_set_value (result_entries,
- result_entries_pointers[k],
- changed_entry);
- }
- else if (!entry_equals (ancestor_file.entries[i],
- changed_entry))
- {
- struct conflict *c = XMALLOC (struct conflict);
- c->num_old_entries = 1;
- c->old_entries =
- XNMALLOC (c->num_old_entries, struct entry *);
- c->old_entries[0] = ancestor_file.entries[i];
- c->num_modified_entries = 1;
- c->modified_entries =
- XNMALLOC (c->num_modified_entries, struct entry *);
- c->modified_entries[0] = changed_entry;
- gl_list_add_last (result_conflicts, c);
- }
- }
- done = true;
- }
- }
- }
- if (!done)
- {
- bool simple;
- /* Test whether the change is "simple", i.e. whether it
- consists of small changes to the old ChangeLog entries
- and additions before them:
- entry_1
- ...
- entry_n
- are mapped to
- added_entry
- ...
- added_entry
- modified_entry_1
- ...
- modified_entry_n. */
- if (edit->i2 - edit->i1 <= edit->j2 - edit->j1)
- {
- size_t i;
- simple = true;
- for (i = edit->i1; i <= edit->i2; i++)
- if (entry_fstrcmp (ancestor_file.entries[i],
- modified_file.entries[i + edit->j2 - edit->i2])
- < FSTRCMP_THRESHOLD)
- {
- simple = false;
- break;
- }
- }
- else
- simple = false;
- if (simple)
- {
- /* Apply the additions and each of the single-entry
- changes separately. */
- size_t num_changed = edit->i2 - edit->i1 + 1; /* > 0 */
- size_t num_added = (edit->j2 - edit->j1 + 1) - num_changed;
- if (edit->j1 == 0)
- {
- /* A simple change at the top of modified_file.
- Apply it to the top of mainstream_file. */
- ssize_t j;
- for (j = edit->j1 + num_added - 1; j >= edit->j1; j--)
- {
- struct entry *added_entry = modified_file.entries[j];
- gl_list_add_first (result_entries, added_entry);
- }
- for (j = edit->j1 + num_added; j <= edit->j2; j++)
- {
- struct entry *changed_entry = modified_file.entries[j];
- size_t i = j + edit->i2 - edit->j2;
- ssize_t k = index_mapping[i];
- if (k >= 0
- && entry_equals (ancestor_file.entries[i],
- mainstream_file.entries[k]))
- {
- gl_list_node_set_value (result_entries,
- result_entries_pointers[k],
- changed_entry);
- }
- else
- {
- struct conflict *c;
- ASSERT (!entry_equals (ancestor_file.entries[i],
- changed_entry));
- c = XMALLOC (struct conflict);
- c->num_old_entries = 1;
- c->old_entries =
- XNMALLOC (c->num_old_entries, struct entry *);
- c->old_entries[0] = ancestor_file.entries[i];
- c->num_modified_entries = 1;
- c->modified_entries =
- XNMALLOC (c->num_modified_entries, struct entry *);
- c->modified_entries[0] = changed_entry;
- gl_list_add_last (result_conflicts, c);
- }
- }
- done = true;
- }
- else
- {
- ssize_t i_before;
- ssize_t k_before;
- bool linear;
- i_before = diffs.index_mapping_reverse[edit->j1 - 1];
- ASSERT (i_before >= 0);
- /* A simple change after ancestor_file.entries[i_before].
- See whether this entry and the following num_changed
- entries still exist in mainstream_file and are still
- consecutive. */
- k_before = index_mapping[i_before];
- linear = (k_before >= 0);
- if (linear)
- {
- size_t i;
- for (i = i_before + 1; i <= i_before + num_changed; i++)
- if (index_mapping[i] != k_before + (i - i_before))
- {
- linear = false;
- break;
- }
- }
- if (linear)
- {
- gl_list_node_t node_for_insert =
- result_entries_pointers[k_before + 1];
- ssize_t j;
- for (j = edit->j1 + num_added - 1; j >= edit->j1; j--)
- {
- struct entry *added_entry = modified_file.entries[j];
- gl_list_add_before (result_entries, node_for_insert, added_entry);
- }
- for (j = edit->j1 + num_added; j <= edit->j2; j++)
- {
- struct entry *changed_entry = modified_file.entries[j];
- size_t i = j + edit->i2 - edit->j2;
- ssize_t k = index_mapping[i];
- ASSERT (k >= 0);
- if (entry_equals (ancestor_file.entries[i],
- mainstream_file.entries[k]))
- {
- gl_list_node_set_value (result_entries,
- result_entries_pointers[k],
- changed_entry);
- }
- else
- {
- struct conflict *c;
- ASSERT (!entry_equals (ancestor_file.entries[i],
- changed_entry));
- c = XMALLOC (struct conflict);
- c->num_old_entries = 1;
- c->old_entries =
- XNMALLOC (c->num_old_entries, struct entry *);
- c->old_entries[0] = ancestor_file.entries[i];
- c->num_modified_entries = 1;
- c->modified_entries =
- XNMALLOC (c->num_modified_entries, struct entry *);
- c->modified_entries[0] = changed_entry;
- gl_list_add_last (result_conflicts, c);
- }
- }
- done = true;
- }
- }
- }
- else
- {
- /* A big change.
- See whether the num_changed entries still exist
- unchanged in mainstream_file and are still
- consecutive. */
- ssize_t i_first;
- ssize_t k_first;
- bool linear_unchanged;
- i_first = edit->i1;
- k_first = index_mapping[i_first];
- linear_unchanged =
- (k_first >= 0
- && entry_equals (ancestor_file.entries[i_first],
- mainstream_file.entries[k_first]));
- if (linear_unchanged)
- {
- size_t i;
- for (i = i_first + 1; i <= edit->i2; i++)
- if (!(index_mapping[i] == k_first + (i - i_first)
- && entry_equals (ancestor_file.entries[i],
- mainstream_file.entries[index_mapping[i]])))
- {
- linear_unchanged = false;
- break;
- }
- }
- if (linear_unchanged)
- {
- gl_list_node_t node_for_insert =
- result_entries_pointers[k_first];
- ssize_t j;
- size_t i;
- for (j = edit->j2; j >= edit->j1; j--)
- {
- struct entry *new_entry = modified_file.entries[j];
- gl_list_add_before (result_entries, node_for_insert, new_entry);
- }
- for (i = edit->i1; i <= edit->i2; i++)
- {
- ssize_t k = index_mapping[i];
- ASSERT (k >= 0);
- ASSERT (entry_equals (ancestor_file.entries[i],
- mainstream_file.entries[k]));
- gl_list_node_set_value (result_entries,
- result_entries_pointers[k],
- &empty_entry);
- }
- done = true;
- }
- }
- }
- if (!done)
- {
- struct conflict *c = XMALLOC (struct conflict);
- size_t i, j;
- c->num_old_entries = edit->i2 - edit->i1 + 1;
- c->old_entries =
- XNMALLOC (c->num_old_entries, struct entry *);
- for (i = edit->i1; i <= edit->i2; i++)
- c->old_entries[i - edit->i1] = ancestor_file.entries[i];
- c->num_modified_entries = edit->j2 - edit->j1 + 1;
- c->modified_entries =
- XNMALLOC (c->num_modified_entries, struct entry *);
- for (j = edit->j1; j <= edit->j2; j++)
- c->modified_entries[j - edit->j1] = modified_file.entries[j];
- gl_list_add_last (result_conflicts, c);
- }
- }
- break;
- }
- }
+ {
+ struct edit *edit = diffs.edits[e];
+ switch (edit->type)
+ {
+ case ADDITION:
+ if (edit->j1 == 0)
+ {
+ /* An addition to the top of modified_file.
+ Apply it to the top of mainstream_file. */
+ ssize_t j;
+ for (j = edit->j2; j >= edit->j1; j--)
+ {
+ struct entry *added_entry = modified_file.entries[j];
+ gl_list_add_first (result_entries, added_entry);
+ }
+ }
+ else
+ {
+ ssize_t i_before;
+ ssize_t i_after;
+ ssize_t k_before;
+ ssize_t k_after;
+ i_before = diffs.index_mapping_reverse[edit->j1 - 1];
+ ASSERT (i_before >= 0);
+ i_after = (edit->j2 + 1 == modified_file.num_entries
+ ? ancestor_file.num_entries
+ : diffs.index_mapping_reverse[edit->j2 + 1]);
+ ASSERT (i_after >= 0);
+ ASSERT (i_after == i_before + 1);
+ /* An addition between ancestor_file.entries[i_before] and
+ ancestor_file.entries[i_after]. See whether these two
+ entries still exist in mainstream_file and are still
+ consecutive. */
+ k_before = entries_mapping_get (&mapping, i_before);
+ k_after = (i_after == ancestor_file.num_entries
+ ? mainstream_file.num_entries
+ : entries_mapping_get (&mapping, i_after));
+ if (k_before >= 0 && k_after >= 0 && k_after == k_before + 1)
+ {
+ /* Yes, the entry before and after are still neighbours
+ in mainstream_file. Apply the addition between
+ them. */
+ if (k_after == mainstream_file.num_entries)
+ {
+ size_t j;
+ for (j = edit->j1; j <= edit->j2; j++)
+ {
+ struct entry *added_entry = modified_file.entries[j];
+ gl_list_add_last (result_entries, added_entry);
+ }
+ }
+ else
+ {
+ gl_list_node_t node_k_after = result_entries_pointers[k_after];
+ size_t j;
+ for (j = edit->j1; j <= edit->j2; j++)
+ {
+ struct entry *added_entry = modified_file.entries[j];
+ gl_list_add_before (result_entries, node_k_after, added_entry);
+ }
+ }
+ }
+ else
+ {
+ /* It's not clear where the additions should be applied.
+ Let the user decide. */
+ struct conflict *c = XMALLOC (struct conflict);
+ size_t j;
+ c->num_old_entries = 0;
+ c->old_entries = NULL;
+ c->num_modified_entries = edit->j2 - edit->j1 + 1;
+ c->modified_entries =
+ XNMALLOC (c->num_modified_entries, struct entry *);
+ for (j = edit->j1; j <= edit->j2; j++)
+ c->modified_entries[j - edit->j1] = modified_file.entries[j];
+ gl_list_add_last (result_conflicts, c);
+ }
+ }
+ break;
+ case REMOVAL:
+ {
+ /* Apply the removals one by one. */
+ size_t i;
+ for (i = edit->i1; i <= edit->i2; i++)
+ {
+ struct entry *removed_entry = ancestor_file.entries[i];
+ ssize_t k = entries_mapping_get (&mapping, i);
+ if (k >= 0
+ && entry_equals (removed_entry,
+ mainstream_file.entries[k]))
+ {
+ /* The entry to be removed still exists in
+ mainstream_file. Remove it. */
+ gl_list_node_set_value (result_entries,
+ result_entries_pointers[k],
+ &empty_entry);
+ }
+ else
+ {
+ /* The entry to be removed was already removed or was
+ modified. This is a conflict. */
+ struct conflict *c = XMALLOC (struct conflict);
+ c->num_old_entries = 1;
+ c->old_entries =
+ XNMALLOC (c->num_old_entries, struct entry *);
+ c->old_entries[0] = removed_entry;
+ c->num_modified_entries = 0;
+ c->modified_entries = NULL;
+ gl_list_add_last (result_conflicts, c);
+ }
+ }
+ }
+ break;
+ case CHANGE:
+ {
+ bool done = false;
+ /* When the user usually merges entries from the same day,
+ and this edit is at the top of the file: */
+ if (split_merged_entry && edit->j1 == 0)
+ {
+ /* Test whether the change is "simple merged", i.e. whether
+ it consists of additions, followed by an augmentation of
+ the first changed entry, followed by small changes of the
+ remaining entries:
+ entry_1
+ entry_2
+ ...
+ entry_n
+ are mapped to
+ added_entry
+ ...
+ added_entry
+ augmented_entry_1
+ modified_entry_2
+ ...
+ modified_entry_n. */
+ if (edit->i2 - edit->i1 <= edit->j2 - edit->j1)
+ {
+ struct entry *split[2];
+ bool simple_merged =
+ try_split_merged_entry (ancestor_file.entries[edit->i1],
+ modified_file.entries[edit->i1 + edit->j2 - edit->i2],
+ split);
+ if (simple_merged)
+ {
+ size_t i;
+ for (i = edit->i1 + 1; i <= edit->i2; i++)
+ if (entry_fstrcmp (ancestor_file.entries[i],
+ modified_file.entries[i + edit->j2 - edit->i2],
+ FSTRCMP_THRESHOLD)
+ < FSTRCMP_THRESHOLD)
+ {
+ simple_merged = false;
+ break;
+ }
+ }
+ if (simple_merged)
+ {
+ /* Apply the additions at the top of modified_file.
+ Apply each of the single-entry changes
+ separately. */
+ size_t num_changed = edit->i2 - edit->i1 + 1; /* > 0 */
+ size_t num_added = (edit->j2 - edit->j1 + 1) - num_changed;
+ ssize_t j;
+ /* First part of the split modified_file.entries[edit->j2 - edit->i2 + edit->i1]: */
+ gl_list_add_first (result_entries, split[0]);
+ /* The additions. */
+ for (j = edit->j1 + num_added - 1; j >= edit->j1; j--)
+ {
+ struct entry *added_entry = modified_file.entries[j];
+ gl_list_add_first (result_entries, added_entry);
+ }
+ /* Now the single-entry changes. */
+ for (j = edit->j1 + num_added; j <= edit->j2; j++)
+ {
+ struct entry *changed_entry =
+ (j == edit->j1 + num_added
+ ? split[1]
+ : modified_file.entries[j]);
+ size_t i = j + edit->i2 - edit->j2;
+ ssize_t k = entries_mapping_get (&mapping, i);
+ if (k >= 0
+ && entry_equals (ancestor_file.entries[i],
+ mainstream_file.entries[k]))
+ {
+ gl_list_node_set_value (result_entries,
+ result_entries_pointers[k],
+ changed_entry);
+ }
+ else if (!entry_equals (ancestor_file.entries[i],
+ changed_entry))
+ {
+ struct conflict *c = XMALLOC (struct conflict);
+ c->num_old_entries = 1;
+ c->old_entries =
+ XNMALLOC (c->num_old_entries, struct entry *);
+ c->old_entries[0] = ancestor_file.entries[i];
+ c->num_modified_entries = 1;
+ c->modified_entries =
+ XNMALLOC (c->num_modified_entries, struct entry *);
+ c->modified_entries[0] = changed_entry;
+ gl_list_add_last (result_conflicts, c);
+ }
+ }
+ done = true;
+ }
+ }
+ }
+ if (!done)
+ {
+ bool simple;
+ /* Test whether the change is "simple", i.e. whether it
+ consists of small changes to the old ChangeLog entries
+ and additions before them:
+ entry_1
+ ...
+ entry_n
+ are mapped to
+ added_entry
+ ...
+ added_entry
+ modified_entry_1
+ ...
+ modified_entry_n. */
+ if (edit->i2 - edit->i1 <= edit->j2 - edit->j1)
+ {
+ size_t i;
+ simple = true;
+ for (i = edit->i1; i <= edit->i2; i++)
+ if (entry_fstrcmp (ancestor_file.entries[i],
+ modified_file.entries[i + edit->j2 - edit->i2],
+ FSTRCMP_THRESHOLD)
+ < FSTRCMP_THRESHOLD)
+ {
+ simple = false;
+ break;
+ }
+ }
+ else
+ simple = false;
+ if (simple)
+ {
+ /* Apply the additions and each of the single-entry
+ changes separately. */
+ size_t num_changed = edit->i2 - edit->i1 + 1; /* > 0 */
+ size_t num_added = (edit->j2 - edit->j1 + 1) - num_changed;
+ if (edit->j1 == 0)
+ {
+ /* A simple change at the top of modified_file.
+ Apply it to the top of mainstream_file. */
+ ssize_t j;
+ for (j = edit->j1 + num_added - 1; j >= edit->j1; j--)
+ {
+ struct entry *added_entry = modified_file.entries[j];
+ gl_list_add_first (result_entries, added_entry);
+ }
+ for (j = edit->j1 + num_added; j <= edit->j2; j++)
+ {
+ struct entry *changed_entry = modified_file.entries[j];
+ size_t i = j + edit->i2 - edit->j2;
+ ssize_t k = entries_mapping_get (&mapping, i);
+ if (k >= 0
+ && entry_equals (ancestor_file.entries[i],
+ mainstream_file.entries[k]))
+ {
+ gl_list_node_set_value (result_entries,
+ result_entries_pointers[k],
+ changed_entry);
+ }
+ else
+ {
+ struct conflict *c;
+ ASSERT (!entry_equals (ancestor_file.entries[i],
+ changed_entry));
+ c = XMALLOC (struct conflict);
+ c->num_old_entries = 1;
+ c->old_entries =
+ XNMALLOC (c->num_old_entries, struct entry *);
+ c->old_entries[0] = ancestor_file.entries[i];
+ c->num_modified_entries = 1;
+ c->modified_entries =
+ XNMALLOC (c->num_modified_entries, struct entry *);
+ c->modified_entries[0] = changed_entry;
+ gl_list_add_last (result_conflicts, c);
+ }
+ }
+ done = true;
+ }
+ else
+ {
+ ssize_t i_before;
+ ssize_t k_before;
+ bool linear;
+ i_before = diffs.index_mapping_reverse[edit->j1 - 1];
+ ASSERT (i_before >= 0);
+ /* A simple change after ancestor_file.entries[i_before].
+ See whether this entry and the following num_changed
+ entries still exist in mainstream_file and are still
+ consecutive. */
+ k_before = entries_mapping_get (&mapping, i_before);
+ linear = (k_before >= 0);
+ if (linear)
+ {
+ size_t i;
+ for (i = i_before + 1; i <= i_before + num_changed; i++)
+ if (entries_mapping_get (&mapping, i) != k_before + (i - i_before))
+ {
+ linear = false;
+ break;
+ }
+ }
+ if (linear)
+ {
+ gl_list_node_t node_for_insert =
+ result_entries_pointers[k_before + 1];
+ ssize_t j;
+ for (j = edit->j1 + num_added - 1; j >= edit->j1; j--)
+ {
+ struct entry *added_entry = modified_file.entries[j];
+ gl_list_add_before (result_entries, node_for_insert, added_entry);
+ }
+ for (j = edit->j1 + num_added; j <= edit->j2; j++)
+ {
+ struct entry *changed_entry = modified_file.entries[j];
+ size_t i = j + edit->i2 - edit->j2;
+ ssize_t k = entries_mapping_get (&mapping, i);
+ ASSERT (k >= 0);
+ if (entry_equals (ancestor_file.entries[i],
+ mainstream_file.entries[k]))
+ {
+ gl_list_node_set_value (result_entries,
+ result_entries_pointers[k],
+ changed_entry);
+ }
+ else
+ {
+ struct conflict *c;
+ ASSERT (!entry_equals (ancestor_file.entries[i],
+ changed_entry));
+ c = XMALLOC (struct conflict);
+ c->num_old_entries = 1;
+ c->old_entries =
+ XNMALLOC (c->num_old_entries, struct entry *);
+ c->old_entries[0] = ancestor_file.entries[i];
+ c->num_modified_entries = 1;
+ c->modified_entries =
+ XNMALLOC (c->num_modified_entries, struct entry *);
+ c->modified_entries[0] = changed_entry;
+ gl_list_add_last (result_conflicts, c);
+ }
+ }
+ done = true;
+ }
+ }
+ }
+ else
+ {
+ /* A big change.
+ See whether the num_changed entries still exist
+ unchanged in mainstream_file and are still
+ consecutive. */
+ ssize_t i_first;
+ ssize_t k_first;
+ bool linear_unchanged;
+ i_first = edit->i1;
+ k_first = entries_mapping_get (&mapping, i_first);
+ linear_unchanged =
+ (k_first >= 0
+ && entry_equals (ancestor_file.entries[i_first],
+ mainstream_file.entries[k_first]));
+ if (linear_unchanged)
+ {
+ size_t i;
+ for (i = i_first + 1; i <= edit->i2; i++)
+ if (!(entries_mapping_get (&mapping, i) == k_first + (i - i_first)
+ && entry_equals (ancestor_file.entries[i],
+ mainstream_file.entries[entries_mapping_get (&mapping, i)])))
+ {
+ linear_unchanged = false;
+ break;
+ }
+ }
+ if (linear_unchanged)
+ {
+ gl_list_node_t node_for_insert =
+ result_entries_pointers[k_first];
+ ssize_t j;
+ size_t i;
+ for (j = edit->j2; j >= edit->j1; j--)
+ {
+ struct entry *new_entry = modified_file.entries[j];
+ gl_list_add_before (result_entries, node_for_insert, new_entry);
+ }
+ for (i = edit->i1; i <= edit->i2; i++)
+ {
+ ssize_t k = entries_mapping_get (&mapping, i);
+ ASSERT (k >= 0);
+ ASSERT (entry_equals (ancestor_file.entries[i],
+ mainstream_file.entries[k]));
+ gl_list_node_set_value (result_entries,
+ result_entries_pointers[k],
+ &empty_entry);
+ }
+ done = true;
+ }
+ }
+ }
+ if (!done)
+ {
+ struct conflict *c = XMALLOC (struct conflict);
+ size_t i, j;
+ c->num_old_entries = edit->i2 - edit->i1 + 1;
+ c->old_entries =
+ XNMALLOC (c->num_old_entries, struct entry *);
+ for (i = edit->i1; i <= edit->i2; i++)
+ c->old_entries[i - edit->i1] = ancestor_file.entries[i];
+ c->num_modified_entries = edit->j2 - edit->j1 + 1;
+ c->modified_entries =
+ XNMALLOC (c->num_modified_entries, struct entry *);
+ for (j = edit->j1; j <= edit->j2; j++)
+ c->modified_entries[j - edit->j1] = modified_file.entries[j];
+ gl_list_add_last (result_conflicts, c);
+ }
+ }
+ break;
+ }
+ }