[gnome-contacts/nielsdg/dirty: 2/2] contact: Copy the chunks before applying changes




commit c2e72f699295d792fd790bfd5e4d48b5c646ceb6
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Mon Oct 10 20:16:45 2022 +0200

    contact: Copy the chunks before applying changes
    
    When applying the changes of certain fields, we've seen that this leads
    to a `individuals_changed_detailed()` being called with the same
    individual in the `removed` and `added` set. The signal callback
    propagates to several layers, until it lands in the
    `Contact:on_individual_personas_changed()` function. There, all chunks
    related to the persona are removed, even when we still might be applying
    changes of some of the other chunks.
    
    The `apply_changes()` method in other words should keep its own copy to
    prevent that.
    
    Fixes: https://gitlab.gnome.org/GNOME/gnome-contacts/-/issues/271

 src/core/contacts-contact.vala | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
---
diff --git a/src/core/contacts-contact.vala b/src/core/contacts-contact.vala
index 761f447b..742bab71 100644
--- a/src/core/contacts-contact.vala
+++ b/src/core/contacts-contact.vala
@@ -264,9 +264,12 @@ public class Contacts.Contact : GLib.Object, GLib.ListModel {
   public async unowned Individual? apply_changes (PersonaStore store) throws GLib.Error {
     unowned Individual? individual = null;
 
+    // Create a (shallow) copy of the chunks
+    var chunks = this.chunks.copy ((chunk) => { return chunk; });
+
     // For those that were a persona: save the properties using the API
-    for (uint i = 0; i < this.chunks.length; i++) {
-      unowned var chunk = this.chunks[i];
+    for (uint i = 0; i < chunks.length; i++) {
+      unowned var chunk = chunks[i];
       if (chunk.persona == null)
         continue;
 
@@ -297,8 +300,8 @@ public class Contacts.Contact : GLib.Object, GLib.ListModel {
 
     // Find those without a persona, and save them into the primary store
     var new_details = new HashTable<string, Value?> (str_hash, str_equal);
-    for (uint i = 0; i < this.chunks.length; i++) {
-      unowned var chunk = this.chunks[i];
+    for (uint i = 0; i < chunks.length; i++) {
+      unowned var chunk = chunks[i];
       if (chunk.persona != null)
         continue;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]