mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-03-25 08:55:50 +00:00
Add asyncio to the storage backends and most of the codebase. A lot of it merely uses asyncio APIs, but still doesn't actually run several things concurrently internally. Further improvements will be added on top of these changes Thanks to Thomas Grainger (@graingert) for a few useful pointers related to asyncio.
67 lines
2 KiB
Python
67 lines
2 KiB
Python
import logging
|
|
from os.path import basename
|
|
|
|
import aiostream
|
|
|
|
from .utils import generate_href
|
|
from .utils import href_safe
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class IrreparableItem(Exception):
|
|
pass
|
|
|
|
|
|
async def repair_storage(storage, repair_unsafe_uid):
|
|
seen_uids = set()
|
|
all_hrefs = await aiostream.stream.list(storage.list())
|
|
for i, (href, _) in enumerate(all_hrefs):
|
|
item, etag = await storage.get(href)
|
|
logger.info("[{}/{}] Processing {}".format(i, len(all_hrefs), href))
|
|
|
|
try:
|
|
new_item = repair_item(href, item, seen_uids, repair_unsafe_uid)
|
|
except IrreparableItem:
|
|
logger.error(
|
|
"Item {!r} is malformed beyond repair. "
|
|
"The PRODID property may indicate which software "
|
|
"created this item.".format(href)
|
|
)
|
|
logger.error(f"Item content: {item.raw!r}")
|
|
continue
|
|
|
|
seen_uids.add(new_item.uid)
|
|
if new_item.raw != item.raw:
|
|
if new_item.uid != item.uid:
|
|
await storage.upload(new_item)
|
|
await storage.delete(href, etag)
|
|
else:
|
|
await storage.update(href, new_item, etag)
|
|
|
|
|
|
def repair_item(href, item, seen_uids, repair_unsafe_uid):
|
|
if item.parsed is None:
|
|
raise IrreparableItem()
|
|
|
|
new_item = item
|
|
|
|
if not item.uid:
|
|
logger.warning("No UID, assigning random UID.")
|
|
new_item = item.with_uid(generate_href())
|
|
elif item.uid in seen_uids:
|
|
logger.warning("Duplicate UID, assigning random UID.")
|
|
new_item = item.with_uid(generate_href())
|
|
elif not href_safe(item.uid) or not href_safe(basename(href)):
|
|
if not repair_unsafe_uid:
|
|
logger.warning(
|
|
"UID may cause problems, add " "--repair-unsafe-uid to repair."
|
|
)
|
|
else:
|
|
logger.warning("UID or href is unsafe, assigning random UID.")
|
|
new_item = item.with_uid(generate_href())
|
|
|
|
if not new_item.uid:
|
|
raise IrreparableItem()
|
|
|
|
return new_item
|