vdirsyncer/vdirsyncer/metasync.py
2016-10-04 18:46:57 +02:00

63 lines
1.7 KiB
Python

import logging
from . import exceptions
from .storage.base import normalize_meta_value
logger = logging.getLogger(__name__)
class MetaSyncError(exceptions.Error):
pass
class MetaSyncConflict(MetaSyncError):
key = None
def metasync(storage_a, storage_b, status, keys, conflict_resolution=None):
def _a_to_b():
logger.info(u'Copying {} to {}'.format(key, storage_b))
storage_b.set_meta(key, a)
status[key] = a
def _b_to_a():
logger.info(u'Copying {} to {}'.format(key, storage_a))
storage_a.set_meta(key, b)
status[key] = b
def _resolve_conflict():
if a == b:
status[key] = a
elif conflict_resolution == 'a wins':
_a_to_b()
elif conflict_resolution == 'b wins':
_b_to_a()
else:
if callable(conflict_resolution):
logger.warning('Custom commands don\'t work on metasync.')
elif conflict_resolution is not None:
raise exceptions.UserError(
'Invalid conflict resolution setting.'
)
raise MetaSyncConflict(key)
for key in keys:
a = storage_a.get_meta(key)
b = storage_b.get_meta(key)
s = normalize_meta_value(status.get(key))
logger.debug(u'Key: {}'.format(key))
logger.debug(u'A: {}'.format(a))
logger.debug(u'B: {}'.format(b))
logger.debug(u'S: {}'.format(s))
if a != s and b != s:
_resolve_conflict()
elif a != s and b == s:
_a_to_b()
elif a == s and b != s:
_b_to_a()
else:
assert a == b
for key in set(status) - set(keys):
del status[key]