|
|
|
@ -68,6 +68,7 @@ where |
|
|
|
let mut cal_local = cal_local.lock().unwrap(); |
|
|
|
let mut cal_local = cal_local.lock().unwrap(); |
|
|
|
|
|
|
|
|
|
|
|
// Step 1 - find the differences
|
|
|
|
// Step 1 - find the differences
|
|
|
|
|
|
|
|
log::debug!("* Finding the differences to sync..."); |
|
|
|
let mut local_del = HashSet::new(); |
|
|
|
let mut local_del = HashSet::new(); |
|
|
|
let mut remote_del = HashSet::new(); |
|
|
|
let mut remote_del = HashSet::new(); |
|
|
|
let mut local_changes = HashSet::new(); |
|
|
|
let mut local_changes = HashSet::new(); |
|
|
|
@ -78,13 +79,15 @@ where |
|
|
|
let remote_items = cal_remote.get_item_version_tags().await?; |
|
|
|
let remote_items = cal_remote.get_item_version_tags().await?; |
|
|
|
let mut local_items_to_handle = cal_local.get_item_ids().await?; |
|
|
|
let mut local_items_to_handle = cal_local.get_item_ids().await?; |
|
|
|
for (id, remote_tag) in remote_items { |
|
|
|
for (id, remote_tag) in remote_items { |
|
|
|
|
|
|
|
log::trace!("* Considering remote item {}...", id); |
|
|
|
match cal_local.get_item_by_id(&id).await { |
|
|
|
match cal_local.get_item_by_id(&id).await { |
|
|
|
None => { |
|
|
|
None => { |
|
|
|
// This was created on the remote
|
|
|
|
// This was created on the remote
|
|
|
|
|
|
|
|
log::debug!("* {} is a remote addition", id); |
|
|
|
remote_additions.insert(id); |
|
|
|
remote_additions.insert(id); |
|
|
|
}, |
|
|
|
}, |
|
|
|
Some(local_item) => { |
|
|
|
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); |
|
|
|
log::error!("Inconsistent state: missing task {} from the local tasks", id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -96,24 +99,29 @@ where |
|
|
|
SyncStatus::Synced(local_tag) => { |
|
|
|
SyncStatus::Synced(local_tag) => { |
|
|
|
if &remote_tag != local_tag { |
|
|
|
if &remote_tag != local_tag { |
|
|
|
// This has been modified on the remote
|
|
|
|
// This has been modified on the remote
|
|
|
|
|
|
|
|
log::debug!("* {} is a remote change", id); |
|
|
|
remote_changes.insert(id); |
|
|
|
remote_changes.insert(id); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
SyncStatus::LocallyModified(local_tag) => { |
|
|
|
SyncStatus::LocallyModified(local_tag) => { |
|
|
|
if &remote_tag == local_tag { |
|
|
|
if &remote_tag == local_tag { |
|
|
|
// This has been changed locally
|
|
|
|
// This has been changed locally
|
|
|
|
|
|
|
|
log::debug!("* {} is a local change", id); |
|
|
|
local_changes.insert(id); |
|
|
|
local_changes.insert(id); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
log::info!("Conflict: task {} has been modified in both sources. Using the remote version.", id); |
|
|
|
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); |
|
|
|
remote_changes.insert(id); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
SyncStatus::LocallyDeleted(local_tag) => { |
|
|
|
SyncStatus::LocallyDeleted(local_tag) => { |
|
|
|
if &remote_tag == local_tag { |
|
|
|
if &remote_tag == local_tag { |
|
|
|
// This has been locally deleted
|
|
|
|
// This has been locally deleted
|
|
|
|
|
|
|
|
log::debug!("* {} is a local deletion", id); |
|
|
|
local_del.insert(id); |
|
|
|
local_del.insert(id); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
log::info!("Conflict: task {} has been locally deleted and remotely modified. Reverting to the remote version.", id); |
|
|
|
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); |
|
|
|
remote_changes.insert(id); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
@ -124,6 +132,7 @@ where |
|
|
|
|
|
|
|
|
|
|
|
// Also iterate on the local tasks that are not on the remote
|
|
|
|
// Also iterate on the local tasks that are not on the remote
|
|
|
|
for id in local_items_to_handle { |
|
|
|
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 { |
|
|
|
let local_item = match cal_local.get_item_by_id(&id).await { |
|
|
|
None => { |
|
|
|
None => { |
|
|
|
log::error!("Inconsistent state: missing task {} from the local tasks", id); |
|
|
|
log::error!("Inconsistent state: missing task {} from the local tasks", id); |
|
|
|
@ -134,33 +143,52 @@ where |
|
|
|
match local_item.sync_status() { |
|
|
|
match local_item.sync_status() { |
|
|
|
SyncStatus::Synced(_) => { |
|
|
|
SyncStatus::Synced(_) => { |
|
|
|
// This item has been removed from the remote
|
|
|
|
// This item has been removed from the remote
|
|
|
|
|
|
|
|
log::debug!("# {} is a deletion from the server", id); |
|
|
|
remote_del.insert(id); |
|
|
|
remote_del.insert(id); |
|
|
|
}, |
|
|
|
}, |
|
|
|
SyncStatus::NotSynced => { |
|
|
|
SyncStatus::NotSynced => { |
|
|
|
// This item has just been locally created
|
|
|
|
// This item has just been locally created
|
|
|
|
|
|
|
|
log::debug!("# {} has been locally created", id); |
|
|
|
local_additions.insert(id); |
|
|
|
local_additions.insert(id); |
|
|
|
}, |
|
|
|
}, |
|
|
|
variant @ _=> { |
|
|
|
SyncStatus::LocallyDeleted(_) => { |
|
|
|
log::error!("Inconsistent state: unexpected variant {:?}", variant); |
|
|
|
// 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
|
|
|
|
// Step 2 - commit changes
|
|
|
|
for id_del in local_del { |
|
|
|
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); |
|
|
|
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 { |
|
|
|
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 { |
|
|
|
if let Err(err) = cal_local.immediately_delete_item(&id_del).await { |
|
|
|
log::warn!("Unable to delete local item {}: {}", id_del, err); |
|
|
|
log::warn!("Unable to delete local item {}: {}", id_del, err); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for id_add in remote_additions { |
|
|
|
for id_add in remote_additions { |
|
|
|
|
|
|
|
log::debug!("> Applying remote addition {} locally", id_add); |
|
|
|
match cal_remote.get_item_by_id(&id_add).await { |
|
|
|
match cal_remote.get_item_by_id(&id_add).await { |
|
|
|
None => { |
|
|
|
None => { |
|
|
|
log::error!("Inconsistency: new item {} has vanished from the remote end", id_add); |
|
|
|
log::error!("Inconsistency: new item {} has vanished from the remote end", id_add); |
|
|
|
@ -175,13 +203,14 @@ where |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for id_change in remote_changes { |
|
|
|
for id_change in remote_changes { |
|
|
|
|
|
|
|
log::debug!("> Applying remote change {} locally", id_change); |
|
|
|
match cal_remote.get_item_by_id(&id_change).await { |
|
|
|
match cal_remote.get_item_by_id(&id_change).await { |
|
|
|
None => { |
|
|
|
None => { |
|
|
|
log::error!("Inconsistency: modified item {} has vanished from the remote end", id_change); |
|
|
|
log::error!("Inconsistency: modified item {} has vanished from the remote end", id_change); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
}, |
|
|
|
}, |
|
|
|
Some(item) => { |
|
|
|
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); |
|
|
|
log::error!("Unable to delete item {} from local calendar: {}", id_change, err); |
|
|
|
} |
|
|
|
} |
|
|
|
if let Err(err) = cal_local.add_item(item.clone()).await { |
|
|
|
if let Err(err) = cal_local.add_item(item.clone()).await { |
|
|
|
@ -193,6 +222,7 @@ where |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for id_add in local_additions { |
|
|
|
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 { |
|
|
|
match cal_local.get_item_by_id(&id_add).await { |
|
|
|
None => { |
|
|
|
None => { |
|
|
|
log::error!("Inconsistency: created item {} has been marked for upload but is locally missing", id_add); |
|
|
|
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 { |
|
|
|
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 { |
|
|
|
match cal_local.get_item_by_id(&id_change).await { |
|
|
|
None => { |
|
|
|
None => { |
|
|
|
log::error!("Inconsistency: modified item {} has been marked for upload but is locally missing", id_change); |
|
|
|
log::error!("Inconsistency: modified item {} has been marked for upload but is locally missing", id_change); |
|
|
|
|