diff --git a/src/provider.rs b/src/provider.rs index 17b80ac..6171e03 100644 --- a/src/provider.rs +++ b/src/provider.rs @@ -51,9 +51,9 @@ where let server_mod = cal_server.get_tasks_modified_since(Some(self.last_sync)); let server_del = cal_server.get_items_deleted_since(self.last_sync); - let local_mod = cal_local.get_tasks_modified_since(Some(self.last_sync)); let local_del = cal_local.get_items_deleted_since(self.last_sync); + // Pull remote changes from the server let mut tasks_to_add_to_local = Vec::new(); let mut tasks_id_to_remove_from_local = Vec::new(); for deleted_id in server_del { @@ -66,10 +66,21 @@ where } tasks_to_add_to_local.push((*new_item).clone()); } + // Even in case of conflicts, "the server always wins", so it is safe to remove tasks from the local cache as soon as now + remove_from_calendar(&tasks_id_to_remove_from_local, cal_local); + + + + // Push local changes to the server + let local_mod = cal_local.get_tasks_modified_since(Some(self.last_sync)); let mut tasks_to_add_to_server = Vec::new(); let mut tasks_id_to_remove_from_server = Vec::new(); for deleted_id in local_del { + if server_mod.contains_key(&deleted_id) { + log::warn!("Conflict for task {}, that has been locally deleted and updated in the server. Using the server version.", deleted_id); + continue; + } tasks_id_to_remove_from_server.push(deleted_id); } for (new_id, new_item) in &local_mod { @@ -80,7 +91,6 @@ where tasks_to_add_to_server.push((*new_item).clone()); } - remove_from_calendar(&tasks_id_to_remove_from_local, cal_local); remove_from_calendar(&tasks_id_to_remove_from_server, cal_server); move_to_calendar(&mut tasks_to_add_to_local, cal_local); move_to_calendar(&mut tasks_to_add_to_server, cal_server); diff --git a/tests/sync.rs b/tests/sync.rs index 314a27a..2107511 100644 --- a/tests/sync.rs +++ b/tests/sync.rs @@ -45,11 +45,11 @@ fn print_calendar_list(cals: &Vec) { /// Populate sources with the following: /// * At the last sync: both sources had A, B, C, D, E, F, G, H, I, J, K, L, M at last sync /// * Before the newer sync, this will be the content of the sources: -/// * server: A, C, D, E', F', G✓, H , I', K, L, M, N -/// * cache: A, B, D', E, F'', G , H✓, I✓, J✓, K, L, M, O +/// * server: A, C, D, E', F', G✓, H , I', K✓, L, M, N +/// * cache: A, B, D', E, F'', G , H✓, I✓, J✓, L, M, O /// /// Hence, here is the expected result after the sync: -/// * both: A, D', E', F', G✓, H✓, I', K, L, M, N, O +/// * both: A, D', E', F', G✓, H✓, I', K✓, L, M, N, O /// /// Notes: /// * X': name has been modified since the last sync @@ -129,6 +129,9 @@ async fn populate_test_provider() -> Provider { cal_server.delete_item(&task_j_id); + cal_server.get_item_by_id_mut(&task_k_id).unwrap().unwrap_task_mut() + .set_completed(true); + let task_n = Item::Task(Task::new("task N (new from server)".into(), Utc::now())); cal_server.add_item(task_n); @@ -154,6 +157,8 @@ async fn populate_test_provider() -> Provider { cal_local.get_item_by_id_mut(&task_j_id).unwrap().unwrap_task_mut() .set_completed(true); + cal_local.delete_item(&task_k_id); + let task_o = Item::Task(Task::new("task O (new from local)".into(), Utc::now())); cal_local.add_item(task_o);