diff --git a/vdirsyncer/http.py b/vdirsyncer/http.py index 30cfe909..3a158862 100644 --- a/vdirsyncer/http.py +++ b/vdirsyncer/http.py @@ -147,7 +147,12 @@ async def request( logger.debug(response.status) logger.debug(response.headers) - logger.debug(response.content) + if ( + response.status >= 400 + and hasattr(response, "content") + and hasattr(response.content, "_buffer") + ): + logger.debug(response.content._buffer) if response.status == 412: raise exceptions.PreconditionFailed(response.reason) diff --git a/vdirsyncer/storage/dav.py b/vdirsyncer/storage/dav.py index dcaf15e9..9726b10f 100644 --- a/vdirsyncer/storage/dav.py +++ b/vdirsyncer/storage/dav.py @@ -553,7 +553,7 @@ async def get_multi(self, hrefs): else: rv.append((href, Item(raw), etag)) for href in hrefs_left: - raise exceptions.NotFoundError(href) + dav_logger.warning(f"Skipping {href}, not found") for href, item, etag in rv: yield href, item, etag @@ -593,12 +593,52 @@ async def _put(self, href, item, etag): async def update(self, href, item, etag): if etag is None: raise ValueError("etag must be given and must not be None.") - href, etag = await self._put(self._normalize_href(href), item, etag) + try: + href, etag = await self._put(self._normalize_href(href), item, etag) + except aiohttp.ClientResponseError as e: + if e.status == 409: + dav_logger.debug("Conflict, will delete old event and recreate it.") + try: + await self.delete(self._normalize_href(href), None) + dav_logger.debug("Now trying again") + rv = await self._put(self._normalize_href(href), item, None) + except aiohttp.ClientResponseError as delerr: + dav_logger.debug(f"delerr.status = {delerr.status}") + if delerr.status == 403 or delerr.status == 404: + dav_logger.warning("Old event not found, ignoring") + rv = None, None + else: + raise + elif e.status == 403: + dav_logger.debug("Google Calendar refusing update, ignore") + rv = None, None + else: + raise return etag async def upload(self, item: Item): href = self._get_href(item) - rv = await self._put(href, item, None) + try: + rv = await self._put(href, item, None) + except aiohttp.ClientResponseError as e: + if e.status == 409: + dav_logger.debug("Conflict, will delete old event and recreate it.") + try: + await self.delete(href, None) + dav_logger.debug("Now trying again") + rv = await self._put(href, item, None) + except aiohttp.ClientResponseError as delerr: + dav_logger.debug(f"delerr.status = {delerr.status}") + if delerr.status == 403 or delerr.status == 404: + dav_logger.warning("Old event not found, ignoring") + rv = None, None + else: + raise + elif e.status == 403: + dav_logger.debug("Google Calendar refusing update, ignore") + rv = None, None + else: + raise return rv async def delete(self, href, etag): @@ -633,6 +673,7 @@ def _parse_prop_responses(self, root, handled_hrefs=None): props = response.findall("{DAV:}propstat/{DAV:}prop") if props is None or not len(props): dav_logger.debug(f"Skipping {href!r}, properties are missing.") + dav_logger.debug(f"Response for {href!r}: {etree.tostring(response)}") continue else: props = _merge_xml(props) diff --git a/vdirsyncer/sync/__init__.py b/vdirsyncer/sync/__init__.py index 8678bc9a..6e489dae 100644 --- a/vdirsyncer/sync/__init__.py +++ b/vdirsyncer/sync/__init__.py @@ -208,7 +208,6 @@ async def _run_impl(self, a, b): ) ) href, etag = await self.dest.storage.upload(self.item) - assert href is not None self.dest.status.insert_ident( self.ident, ItemMetadata(href=href, hash=self.item.hash, etag=etag)