From 0075ebfbdb1bfdd916cfb6d4d98037dc4768c253 Mon Sep 17 00:00:00 2001 From: daladim Date: Tue, 16 Nov 2021 00:10:47 +0100 Subject: [PATCH] More ID -> URL renaming --- examples/provider-sync.rs | 30 +++--- src/cache.rs | 38 +++---- src/calendar/cached_calendar.rs | 72 ++++++------- src/calendar/mod.rs | 3 - src/calendar/remote_calendar.rs | 20 ++-- src/client.rs | 17 ++- src/ical/builder.rs | 4 +- src/mock_behaviour.rs | 8 +- src/provider/mod.rs | 183 ++++++++++++++++---------------- src/task.rs | 3 +- src/traits.rs | 31 +++--- src/utils/mod.rs | 17 ++- tests/scenarii.rs | 65 ++++++------ tests/sync.rs | 6 +- 14 files changed, 244 insertions(+), 253 deletions(-) diff --git a/examples/provider-sync.rs b/examples/provider-sync.rs index a93dbf5..666c0b1 100644 --- a/examples/provider-sync.rs +++ b/examples/provider-sync.rs @@ -6,7 +6,7 @@ use chrono::{Utc}; use url::Url; use kitchen_fridge::{client::Client, traits::CalDavSource}; -use kitchen_fridge::calendar::{CalendarId, SupportedComponents}; +use kitchen_fridge::calendar::SupportedComponents; use kitchen_fridge::Item; use kitchen_fridge::Task; use kitchen_fridge::task::CompletionStatus; @@ -81,27 +81,27 @@ async fn add_items_and_sync_again(provider: &mut CalDavProvider) pause(); // Create a new calendar... - let new_calendar_id: CalendarId = EXAMPLE_CREATED_CALENDAR_URL.parse().unwrap(); + let new_calendar_url: Url = EXAMPLE_CREATED_CALENDAR_URL.parse().unwrap(); let new_calendar_name = "A brave new calendar".to_string(); if let Err(_err) = provider.local_mut() - .create_calendar(new_calendar_id.clone(), new_calendar_name.clone(), SupportedComponents::TODO, None) + .create_calendar(new_calendar_url.clone(), new_calendar_name.clone(), SupportedComponents::TODO, None) .await { println!("Unable to add calendar, maybe it exists already. We're not adding it after all."); } // ...and add a task in it let new_name = "This is a new task in a new calendar"; - let new_task = Task::new(String::from(new_name), true, &new_calendar_id); - provider.local().get_calendar(&new_calendar_id).await.unwrap() + let new_task = Task::new(String::from(new_name), true, &new_calendar_url); + provider.local().get_calendar(&new_calendar_url).await.unwrap() .lock().unwrap().add_item(Item::Task(new_task)).await.unwrap(); // Also create a task in a previously existing calendar - let changed_calendar_id: CalendarId = EXAMPLE_EXISTING_CALENDAR_URL.parse().unwrap(); + let changed_calendar_url: Url = EXAMPLE_EXISTING_CALENDAR_URL.parse().unwrap(); let new_task_name = "This is a new task we're adding as an example, with ÜTF-8 characters"; - let new_task = Task::new(String::from(new_task_name), false, &changed_calendar_id); + let new_task = Task::new(String::from(new_task_name), false, &changed_calendar_url); let new_url = new_task.url().clone(); - provider.local().get_calendar(&changed_calendar_id).await.unwrap() + provider.local().get_calendar(&changed_calendar_url).await.unwrap() .lock().unwrap().add_item(Item::Task(new_task)).await.unwrap(); @@ -112,20 +112,20 @@ async fn add_items_and_sync_again(provider: &mut CalDavProvider) } provider.local().save_to_folder().unwrap(); - complete_item_and_sync_again(provider, &changed_calendar_id, &new_url).await; + complete_item_and_sync_again(provider, &changed_calendar_url, &new_url).await; } async fn complete_item_and_sync_again( provider: &mut CalDavProvider, - changed_calendar_id: &CalendarId, + changed_calendar_url: &Url, url_to_complete: &Url) { println!("\nNow, we'll mark this last task as completed, and run the sync again."); pause(); let completion_status = CompletionStatus::Completed(Some(Utc::now())); - provider.local().get_calendar(changed_calendar_id).await.unwrap() - .lock().unwrap().get_item_by_id_mut(url_to_complete).await.unwrap() + provider.local().get_calendar(changed_calendar_url).await.unwrap() + .lock().unwrap().get_item_by_url_mut(url_to_complete).await.unwrap() .unwrap_task_mut() .set_completion_status(completion_status); @@ -136,19 +136,19 @@ async fn complete_item_and_sync_again( } provider.local().save_to_folder().unwrap(); - remove_items_and_sync_again(provider, changed_calendar_id, url_to_complete).await; + remove_items_and_sync_again(provider, changed_calendar_url, url_to_complete).await; } async fn remove_items_and_sync_again( provider: &mut CalDavProvider, - changed_calendar_id: &CalendarId, + changed_calendar_url: &Url, id_to_remove: &Url) { println!("\nNow, we'll delete this last task, and run the sync again."); pause(); // Remove the task we had created - provider.local().get_calendar(changed_calendar_id).await.unwrap() + provider.local().get_calendar(changed_calendar_url).await.unwrap() .lock().unwrap() .mark_for_deletion(id_to_remove).await.unwrap(); diff --git a/src/cache.rs b/src/cache.rs index 926ec43..062fb85 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -10,12 +10,12 @@ use std::ffi::OsStr; use serde::{Deserialize, Serialize}; use async_trait::async_trait; use csscolorparser::Color; +use url::Url; use crate::traits::CalDavSource; use crate::traits::BaseCalendar; use crate::traits::CompleteCalendar; use crate::calendar::cached_calendar::CachedCalendar; -use crate::calendar::CalendarId; use crate::calendar::SupportedComponents; #[cfg(feature = "local_calendar_mocks_remote_calendars")] @@ -41,7 +41,7 @@ pub struct Cache { #[derive(Default, Debug, Serialize, Deserialize)] struct CachedData { #[serde(skip)] - calendars: HashMap>>, + calendars: HashMap>>, } impl Cache { @@ -131,8 +131,8 @@ impl Cache { serde_json::to_writer(file, &self.data)?; // Save each calendar - for (cal_id, cal_mutex) in &self.data.calendars { - let file_name = sanitize_filename::sanitize(cal_id.as_str()) + ".cal"; + for (cal_url, cal_mutex) in &self.data.calendars { + let file_name = sanitize_filename::sanitize(cal_url.as_str()) + ".cal"; let cal_file = folder.join(file_name); let file = std::fs::File::create(&cal_file)?; let cal = cal_mutex.lock().unwrap(); @@ -156,10 +156,10 @@ impl Cache { return Ok(false); } - for (calendar_id, cal_l) in calendars_l { - log::debug!("Comparing calendars {}", calendar_id); + for (calendar_url, cal_l) in calendars_l { + log::debug!("Comparing calendars {}", calendar_url); let cal_l = cal_l.lock().unwrap(); - let cal_r = match calendars_r.get(&calendar_id) { + let cal_r = match calendars_r.get(&calendar_url) { Some(c) => c.lock().unwrap(), None => return Err("should not happen, we've just tested keys are the same".into()), }; @@ -185,38 +185,38 @@ impl Drop for Cache { impl Cache { /// The non-async version of [`crate::traits::CalDavSource::get_calendars`] - pub fn get_calendars_sync(&self) -> Result>>, Box> { + pub fn get_calendars_sync(&self) -> Result>>, Box> { #[cfg(feature = "local_calendar_mocks_remote_calendars")] self.mock_behaviour.as_ref().map_or(Ok(()), |b| b.lock().unwrap().can_get_calendars())?; Ok(self.data.calendars.iter() - .map(|(id, cal)| (id.clone(), cal.clone())) + .map(|(url, cal)| (url.clone(), cal.clone())) .collect() ) } /// The non-async version of [`crate::traits::CalDavSource::get_calendar`] - pub fn get_calendar_sync(&self, id: &CalendarId) -> Option>> { - self.data.calendars.get(id).map(|arc| arc.clone()) + pub fn get_calendar_sync(&self, url: &Url) -> Option>> { + self.data.calendars.get(url).map(|arc| arc.clone()) } } #[async_trait] impl CalDavSource for Cache { - async fn get_calendars(&self) -> Result>>, Box> { + async fn get_calendars(&self) -> Result>>, Box> { self.get_calendars_sync() } - async fn get_calendar(&self, id: &CalendarId) -> Option>> { - self.get_calendar_sync(id) + async fn get_calendar(&self, url: &Url) -> Option>> { + self.get_calendar_sync(url) } - async fn create_calendar(&mut self, id: CalendarId, name: String, supported_components: SupportedComponents, color: Option) -> Result>, Box> { - log::debug!("Inserting local calendar {}", id); + async fn create_calendar(&mut self, url: Url, name: String, supported_components: SupportedComponents, color: Option) -> Result>, Box> { + log::debug!("Inserting local calendar {}", url); #[cfg(feature = "local_calendar_mocks_remote_calendars")] self.mock_behaviour.as_ref().map_or(Ok(()), |b| b.lock().unwrap().can_create_calendar())?; - let new_calendar = CachedCalendar::new(name, id.clone(), supported_components, color); + let new_calendar = CachedCalendar::new(name, url.clone(), supported_components, color); let arc = Arc::new(Mutex::new(new_calendar)); #[cfg(feature = "local_calendar_mocks_remote_calendars")] @@ -224,7 +224,7 @@ impl CalDavSource for Cache { arc.lock().unwrap().set_mock_behaviour(Some(Arc::clone(behaviour))); }; - match self.data.calendars.insert(id, arc.clone()) { + match self.data.calendars.insert(url, arc.clone()) { Some(_) => Err("Attempt to insert calendar failed: there is alredy such a calendar.".into()), None => Ok(arc), } @@ -293,7 +293,7 @@ mod tests { let cache_path = PathBuf::from(String::from("test_cache/sanity_tests")); let mut cache = populate_cache(&cache_path).await; - // We should not be able to add a second calendar with the same id + // We should not be able to add a second calendar with the same URL let second_addition_same_calendar = cache.create_calendar( Url::parse("https://caldav.com/shopping").unwrap(), "My shopping list".to_string(), diff --git a/src/calendar/cached_calendar.rs b/src/calendar/cached_calendar.rs index aa14db8..502cdbd 100644 --- a/src/calendar/cached_calendar.rs +++ b/src/calendar/cached_calendar.rs @@ -8,7 +8,7 @@ use url::Url; use crate::item::SyncStatus; use crate::traits::{BaseCalendar, CompleteCalendar}; -use crate::calendar::{CalendarId, SupportedComponents}; +use crate::calendar::SupportedComponents; use crate::Item; #[cfg(feature = "local_calendar_mocks_remote_calendars")] @@ -102,13 +102,13 @@ impl CachedCalendar { log::debug!("Different keys for items"); return Ok(false); } - for (id_l, item_l) in items_l { - let item_r = match items_r.get(&id_l) { + for (url_l, item_l) in items_l { + let item_r = match items_r.get(&url_l) { Some(c) => c, None => return Err("should not happen, we've just tested keys are the same".into()), }; if item_l.has_same_observable_content_as(&item_r) == false { - log::debug!("Different items for id {}:", id_l); + log::debug!("Different items for URL {}:", url_l); log::debug!("{:#?}", item_l); log::debug!("{:#?}", item_r); return Ok(false); @@ -118,8 +118,8 @@ impl CachedCalendar { Ok(true) } - /// The non-async version of [`Self::get_item_ids`] - pub fn get_item_ids_sync(&self) -> Result, Box> { + /// The non-async version of [`Self::get_item_urls`] + pub fn get_item_urls_sync(&self) -> Result, Box> { Ok(self.items.iter() .map(|(url, _)| url.clone()) .collect() @@ -134,14 +134,14 @@ impl CachedCalendar { ) } - /// The non-async version of [`Self::get_item_by_id`] - pub fn get_item_by_id_sync<'a>(&'a self, id: &Url) -> Option<&'a Item> { - self.items.get(id) + /// The non-async version of [`Self::get_item_by_url`] + pub fn get_item_by_url_sync<'a>(&'a self, url: &Url) -> Option<&'a Item> { + self.items.get(url) } - /// The non-async version of [`Self::get_item_by_id_mut`] - pub fn get_item_by_id_mut_sync<'a>(&'a mut self, id: &Url) -> Option<&'a mut Item> { - self.items.get_mut(id) + /// The non-async version of [`Self::get_item_by_url_mut`] + pub fn get_item_by_url_mut_sync<'a>(&'a mut self, url: &Url) -> Option<&'a mut Item> { + self.items.get_mut(url) } /// The non-async version of [`Self::add_item`] @@ -169,8 +169,8 @@ impl CachedCalendar { } /// The non-async version of [`Self::mark_for_deletion`] - pub fn mark_for_deletion_sync(&mut self, item_id: &Url) -> Result<(), Box> { - match self.items.get_mut(item_id) { + pub fn mark_for_deletion_sync(&mut self, item_url: &Url) -> Result<(), Box> { + match self.items.get_mut(item_url) { None => Err("no item for this key".into()), Some(item) => { match item.sync_status() { @@ -188,7 +188,7 @@ impl CachedCalendar { }, SyncStatus::NotSynced => { // This was never synced to the server, we can safely delete it as soon as now - self.items.remove(item_id); + self.items.remove(item_url); }, }; Ok(()) @@ -197,9 +197,9 @@ impl CachedCalendar { } /// The non-async version of [`Self::immediately_delete_item`] - pub fn immediately_delete_item_sync(&mut self, item_id: &Url) -> Result<(), Box> { - match self.items.remove(item_id) { - None => Err(format!("Item {} is absent from this calendar", item_id).into()), + pub fn immediately_delete_item_sync(&mut self, item_url: &Url) -> Result<(), Box> { + match self.items.remove(item_url) { + None => Err(format!("Item {} is absent from this calendar", item_url).into()), Some(_) => Ok(()) } } @@ -236,7 +236,7 @@ impl BaseCalendar for CachedCalendar { #[async_trait] impl CompleteCalendar for CachedCalendar { - fn new(name: String, url: CalendarId, supported_components: SupportedComponents, color: Option) -> Self { + fn new(name: String, url: Url, supported_components: SupportedComponents, color: Option) -> Self { Self { name, url, supported_components, color, #[cfg(feature = "local_calendar_mocks_remote_calendars")] @@ -245,28 +245,28 @@ impl CompleteCalendar for CachedCalendar { } } - async fn get_item_ids(&self) -> Result, Box> { - self.get_item_ids_sync() + async fn get_item_urls(&self) -> Result, Box> { + self.get_item_urls_sync() } async fn get_items(&self) -> Result, Box> { self.get_items_sync() } - async fn get_item_by_id<'a>(&'a self, id: &Url) -> Option<&'a Item> { - self.get_item_by_id_sync(id) + async fn get_item_by_url<'a>(&'a self, url: &Url) -> Option<&'a Item> { + self.get_item_by_url_sync(url) } - async fn get_item_by_id_mut<'a>(&'a mut self, id: &Url) -> Option<&'a mut Item> { - self.get_item_by_id_mut_sync(id) + async fn get_item_by_url_mut<'a>(&'a mut self, url: &Url) -> Option<&'a mut Item> { + self.get_item_by_url_mut_sync(url) } - async fn mark_for_deletion(&mut self, item_id: &Url) -> Result<(), Box> { - self.mark_for_deletion_sync(item_id) + async fn mark_for_deletion(&mut self, item_url: &Url) -> Result<(), Box> { + self.mark_for_deletion_sync(item_url) } - async fn immediately_delete_item(&mut self, item_id: &Url) -> Result<(), Box> { - self.immediately_delete_item_sync(item_id) + async fn immediately_delete_item(&mut self, item_url: &Url) -> Result<(), Box> { + self.immediately_delete_item_sync(item_url) } } @@ -294,30 +294,30 @@ impl DavCalendar for CachedCalendar { let mut result = HashMap::new(); - for (id, item) in self.items.iter() { + for (url, item) in self.items.iter() { let vt = match item.sync_status() { SyncStatus::Synced(vt) => vt.clone(), _ => { panic!("Mock calendars must contain only SyncStatus::Synced. Got {:?}", item); } }; - result.insert(id.clone(), vt); + result.insert(url.clone(), vt); } Ok(result) } - async fn get_item_by_id(&self, id: &Url) -> Result, Box> { + async fn get_item_by_url(&self, url: &Url) -> Result, Box> { #[cfg(feature = "local_calendar_mocks_remote_calendars")] - self.mock_behaviour.as_ref().map_or(Ok(()), |b| b.lock().unwrap().can_get_item_by_id())?; + self.mock_behaviour.as_ref().map_or(Ok(()), |b| b.lock().unwrap().can_get_item_by_url())?; - Ok(self.items.get(id).cloned()) + Ok(self.items.get(url).cloned()) } - async fn delete_item(&mut self, item_id: &Url) -> Result<(), Box> { + async fn delete_item(&mut self, item_url: &Url) -> Result<(), Box> { #[cfg(feature = "local_calendar_mocks_remote_calendars")] self.mock_behaviour.as_ref().map_or(Ok(()), |b| b.lock().unwrap().can_delete_item())?; - self.immediately_delete_item(item_id).await + self.immediately_delete_item(item_url).await } } diff --git a/src/calendar/mod.rs b/src/calendar/mod.rs index 8ff675b..9ccce9b 100644 --- a/src/calendar/mod.rs +++ b/src/calendar/mod.rs @@ -77,6 +77,3 @@ impl Default for SearchFilter { SearchFilter::All } } - - -pub type CalendarId = url::Url; diff --git a/src/calendar/remote_calendar.rs b/src/calendar/remote_calendar.rs index 050c78a..f4f1ab1 100644 --- a/src/calendar/remote_calendar.rs +++ b/src/calendar/remote_calendar.rs @@ -138,7 +138,7 @@ impl DavCalendar for RemoteCalendar { for response in responses { let item_url = crate::utils::find_elem(&response, "href") .map(|elem| self.resource.combine(&elem.text())); - let item_id = match item_url { + let item_url = match item_url { None => { log::warn!("Unable to extract HREF"); continue; @@ -150,7 +150,7 @@ impl DavCalendar for RemoteCalendar { let version_tag = match crate::utils::find_elem(&response, "getetag") { None => { - log::warn!("Unable to extract ETAG for item {}, ignoring it", item_id); + log::warn!("Unable to extract ETAG for item {}, ignoring it", item_url); continue; }, Some(etag) => { @@ -158,7 +158,7 @@ impl DavCalendar for RemoteCalendar { } }; - items.insert(item_id.clone(), version_tag); + items.insert(item_url.clone(), version_tag); } // Note: the mutex cannot be locked during this whole async function, but it can safely be re-entrant (this will just waste an unnecessary request) @@ -166,9 +166,9 @@ impl DavCalendar for RemoteCalendar { Ok(items) } - async fn get_item_by_id(&self, id: &Url) -> Result, Box> { + async fn get_item_by_url(&self, url: &Url) -> Result, Box> { let res = reqwest::Client::new() - .get(id.clone()) + .get(url.clone()) .header(CONTENT_TYPE, "text/calendar") .basic_auth(self.resource.username(), Some(self.resource.password())) .send() @@ -182,18 +182,18 @@ impl DavCalendar for RemoteCalendar { // This is supposed to be cached let version_tags = self.get_item_version_tags().await?; - let vt = match version_tags.get(id) { - None => return Err(format!("Inconsistent data: {} has no version tag", id).into()), + let vt = match version_tags.get(url) { + None => return Err(format!("Inconsistent data: {} has no version tag", url).into()), Some(vt) => vt, }; - let item = crate::ical::parse(&text, id.clone(), SyncStatus::Synced(vt.clone()))?; + let item = crate::ical::parse(&text, url.clone(), SyncStatus::Synced(vt.clone()))?; Ok(Some(item)) } - async fn delete_item(&mut self, item_id: &Url) -> Result<(), Box> { + async fn delete_item(&mut self, item_url: &Url) -> Result<(), Box> { let del_response = reqwest::Client::new() - .delete(item_id.clone()) + .delete(item_url.clone()) .basic_auth(self.resource.username(), Some(self.resource.password())) .send() .await?; diff --git a/src/client.rs b/src/client.rs index 242a1a1..a4d843e 100644 --- a/src/client.rs +++ b/src/client.rs @@ -15,7 +15,6 @@ use csscolorparser::Color; use crate::resource::Resource; use crate::utils::{find_elem, find_elems}; use crate::calendar::remote_calendar::RemoteCalendar; -use crate::calendar::CalendarId; use crate::calendar::SupportedComponents; use crate::traits::CalDavSource; use crate::traits::BaseCalendar; @@ -113,7 +112,7 @@ pub struct Client { struct CachedReplies { principal: Option, calendar_home_set: Option, - calendars: Option>>>, + calendars: Option>>>, } impl Client { @@ -228,7 +227,7 @@ impl Client { #[async_trait] impl CalDavSource for Client { - async fn get_calendars(&self) -> Result>>, Box> { + async fn get_calendars(&self) -> Result>>, Box> { self.populate_calendars().await?; match &self.cached_replies.lock().unwrap().calendars { @@ -239,7 +238,7 @@ impl CalDavSource for Client { }; } - async fn get_calendar(&self, id: &CalendarId) -> Option>> { + async fn get_calendar(&self, url: &Url) -> Option>> { if let Err(err) = self.populate_calendars().await { log::warn!("Unable to fetch calendars: {}", err); return None; @@ -248,17 +247,17 @@ impl CalDavSource for Client { self.cached_replies.lock().unwrap() .calendars .as_ref() - .and_then(|cals| cals.get(id)) + .and_then(|cals| cals.get(url)) .map(|cal| cal.clone()) } - async fn create_calendar(&mut self, id: CalendarId, name: String, supported_components: SupportedComponents, color: Option) -> Result>, Box> { + async fn create_calendar(&mut self, url: Url, name: String, supported_components: SupportedComponents, color: Option) -> Result>, Box> { self.populate_calendars().await?; match self.cached_replies.lock().unwrap().calendars.as_ref() { None => return Err("No calendars have been fetched".into()), Some(cals) => { - if cals.contains_key(&id) { + if cals.contains_key(&url) { return Err("This calendar already exists".into()); } }, @@ -267,7 +266,7 @@ impl CalDavSource for Client { let creation_body = calendar_body(name, supported_components); let response = reqwest::Client::new() - .request(Method::from_bytes(b"MKCALENDAR").unwrap(), id.clone()) + .request(Method::from_bytes(b"MKCALENDAR").unwrap(), url.clone()) .header(CONTENT_TYPE, "application/xml") .basic_auth(self.resource.username(), Some(self.resource.password())) .body(creation_body) @@ -279,7 +278,7 @@ impl CalDavSource for Client { return Err(format!("Unexpected HTTP status code. Expected CREATED, got {}", status.as_u16()).into()); } - self.get_calendar(&id).await.ok_or(format!("Unable to insert calendar {:?}", id).into()) + self.get_calendar(&url).await.ok_or(format!("Unable to insert calendar {:?}", url).into()) } } diff --git a/src/ical/builder.rs b/src/ical/builder.rs index 05550e9..3e4840e 100644 --- a/src/ical/builder.rs +++ b/src/ical/builder.rs @@ -130,12 +130,12 @@ mod tests { } fn build_task(completed: bool) -> (String, String, String) { - let cal_id = "http://my.calend.ar/id".parse().unwrap(); + let cal_url = "http://my.calend.ar/id".parse().unwrap(); let now = Utc::now(); let s_now = format_date_time(&now); let task = Item::Task(Task::new( - String::from("This is a task with ÜTF-8 characters"), completed, &cal_id + String::from("This is a task with ÜTF-8 characters"), completed, &cal_url )); let ical = build_from(&task).unwrap(); diff --git a/src/mock_behaviour.rs b/src/mock_behaviour.rs index c40c368..c5c8bd1 100644 --- a/src/mock_behaviour.rs +++ b/src/mock_behaviour.rs @@ -22,7 +22,7 @@ pub struct MockBehaviour { // From the DavCalendar trait pub get_item_version_tags_behaviour: (u32, u32), - pub get_item_by_id_behaviour: (u32, u32), + pub get_item_by_url_behaviour: (u32, u32), pub delete_item_behaviour: (u32, u32), } @@ -41,7 +41,7 @@ impl MockBehaviour { add_item_behaviour: (0, n_fails), update_item_behaviour: (0, n_fails), get_item_version_tags_behaviour: (0, n_fails), - get_item_by_id_behaviour: (0, n_fails), + get_item_by_url_behaviour: (0, n_fails), delete_item_behaviour: (0, n_fails), } } @@ -84,9 +84,9 @@ impl MockBehaviour { if self.is_suspended { return Ok(()) } decrement(&mut self.get_item_version_tags_behaviour, "get_item_version_tags") } - pub fn can_get_item_by_id(&mut self) -> Result<(), Box> { + pub fn can_get_item_by_url(&mut self) -> Result<(), Box> { if self.is_suspended { return Ok(()) } - decrement(&mut self.get_item_by_id_behaviour, "get_item_by_id") + decrement(&mut self.get_item_by_url_behaviour, "get_item_by_url") } pub fn can_delete_item(&mut self) -> Result<(), Box> { if self.is_suspended { return Ok(()) } diff --git a/src/provider/mod.rs b/src/provider/mod.rs index 2e9fb84..aaca96f 100644 --- a/src/provider/mod.rs +++ b/src/provider/mod.rs @@ -11,7 +11,6 @@ use url::Url; use crate::traits::{BaseCalendar, CalDavSource, DavCalendar}; use crate::traits::CompleteCalendar; use crate::item::SyncStatus; -use crate::calendar::CalendarId; pub mod sync_progress; use sync_progress::SyncProgress; @@ -103,39 +102,39 @@ where // Sync every remote calendar let cals_remote = self.remote.get_calendars().await?; - for (cal_id, cal_remote) in cals_remote { - let counterpart = match self.get_or_insert_local_counterpart_calendar(&cal_id, cal_remote.clone()).await { + for (cal_url, cal_remote) in cals_remote { + let counterpart = match self.get_or_insert_local_counterpart_calendar(&cal_url, cal_remote.clone()).await { Err(err) => { - progress.warn(&format!("Unable to get or insert local counterpart calendar for {} ({}). Skipping this time", cal_id, err)); + progress.warn(&format!("Unable to get or insert local counterpart calendar for {} ({}). Skipping this time", cal_url, err)); continue; }, Ok(arc) => arc, }; if let Err(err) = Self::sync_calendar_pair(counterpart, cal_remote, progress).await { - progress.warn(&format!("Unable to sync calendar {}: {}, skipping this time.", cal_id, err)); + progress.warn(&format!("Unable to sync calendar {}: {}, skipping this time.", cal_url, err)); continue; } - handled_calendars.insert(cal_id); + handled_calendars.insert(cal_url); } // Sync every local calendar that would not be in the remote yet let cals_local = self.local.get_calendars().await?; - for (cal_id, cal_local) in cals_local { - if handled_calendars.contains(&cal_id) { + for (cal_url, cal_local) in cals_local { + if handled_calendars.contains(&cal_url) { continue; } - let counterpart = match self.get_or_insert_remote_counterpart_calendar(&cal_id, cal_local.clone()).await { + let counterpart = match self.get_or_insert_remote_counterpart_calendar(&cal_url, cal_local.clone()).await { Err(err) => { - progress.warn(&format!("Unable to get or insert remote counterpart calendar for {} ({}). Skipping this time", cal_id, err)); + progress.warn(&format!("Unable to get or insert remote counterpart calendar for {} ({}). Skipping this time", cal_url, err)); continue; }, Ok(arc) => arc, }; if let Err(err) = Self::sync_calendar_pair(cal_local, counterpart, progress).await { - progress.warn(&format!("Unable to sync calendar {}: {}, skipping this time.", cal_id, err)); + progress.warn(&format!("Unable to sync calendar {}: {}, skipping this time.", cal_url, err)); continue; } } @@ -146,11 +145,11 @@ where } - async fn get_or_insert_local_counterpart_calendar(&mut self, cal_id: &CalendarId, needle: Arc>) -> Result>, Box> { - get_or_insert_counterpart_calendar("local", &mut self.local, cal_id, needle).await + async fn get_or_insert_local_counterpart_calendar(&mut self, cal_url: &Url, needle: Arc>) -> Result>, Box> { + get_or_insert_counterpart_calendar("local", &mut self.local, cal_url, needle).await } - async fn get_or_insert_remote_counterpart_calendar(&mut self, cal_id: &CalendarId, needle: Arc>) -> Result>, Box> { - get_or_insert_counterpart_calendar("remote", &mut self.remote, cal_id, needle).await + async fn get_or_insert_remote_counterpart_calendar(&mut self, cal_url: &Url, needle: Arc>) -> Result>, Box> { + get_or_insert_counterpart_calendar("remote", &mut self.remote, cal_url, needle).await } @@ -180,52 +179,52 @@ where details: format!("{} remote items", remote_items.len()), }); - let mut local_items_to_handle = cal_local.get_item_ids().await?; - for (id, remote_tag) in remote_items { - progress.trace(&format!("***** Considering remote item {}...", id)); - match cal_local.get_item_by_id(&id).await { + let mut local_items_to_handle = cal_local.get_item_urls().await?; + for (url, remote_tag) in remote_items { + progress.trace(&format!("***** Considering remote item {}...", url)); + match cal_local.get_item_by_url(&url).await { None => { // This was created on the remote - progress.debug(&format!("* {} is a remote addition", id)); - remote_additions.insert(id); + progress.debug(&format!("* {} is a remote addition", url)); + remote_additions.insert(url); }, Some(local_item) => { - if local_items_to_handle.remove(&id) == false { - progress.error(&format!("Inconsistent state: missing task {} from the local tasks", id)); + if local_items_to_handle.remove(&url) == false { + progress.error(&format!("Inconsistent state: missing task {} from the local tasks", url)); } match local_item.sync_status() { SyncStatus::NotSynced => { - progress.error(&format!("ID reuse between remote and local sources ({}). Ignoring this item in the sync", id)); + progress.error(&format!("URL reuse between remote and local sources ({}). Ignoring this item in the sync", url)); continue; }, SyncStatus::Synced(local_tag) => { if &remote_tag != local_tag { // This has been modified on the remote - progress.debug(&format!("* {} is a remote change", id)); - remote_changes.insert(id); + progress.debug(&format!("* {} is a remote change", url)); + remote_changes.insert(url); } }, SyncStatus::LocallyModified(local_tag) => { if &remote_tag == local_tag { // This has been changed locally - progress.debug(&format!("* {} is a local change", id)); - local_changes.insert(id); + progress.debug(&format!("* {} is a local change", url)); + local_changes.insert(url); } else { - progress.info(&format!("Conflict: task {} has been modified in both sources. Using the remote version.", id)); - progress.debug(&format!("* {} is considered a remote change", id)); - remote_changes.insert(id); + progress.info(&format!("Conflict: task {} has been modified in both sources. Using the remote version.", url)); + progress.debug(&format!("* {} is considered a remote change", url)); + remote_changes.insert(url); } }, SyncStatus::LocallyDeleted(local_tag) => { if &remote_tag == local_tag { // This has been locally deleted - progress.debug(&format!("* {} is a local deletion", id)); - local_del.insert(id); + progress.debug(&format!("* {} is a local deletion", url)); + local_del.insert(url); } else { - progress.info(&format!("Conflict: task {} has been locally deleted and remotely modified. Reverting to the remote version.", id)); - progress.debug(&format!("* {} is a considered a remote change", id)); - remote_changes.insert(id); + progress.info(&format!("Conflict: task {} has been locally deleted and remotely modified. Reverting to the remote version.", url)); + progress.debug(&format!("* {} is a considered a remote change", url)); + remote_changes.insert(url); } }, } @@ -234,11 +233,11 @@ where } // Also iterate on the local tasks that are not on the remote - for id in local_items_to_handle { - progress.trace(&format!("##### Considering local item {}...", id)); - let local_item = match cal_local.get_item_by_id(&id).await { + for url in local_items_to_handle { + progress.trace(&format!("##### Considering local item {}...", url)); + let local_item = match cal_local.get_item_by_url(&url).await { None => { - progress.error(&format!("Inconsistent state: missing task {} from the local tasks", id)); + progress.error(&format!("Inconsistent state: missing task {} from the local tasks", url)); continue; }, Some(item) => item, @@ -247,22 +246,22 @@ where match local_item.sync_status() { SyncStatus::Synced(_) => { // This item has been removed from the remote - progress.debug(&format!("# {} is a deletion from the server", id)); - remote_del.insert(id); + progress.debug(&format!("# {} is a deletion from the server", url)); + remote_del.insert(url); }, SyncStatus::NotSynced => { // This item has just been locally created - progress.debug(&format!("# {} has been locally created", id)); - local_additions.insert(id); + progress.debug(&format!("# {} has been locally created", url)); + local_additions.insert(url); }, SyncStatus::LocallyDeleted(_) => { // This item has been deleted from both sources - progress.debug(&format!("# {} has been deleted from both sources", id)); - remote_del.insert(id); + progress.debug(&format!("# {} has been deleted from both sources", url)); + remote_del.insert(url); }, SyncStatus::LocallyModified(_) => { - progress.info(&format!("Conflict: item {} has been deleted from the server and locally modified. Deleting the local copy", id)); - remote_del.insert(id); + progress.info(&format!("Conflict: item {} has been deleted from the server and locally modified. Deleting the local copy", url)); + remote_del.insert(url); }, } } @@ -270,80 +269,80 @@ where // Step 2 - commit changes progress.trace("Committing changes..."); - for id_del in local_del { - progress.debug(&format!("> Pushing local deletion {} to the server", id_del)); + for url_del in local_del { + progress.debug(&format!("> Pushing local deletion {} to the server", url_del)); progress.feedback(SyncEvent::InProgress{ calendar: cal_name.clone(), - details: Self::item_name(&cal_local, &id_del).await, + details: Self::item_name(&cal_local, &url_del).await, }); - match cal_remote.delete_item(&id_del).await { + match cal_remote.delete_item(&url_del).await { Err(err) => { - progress.warn(&format!("Unable to delete remote item {}: {}", id_del, err)); + progress.warn(&format!("Unable to delete remote item {}: {}", url_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 { - progress.error(&format!("Unable to permanently delete local item {}: {}", id_del, err)); + if let Err(err) = cal_local.immediately_delete_item(&url_del).await { + progress.error(&format!("Unable to permanently delete local item {}: {}", url_del, err)); } }, } } - for id_del in remote_del { - progress.debug(&format!("> Applying remote deletion {} locally", id_del)); + for url_del in remote_del { + progress.debug(&format!("> Applying remote deletion {} locally", url_del)); progress.feedback(SyncEvent::InProgress{ calendar: cal_name.clone(), - details: Self::item_name(&cal_local, &id_del).await, + details: Self::item_name(&cal_local, &url_del).await, }); - if let Err(err) = cal_local.immediately_delete_item(&id_del).await { - progress.warn(&format!("Unable to delete local item {}: {}", id_del, err)); + if let Err(err) = cal_local.immediately_delete_item(&url_del).await { + progress.warn(&format!("Unable to delete local item {}: {}", url_del, err)); } } - for id_add in remote_additions { - progress.debug(&format!("> Applying remote addition {} locally", id_add)); + for url_add in remote_additions { + progress.debug(&format!("> Applying remote addition {} locally", url_add)); progress.feedback(SyncEvent::InProgress{ calendar: cal_name.clone(), - details: Self::item_name(&cal_local, &id_add).await, + details: Self::item_name(&cal_local, &url_add).await, }); - match cal_remote.get_item_by_id(&id_add).await { + match cal_remote.get_item_by_url(&url_add).await { Err(err) => { - progress.warn(&format!("Unable to get remote item {}: {}. Skipping it.", id_add, err)); + progress.warn(&format!("Unable to get remote item {}: {}. Skipping it.", url_add, err)); continue; }, Ok(item) => match item { None => { - progress.error(&format!("Inconsistency: new item {} has vanished from the remote end", id_add)); + progress.error(&format!("Inconsistency: new item {} has vanished from the remote end", url_add)); continue; }, Some(new_item) => { if let Err(err) = cal_local.add_item(new_item.clone()).await { - progress.error(&format!("Not able to add item {} to local calendar: {}", id_add, err)); + progress.error(&format!("Not able to add item {} to local calendar: {}", url_add, err)); } }, }, } } - for id_change in remote_changes { - progress.debug(&format!("> Applying remote change {} locally", id_change)); + for url_change in remote_changes { + progress.debug(&format!("> Applying remote change {} locally", url_change)); progress.feedback(SyncEvent::InProgress{ calendar: cal_name.clone(), - details: Self::item_name(&cal_local, &id_change).await, + details: Self::item_name(&cal_local, &url_change).await, }); - match cal_remote.get_item_by_id(&id_change).await { + match cal_remote.get_item_by_url(&url_change).await { Err(err) => { - progress.warn(&format!("Unable to get remote item {}: {}. Skipping it", id_change, err)); + progress.warn(&format!("Unable to get remote item {}: {}. Skipping it", url_change, err)); continue; }, Ok(item) => match item { None => { - progress.error(&format!("Inconsistency: modified item {} has vanished from the remote end", id_change)); + progress.error(&format!("Inconsistency: modified item {} has vanished from the remote end", url_change)); continue; }, Some(item) => { if let Err(err) = cal_local.update_item(item.clone()).await { - progress.error(&format!("Unable to update item {} in local calendar: {}", id_change, err)); + progress.error(&format!("Unable to update item {} in local calendar: {}", url_change, err)); } }, } @@ -351,20 +350,20 @@ where } - for id_add in local_additions { - progress.debug(&format!("> Pushing local addition {} to the server", id_add)); + for url_add in local_additions { + progress.debug(&format!("> Pushing local addition {} to the server", url_add)); progress.feedback(SyncEvent::InProgress{ calendar: cal_name.clone(), - details: Self::item_name(&cal_local, &id_add).await, + details: Self::item_name(&cal_local, &url_add).await, }); - match cal_local.get_item_by_id_mut(&id_add).await { + match cal_local.get_item_by_url_mut(&url_add).await { None => { - progress.error(&format!("Inconsistency: created item {} has been marked for upload but is locally missing", id_add)); + progress.error(&format!("Inconsistency: created item {} has been marked for upload but is locally missing", url_add)); continue; }, Some(item) => { match cal_remote.add_item(item.clone()).await { - Err(err) => progress.error(&format!("Unable to add item {} to remote calendar: {}", id_add, err)), + Err(err) => progress.error(&format!("Unable to add item {} to remote calendar: {}", url_add, err)), Ok(new_ss) => { // Update local sync status item.set_sync_status(new_ss); @@ -374,20 +373,20 @@ where }; } - for id_change in local_changes { - progress.debug(&format!("> Pushing local change {} to the server", id_change)); + for url_change in local_changes { + progress.debug(&format!("> Pushing local change {} to the server", url_change)); progress.feedback(SyncEvent::InProgress{ calendar: cal_name.clone(), - details: Self::item_name(&cal_local, &id_change).await, + details: Self::item_name(&cal_local, &url_change).await, }); - match cal_local.get_item_by_id_mut(&id_change).await { + match cal_local.get_item_by_url_mut(&url_change).await { None => { - progress.error(&format!("Inconsistency: modified item {} has been marked for upload but is locally missing", id_change)); + progress.error(&format!("Inconsistency: modified item {} has been marked for upload but is locally missing", url_change)); continue; }, Some(item) => { match cal_remote.update_item(item.clone()).await { - Err(err) => progress.error(&format!("Unable to update item {} in remote calendar: {}", id_change, err)), + Err(err) => progress.error(&format!("Unable to update item {} in remote calendar: {}", url_change, err)), Ok(new_ss) => { // Update local sync status item.set_sync_status(new_ss); @@ -401,14 +400,14 @@ where } - async fn item_name(cal: &T, id: &Url) -> String { - cal.get_item_by_id(id).await.map(|item| item.name()).unwrap_or_default().to_string() + async fn item_name(cal: &T, url: &Url) -> String { + cal.get_item_by_url(url).await.map(|item| item.name()).unwrap_or_default().to_string() } } -async fn get_or_insert_counterpart_calendar(haystack_descr: &str, haystack: &mut H, cal_id: &CalendarId, needle: Arc>) +async fn get_or_insert_counterpart_calendar(haystack_descr: &str, haystack: &mut H, cal_url: &Url, needle: Arc>) -> Result>, Box> where H: CalDavSource, @@ -416,18 +415,18 @@ where N: BaseCalendar, { loop { - if let Some(cal) = haystack.get_calendar(&cal_id).await { + if let Some(cal) = haystack.get_calendar(&cal_url).await { break Ok(cal); } // This calendar does not exist locally yet, let's add it - log::debug!("Adding a {} calendar {}", haystack_descr, cal_id); + log::debug!("Adding a {} calendar {}", haystack_descr, cal_url); let src = needle.lock().unwrap(); let name = src.name().to_string(); let supported_comps = src.supported_components(); let color = src.color(); if let Err(err) = haystack.create_calendar( - cal_id.clone(), + cal_url.clone(), name, supported_comps, color.cloned(), diff --git a/src/task.rs b/src/task.rs index 4da9d93..2545abb 100644 --- a/src/task.rs +++ b/src/task.rs @@ -7,7 +7,6 @@ use ical::property::Property; use url::Url; use crate::item::SyncStatus; -use crate::calendar::CalendarId; use crate::utils::random_url; /// RFC5545 defines the completion as several optional fields, yet some combinations make no sense. @@ -67,7 +66,7 @@ pub struct Task { impl Task { /// Create a brand new Task that is not on a server yet. /// This will pick a new (random) task ID. - pub fn new(name: String, completed: bool, parent_calendar_url: &CalendarId) -> Self { + pub fn new(name: String, completed: bool, parent_calendar_url: &Url) -> Self { let new_url = random_url(parent_calendar_url); let new_sync_status = SyncStatus::NotSynced; let new_uid = Uuid::new_v4().to_hyphenated().to_string(); diff --git a/src/traits.rs b/src/traits.rs index 66c1b43..e6d5f28 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -11,7 +11,6 @@ use url::Url; use crate::item::SyncStatus; use crate::item::Item; use crate::item::VersionTag; -use crate::calendar::CalendarId; use crate::calendar::SupportedComponents; use crate::resource::Resource; @@ -22,11 +21,11 @@ use crate::resource::Resource; pub trait CalDavSource { /// Returns the current calendars that this source contains /// This function may trigger an update (that can be a long process, or that can even fail, e.g. in case of a remote server) - async fn get_calendars(&self) -> Result>>, Box>; - /// Returns the calendar matching the ID - async fn get_calendar(&self, id: &CalendarId) -> Option>>; + async fn get_calendars(&self) -> Result>>, Box>; + /// Returns the calendar matching the URL + async fn get_calendar(&self, url: &Url) -> Option>>; /// Create a calendar if it did not exist, and return it - async fn create_calendar(&mut self, id: CalendarId, name: String, supported_components: SupportedComponents, color: Option) + async fn create_calendar(&mut self, url: Url, name: String, supported_components: SupportedComponents, color: Option) -> Result>, Box>; // Removing a calendar is not supported yet @@ -78,20 +77,20 @@ pub trait DavCalendar : BaseCalendar { /// Create a new calendar fn new(name: String, resource: Resource, supported_components: SupportedComponents, color: Option) -> Self; - /// Get the IDs and the version tags of every item in this calendar + /// Get the URLs and the version tags of every item in this calendar async fn get_item_version_tags(&self) -> Result, Box>; /// Returns a particular item - async fn get_item_by_id(&self, id: &Url) -> Result, Box>; + async fn get_item_by_url(&self, url: &Url) -> Result, Box>; /// Delete an item - async fn delete_item(&mut self, item_id: &Url) -> Result<(), Box>; + async fn delete_item(&mut self, item_url: &Url) -> Result<(), Box>; - /// Get the IDs of all current items in this calendar - async fn get_item_ids(&self) -> Result, Box> { + /// Get the URLs of all current items in this calendar + async fn get_item_urls(&self) -> Result, Box> { let items = self.get_item_version_tags().await?; Ok(items.iter() - .map(|(id, _tag)| id.clone()) + .map(|(url, _tag)| url.clone()) .collect()) } @@ -108,19 +107,19 @@ pub trait DavCalendar : BaseCalendar { #[async_trait] pub trait CompleteCalendar : BaseCalendar { /// Create a new calendar - fn new(name: String, id: CalendarId, supported_components: SupportedComponents, color: Option) -> Self; + fn new(name: String, url: Url, supported_components: SupportedComponents, color: Option) -> Self; - /// Get the IDs of all current items in this calendar - async fn get_item_ids(&self) -> Result, Box>; + /// Get the URLs of all current items in this calendar + async fn get_item_urls(&self) -> Result, Box>; /// Returns all items that this calendar contains async fn get_items(&self) -> Result, Box>; /// Returns a particular item - async fn get_item_by_id<'a>(&'a self, id: &Url) -> Option<&'a Item>; + async fn get_item_by_url<'a>(&'a self, url: &Url) -> Option<&'a Item>; /// Returns a particular item - async fn get_item_by_id_mut<'a>(&'a mut self, id: &Url) -> Option<&'a mut Item>; + async fn get_item_by_url_mut<'a>(&'a mut self, url: &Url) -> Option<&'a mut Item>; /// Mark an item for deletion. /// This is required so that the upcoming sync will know it should also also delete this task from the server diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 68f1c69..8829265 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -10,7 +10,6 @@ use url::Url; use crate::traits::CompleteCalendar; use crate::traits::DavCalendar; -use crate::calendar::CalendarId; use crate::Item; use crate::item::SyncStatus; @@ -63,12 +62,12 @@ pub fn print_xml(element: &Element) { } /// A debug utility that pretty-prints calendars -pub async fn print_calendar_list(cals: &HashMap>>) +pub async fn print_calendar_list(cals: &HashMap>>) where C: CompleteCalendar, { - for (id, cal) in cals { - println!("CAL {} ({})", cal.lock().unwrap().name(), id); + for (url, cal) in cals { + println!("CAL {} ({})", cal.lock().unwrap().name(), url); match cal.lock().unwrap().get_items().await { Err(_err) => continue, Ok(map) => { @@ -81,17 +80,17 @@ where } /// A debug utility that pretty-prints calendars -pub async fn print_dav_calendar_list(cals: &HashMap>>) +pub async fn print_dav_calendar_list(cals: &HashMap>>) where C: DavCalendar, { - for (id, cal) in cals { - println!("CAL {} ({})", cal.lock().unwrap().name(), id); + for (url, cal) in cals { + println!("CAL {} ({})", cal.lock().unwrap().name(), url); match cal.lock().unwrap().get_item_version_tags().await { Err(_err) => continue, Ok(map) => { - for (id, version_tag) in map { - println!(" * {} (version {:?})", id, version_tag); + for (url, version_tag) in map { + println!(" * {} (version {:?})", url, version_tag); } }, } diff --git a/tests/scenarii.rs b/tests/scenarii.rs index 8987c8b..231af2a 100644 --- a/tests/scenarii.rs +++ b/tests/scenarii.rs @@ -15,7 +15,6 @@ use url::Url; use chrono::Utc; -use kitchen_fridge::calendar::CalendarId; use kitchen_fridge::calendar::SupportedComponents; use kitchen_fridge::traits::CalDavSource; use kitchen_fridge::traits::BaseCalendar; @@ -45,7 +44,7 @@ pub enum LocatedState { pub struct ItemState { // TODO: if/when this crate supports Events as well, we could add such events here /// The calendar it is in - calendar: CalendarId, + calendar: Url, /// Its name name: String, /// Its completion status @@ -55,10 +54,10 @@ pub struct ItemState { pub enum ChangeToApply { Rename(String), SetCompletion(bool), - Create(CalendarId, Item), + Create(Url, Item), /// "remove" means "mark for deletion" in the local calendar, or "immediately delete" on the remote calendar Remove, - // ChangeCalendar(CalendarId) is useless, as long as changing a calendar is implemented as "delete in one calendar and re-create it in another one" + // ChangeCalendar(Url) is useless, as long as changing a calendar is implemented as "delete in one calendar and re-create it in another one" } @@ -88,9 +87,9 @@ pub struct ItemScenario { pub fn scenarii_basic() -> Vec { let mut tasks = Vec::new(); - let first_cal = CalendarId::from("https://some.calend.ar/calendar-1/".parse().unwrap()); - let second_cal = CalendarId::from("https://some.calend.ar/calendar-2/".parse().unwrap()); - let third_cal = CalendarId::from("https://some.calend.ar/calendar-3/".parse().unwrap()); + let first_cal = Url::from("https://some.calend.ar/calendar-1/".parse().unwrap()); + let second_cal = Url::from("https://some.calend.ar/calendar-2/".parse().unwrap()); + let third_cal = Url::from("https://some.calend.ar/calendar-3/".parse().unwrap()); tasks.push( ItemScenario { @@ -419,8 +418,8 @@ pub fn scenarii_basic() -> Vec { pub fn scenarii_first_sync_to_local() -> Vec { let mut tasks = Vec::new(); - let cal1 = CalendarId::from("https://some.calend.ar/first/".parse().unwrap()); - let cal2 = CalendarId::from("https://some.calend.ar/second/".parse().unwrap()); + let cal1 = Url::from("https://some.calend.ar/first/".parse().unwrap()); + let cal2 = Url::from("https://some.calend.ar/second/".parse().unwrap()); tasks.push( ItemScenario { @@ -483,8 +482,8 @@ pub fn scenarii_first_sync_to_local() -> Vec { pub fn scenarii_first_sync_to_server() -> Vec { let mut tasks = Vec::new(); - let cal3 = CalendarId::from("https://some.calend.ar/third/".parse().unwrap()); - let cal4 = CalendarId::from("https://some.calend.ar/fourth/".parse().unwrap()); + let cal3 = Url::from("https://some.calend.ar/third/".parse().unwrap()); + let cal4 = Url::from("https://some.calend.ar/fourth/".parse().unwrap()); tasks.push( ItemScenario { @@ -548,7 +547,7 @@ pub fn scenarii_first_sync_to_server() -> Vec { pub fn scenarii_transient_task() -> Vec { let mut tasks = Vec::new(); - let cal = CalendarId::from("https://some.calend.ar/transient/".parse().unwrap()); + let cal = Url::from("https://some.calend.ar/transient/".parse().unwrap()); tasks.push( ItemScenario { @@ -668,37 +667,37 @@ async fn populate_test_provider(scenarii: &[ItemScenario], mock_behaviour: Arc, scenarii: &[ItemScenario]) { // Apply changes to each item for item in scenarii { - let initial_calendar_id = match &item.initial_state { + let initial_calendar_url = match &item.initial_state { LocatedState::None => None, LocatedState::Local(state) => Some(state.calendar.clone()), LocatedState::Remote(state) => Some(state.calendar.clone()), LocatedState::BothSynced(state) => Some(state.calendar.clone()), }; - let mut calendar_id = initial_calendar_id.clone(); + let mut calendar_url = initial_calendar_url.clone(); for local_change in &item.local_changes_to_apply { - calendar_id = Some(apply_change(provider.local(), calendar_id, &item.url, local_change, false).await); + calendar_url = Some(apply_change(provider.local(), calendar_url, &item.url, local_change, false).await); } - let mut calendar_id = initial_calendar_id; + let mut calendar_url = initial_calendar_url; for remote_change in &item.remote_changes_to_apply { - calendar_id = Some(apply_change(provider.remote(), calendar_id, &item.url, remote_change, true).await); + calendar_url = Some(apply_change(provider.remote(), calendar_url, &item.url, remote_change, true).await); } } } -async fn get_or_insert_calendar(source: &mut Cache, id: &CalendarId) +async fn get_or_insert_calendar(source: &mut Cache, url: &Url) -> Result>, Box> { - match source.get_calendar(id).await { + match source.get_calendar(url).await { Some(cal) => Ok(cal), None => { - let new_name = format!("Test calendar for ID {}", id); + let new_name = format!("Test calendar for URL {}", url); let supported_components = SupportedComponents::TODO; let color = csscolorparser::parse("#ff8000"); // TODO: we should rather have specific colors, depending on the calendars source.create_calendar( - id.clone(), + url.clone(), new_name.to_string(), supported_components, None, @@ -707,13 +706,13 @@ async fn get_or_insert_calendar(source: &mut Cache, id: &CalendarId) } } -/// Apply a single change on a given source, and returns the calendar ID that was modified -async fn apply_change(source: &S, calendar_id: Option, item_url: &Url, change: &ChangeToApply, is_remote: bool) -> CalendarId +/// Apply a single change on a given source, and returns the calendar URL that was modified +async fn apply_change(source: &S, calendar_url: Option, item_url: &Url, change: &ChangeToApply, is_remote: bool) -> Url where S: CalDavSource, C: CompleteCalendar + DavCalendar, // in this test, we're using a calendar that mocks both kinds { - match calendar_id { + match calendar_url { Some(cal) => { apply_changes_on_an_existing_item(source, &cal, item_url, change, is_remote).await; cal @@ -724,14 +723,14 @@ where } } -async fn apply_changes_on_an_existing_item(source: &S, calendar_id: &CalendarId, item_url: &Url, change: &ChangeToApply, is_remote: bool) +async fn apply_changes_on_an_existing_item(source: &S, calendar_url: &Url, item_url: &Url, change: &ChangeToApply, is_remote: bool) where S: CalDavSource, C: CompleteCalendar + DavCalendar, // in this test, we're using a calendar that mocks both kinds { - let cal = source.get_calendar(calendar_id).await.unwrap(); + let cal = source.get_calendar(calendar_url).await.unwrap(); let mut cal = cal.lock().unwrap(); - let task = cal.get_item_by_id_mut(item_url).await.unwrap().unwrap_task_mut(); + let task = cal.get_item_by_url_mut(item_url).await.unwrap().unwrap_task_mut(); match change { ChangeToApply::Rename(new_name) => { @@ -758,14 +757,14 @@ where true => cal.delete_item(item_url).await.unwrap(), }; }, - ChangeToApply::Create(_calendar_id, _item) => { + ChangeToApply::Create(_calendar_url, _item) => { panic!("This function only handles already existing items"); }, } } -/// Create an item, and returns the calendar ID it was inserted in -async fn create_test_item(source: &S, change: &ChangeToApply) -> CalendarId +/// Create an item, and returns the URL of the calendar it was inserted in +async fn create_test_item(source: &S, change: &ChangeToApply) -> Url where S: CalDavSource, C: CompleteCalendar + DavCalendar, // in this test, we're using a calendar that mocks both kinds @@ -776,10 +775,10 @@ where ChangeToApply::Remove => { panic!("This function only creates items that do not exist yet"); } - ChangeToApply::Create(calendar_id, item) => { - let cal = source.get_calendar(calendar_id).await.unwrap(); + ChangeToApply::Create(calendar_url, item) => { + let cal = source.get_calendar(calendar_url).await.unwrap(); cal.lock().unwrap().add_item(item.clone()).await.unwrap(); - calendar_id.clone() + calendar_url.clone() }, } } diff --git a/tests/sync.rs b/tests/sync.rs index 59536d7..37e92ac 100644 --- a/tests/sync.rs +++ b/tests/sync.rs @@ -124,7 +124,7 @@ impl TestFlavour { Self { scenarii: scenarii::scenarii_basic(), mock_behaviour: Arc::new(Mutex::new(MockBehaviour{ - get_item_by_id_behaviour: (3,2), + get_item_by_url_behaviour: (3,2), ..MockBehaviour::default() })), } @@ -145,7 +145,7 @@ impl TestFlavour { scenarii: scenarii::scenarii_basic(), mock_behaviour: Arc::new(Mutex::new(MockBehaviour{ add_item_behaviour: (2,3), - get_item_by_id_behaviour: (1,4), + get_item_by_url_behaviour: (1,4), ..MockBehaviour::default() })), } @@ -183,7 +183,7 @@ impl TestFlavour { delete_item_behaviour: (1,1), create_calendar_behaviour: (1,4), get_item_version_tags_behaviour: (3,1), - get_item_by_id_behaviour: (0,41), + get_item_by_url_behaviour: (0,41), ..MockBehaviour::default() })), }