]> code.delx.au - offlineimap/blobdiff - src/Data/Syncable.hs
More attempts
[offlineimap] / src / Data / Syncable.hs
index 26752458b42bafdcab7a5fd283cc848c6f6c12b2..08cd82a10c5d19532a26ef22fd39f565ff803454 100644 (file)
@@ -85,7 +85,8 @@ bring them into proper sync.
 
 In the event that both master and child previously had an item, and the payload
 of the item has changed on both ends, the payload as given in the child
-will take precedence.
+will take precedence.  If both previously had an item, and it changed on only
+one end, the new value "wins".
 
 This relationship should hold:
 
@@ -117,16 +118,17 @@ syncBiDir masterstate childstate lastchildstate =
                           findAdded masterstate childstate $ lastchildstate)
                          ++ (map (pairToFunc ModifyContent) . Map.toList $ childPayloadChanges)
           masterPayloadChanges = 
-              Map.union (findModified childstate lastchildstate)
-                 (findModified childstate masterstate)
+              Map.union (findModified masterstate childstate lastchildstate)
+                        (findModified masterstate childstate masterstate)
+                 
           -- The child's payload takes precedence, so we are going to
           -- calculate the changes made on the master to apply to the client,
           -- then subtract out any items in the master changes that have the
           -- same key.
           childPayloadChanges = 
-              foldl (flip Map.delete) (findModified masterstate lastchildstate)
-                    (Map.keys (findModified childstate masterstate))
-                    
+              foldl (\m (k, v) -> Map.adjust (\_ -> v) k m)
+                        (findModified childstate masterstate lastchildstate)
+                        (Map.toList $ findModified masterstate childstate lastchildstate)
 
 {- | Compares two SyncCollections, and returns the commands that, when
 applied to the first collection, would yield the second. -}
@@ -158,11 +160,19 @@ findAdded state1 state2 lastchildstate =
 is different in state1 than it was in lastchildstate.  Returns the key and new
 payload for each such item found. -}
 findModified :: (Ord k, Eq v) =>
-                SyncCollection k v -> SyncCollection k v -> SyncCollection k v
-findModified state1 lastchildstate =
+                SyncCollection k v -> SyncCollection k v -> SyncCollection k v -> SyncCollection k v
+findModified basestate state1 lastchildstate =
     Map.mapMaybe id .  
-    Map.intersectionWith (\v1 v2 -> if v1 /= v2 then Just v1 else Nothing) 
-       state1 $ lastchildstate
+    Map.intersectionWithKey comparefunc state1 $ lastchildstate
+    where comparefunc k v1 v2 =
+              if v1 /= v2
+                 then case Map.lookup k basestate of
+                        Nothing -> Nothing
+                        Just baseval ->
+                            if baseval == v1
+                               then Nothing
+                               else Just v1
+                 else Nothing
 
 {- | Apply the specified changes to the given SyncCollection.  Returns
 a new SyncCollection with the changes applied.  If changes are specified
@@ -175,4 +185,6 @@ unaryApplyChanges collection commands =
             Map.delete key collection
         makeChange collection (CopyItem key val) =
             Map.insert key val collection
+        makeChange collection (ModifyContent key val) =
+            Map.adjust (\_ -> val) key collection
     in foldl makeChange collection commands