From 9a23081cdab831b9b630b3f56bdaa548c6303b79 Mon Sep 17 00:00:00 2001 From: daladim Date: Sun, 28 Mar 2021 19:42:07 +0200 Subject: [PATCH] [provider] More logs + fixed syncing bugs --- src/provider.rs | 43 +++++++++++++++++++++++++++++++++++++------ src/utils.rs | 15 +++++++++++++-- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/provider.rs b/src/provider.rs index 48617fb..7a89e38 100644 --- a/src/provider.rs +++ b/src/provider.rs @@ -68,6 +68,7 @@ where let mut cal_local = cal_local.lock().unwrap(); // Step 1 - find the differences + log::debug!("* Finding the differences to sync..."); let mut local_del = HashSet::new(); let mut remote_del = HashSet::new(); let mut local_changes = HashSet::new(); @@ -78,13 +79,15 @@ where let remote_items = cal_remote.get_item_version_tags().await?; let mut local_items_to_handle = cal_local.get_item_ids().await?; for (id, remote_tag) in remote_items { + log::trace!("* Considering remote item {}...", id); match cal_local.get_item_by_id(&id).await { None => { // This was created on the remote + log::debug!("* {} is a remote addition", id); remote_additions.insert(id); }, Some(local_item) => { - if local_items_to_handle.remove(&id) == true { + if local_items_to_handle.remove(&id) == false { log::error!("Inconsistent state: missing task {} from the local tasks", id); } @@ -96,24 +99,29 @@ where SyncStatus::Synced(local_tag) => { if &remote_tag != local_tag { // This has been modified on the remote + log::debug!("* {} is a remote change", id); remote_changes.insert(id); } }, SyncStatus::LocallyModified(local_tag) => { if &remote_tag == local_tag { // This has been changed locally + log::debug!("* {} is a local change", id); local_changes.insert(id); } else { log::info!("Conflict: task {} has been modified in both sources. Using the remote version.", id); + log::debug!("* {} is considered a remote change", id); remote_changes.insert(id); } }, SyncStatus::LocallyDeleted(local_tag) => { if &remote_tag == local_tag { // This has been locally deleted + log::debug!("* {} is a local deletion", id); local_del.insert(id); } else { log::info!("Conflict: task {} has been locally deleted and remotely modified. Reverting to the remote version.", id); + log::debug!("* {} is a considered a remote change", id); remote_changes.insert(id); } }, @@ -124,6 +132,7 @@ where // Also iterate on the local tasks that are not on the remote for id in local_items_to_handle { + log::trace!("# Considering local item {}...", id); let local_item = match cal_local.get_item_by_id(&id).await { None => { log::error!("Inconsistent state: missing task {} from the local tasks", id); @@ -134,33 +143,52 @@ where match local_item.sync_status() { SyncStatus::Synced(_) => { // This item has been removed from the remote + log::debug!("# {} is a deletion from the server", id); remote_del.insert(id); }, SyncStatus::NotSynced => { // This item has just been locally created + log::debug!("# {} has been locally created", id); local_additions.insert(id); }, - variant @ _=> { - log::error!("Inconsistent state: unexpected variant {:?}", variant); + SyncStatus::LocallyDeleted(_) => { + // This item has been deleted from both sources + log::debug!("# {} has been deleted from both sources", id); + remote_del.insert(id); + }, + SyncStatus::LocallyModified(_) => { + log::info!("Conflict: item {} has been deleted from the server and locally modified. Deleting the local copy", id); + remote_del.insert(id); + }, } } - } // Step 2 - commit changes for id_del in local_del { - if let Err(err) = cal_remote.delete_item(&id_del).await { + log::debug!("> Pushing local deletion {} to the server", id_del); + match cal_remote.delete_item(&id_del).await { + Err(err) => { log::warn!("Unable to delete remote item {}: {}", id_del, err); + }, + Ok(()) => { + // Change the local copy from "marked to deletion" to "actually deleted" + if let Err(err) = cal_local.immediately_delete_item(&id_del).await { + log::error!("Unable to permanently delete local item {}: {}", id_del, err); + } + }, } } for id_del in remote_del { + log::debug!("> Applying remote deletion {} locally", id_del); if let Err(err) = cal_local.immediately_delete_item(&id_del).await { log::warn!("Unable to delete local item {}: {}", id_del, err); } } for id_add in remote_additions { + log::debug!("> Applying remote addition {} locally", id_add); match cal_remote.get_item_by_id(&id_add).await { None => { log::error!("Inconsistency: new item {} has vanished from the remote end", id_add); @@ -175,13 +203,14 @@ where } for id_change in remote_changes { + log::debug!("> Applying remote change {} locally", id_change); match cal_remote.get_item_by_id(&id_change).await { None => { log::error!("Inconsistency: modified item {} has vanished from the remote end", id_change); continue; }, Some(item) => { - if let Err(err) = cal_local.delete_item(&id_change).await { + if let Err(err) = cal_local.immediately_delete_item(&id_change).await { log::error!("Unable to delete item {} from local calendar: {}", id_change, err); } if let Err(err) = cal_local.add_item(item.clone()).await { @@ -193,6 +222,7 @@ where for id_add in local_additions { + log::debug!("> Pushing local addition {} to the server", id_add); match cal_local.get_item_by_id(&id_add).await { None => { log::error!("Inconsistency: created item {} has been marked for upload but is locally missing", id_add); @@ -207,6 +237,7 @@ where } for id_change in local_changes { + log::debug!("> Pushing local change {} to the server", id_change); match cal_local.get_item_by_id(&id_change).await { None => { log::error!("Inconsistency: modified item {} has been marked for upload but is locally missing", id_change); diff --git a/src/utils.rs b/src/utils.rs index c36be4d..9bc9474 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,6 +8,7 @@ use minidom::Element; use crate::traits::CompleteCalendar; use crate::calendar::CalendarId; use crate::Item; +use crate::item::SyncStatus; /// Walks an XML tree and returns every element that has the given name pub fn find_elems>(root: &Element, searched_name: S) -> Vec<&Element> { @@ -79,8 +80,18 @@ where pub fn print_task(item: &Item) { match item { Item::Task(task) => { - let completion = if task.completed() {"✓"} else {" "}; - println!(" {} {}\t{}", completion, task.name(), task.id()); + let mut status = String::new(); + if task.completed() { + status += "✓"; + } else { + status += " "; + } + match task.sync_status() { + SyncStatus::LocallyModified(_) => { status += "~"; }, + SyncStatus::LocallyDeleted(_) => { status += "x"; }, + _ => (), + } + println!(" {} {}\t{}", status, task.name(), task.id()); }, _ => return, }