~whynothugo/vdirsyncer-rs

8d5d09b87d439b944090c892f9c6a9f9b69cac92 — Hugo Osvaldo Barrera 2 months ago 80f264a
Drop support for item properties

This is not required for my primary use case. Implementing properties
for items would add substantial complexity that is not required. Emails
are immutable, so re-using the same sync algorithm for them won't be a
good fit.
M vstorage/src/base.rs => vstorage/src/base.rs +1 -4
@@ 60,9 60,7 @@ pub trait Storage<I: Item>: Sync + Send {
    /// A collection must be empty for deletion to succeed.
    async fn destroy_collection(&self, href: &str) -> Result<()>;

    /// List collection properties.
    ///
    /// List all properties of a collection and (if applicable) of its items.
    /// List all properties of a collection.
    async fn list_properties(
        &self,
        collection_href: &str,


@@ 609,7 607,6 @@ pub struct FetchedItem<I: Item> {
}

pub struct ListedProperty<P: Property> {
    pub resource: Href,
    pub property: P,
    pub value: String,
}

M vstorage/src/caldav.rs => vstorage/src/caldav.rs +0 -1
@@ 380,7 380,6 @@ where
            .zip(CalendarProperty::known_properties())
            .filter_map(|((_, v), p)| {
                v.map(|value| ListedProperty {
                    resource: collection_href.to_owned(),
                    property: p.clone(),
                    value,
                })

M vstorage/src/carddav.rs => vstorage/src/carddav.rs +0 -1
@@ 368,7 368,6 @@ where
            .zip(AddressBookProperty::known_properties())
            .filter_map(|((_, v), p)| {
                v.map(|value| ListedProperty {
                    resource: collection_href.to_owned(),
                    property: p.clone(),
                    value,
                })

M vstorage/src/lib.rs => vstorage/src/lib.rs +7 -12
@@ 9,8 9,8 @@
//! Implementation of a common API for reading and writing items on different underlying
//! storage implementations.
//!
//! Storages can contain `icalendar` components, `vcard` entries, or content types where items are
//! either immutable or have unique ids.
//! Storages can contain `icalendar` components, `vcard` entries, or other content types where
//! items are either immutable or have unique ids.
//!
//! # Storage
//!


@@ 30,9 30,6 @@
//!   item is a file.
//! - [`WebCal`]: An icalendar file loaded via HTTP(s). This storage is implicitly read-only.
//!
//! A potential `ImapStorage` could be implemented a single IMAP account, where each collection is
//! a mailbox and each item is an individual email message.
//!
//! The `Storage` type and the logic for synchronisation of storages is is agnostic to the content
//! type inside collections, and can synchronise collections with any type of content. When
//! synchronising two storages, items with the same UID on both sides are synchronised with each


@@ 73,14 70,12 @@
//!
//! ## Properties
//!
//! Storages expose properties. Property types vary depending on a Storage's items. E.g.: Calendars
//! have a `Colour`, `Description`, `DisplayName` and `Order`, whereas Address Books have
//! `DisplayName` and `Description`. In both of these examples, only collections have properties,
//! and items have no properties.
//! Storages expose properties for collections. Property types vary depending on a Storage's items,
//! although items themselves cannot have properties.
//!
//! Calendars have a `Colour`, `Description`, `DisplayName` and `Order`
//!
//! Synchronising Storages with custom `Item` types where items have properties is not yet
//! supported. This limitation means that an implementation trying to synchronise email will
//! synchronise messages but not their properties (e.g.: `Seen`, `Flagged`, etc).
//! Address Books have `DisplayName` and `Description`.
//!
//! ## Entity tags
//!

M vstorage/src/sync/plan.rs => vstorage/src/sync/plan.rs +0 -12
@@ 909,7 909,6 @@ impl<I: Item> PropertyPlan<I> {
            _ => Vec::new(),
        };

        // FIXME: assumes that no props belong to items.
        let all_props = props_a
            .iter()
            .chain(props_b.iter())


@@ 923,17 922,6 @@ impl<I: Item> PropertyPlan<I> {
            let b = props_b.iter().find(|p| p.property == *property);
            let state = props_status.iter().find(|p| p.property == property.name());

            if let Some(a) = a {
                if *a.resource != mapping.a.href {
                    todo!("Synchronising item properties is not implemented");
                }
            }
            if let Some(b) = b {
                if *b.resource != mapping.b.href {
                    todo!("Synchronising item properties is not implemented");
                }
            }

            let action = match (a, b, state) {
                (None, None, None) => None,
                (None, None, Some(_)) => Some(PropertyAction::ClearStatus),

M vstorage/src/sync/status.rs => vstorage/src/sync/status.rs +1 -7
@@ 79,10 79,6 @@ pub(super) struct StatusForItem {
}

pub(super) struct PropertyStatus {
    #[allow(dead_code)] // TODO: will be required for item properties
    pub(super) href_a: String,
    #[allow(dead_code)] // TODO: will be required for item properties
    pub(super) href_b: String,
    // The name of the property
    pub(super) property: String,
    pub(super) value: String,


@@ 416,7 412,7 @@ impl StatusDatabase {
        mapping_uid: &MappingUid,
    ) -> Result<Vec<PropertyStatus>, StatusError> {
        let query = concat!(
            "SELECT href_a, href_b, property, value",
            "SELECT property, value",
            " FROM properties",
            " WHERE mapping_uid = :mapping_uid"
        );


@@ 426,8 422,6 @@ impl StatusDatabase {
        let mut results = Vec::new();
        while let Ok(State::Row) = statement.next() {
            results.push(PropertyStatus {
                href_a: statement.read::<String, _>("href_a")?,
                href_b: statement.read::<String, _>("href_b")?,
                property: statement.read::<String, _>("property")?,
                value: statement.read::<String, _>("value")?,
            });

M vstorage/src/vdir.rs => vstorage/src/vdir.rs +0 -1
@@ 275,7 275,6 @@ where
            let prop_value = self.get_property(collection_href, property.clone()).await?;
            if let Some(value) = prop_value {
                props.push(ListedProperty {
                    resource: collection_href.to_owned(),
                    property: property.clone(),
                    value,
                });