mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-04-27 14:57:41 +00:00
Clean up mess in sync partially
This commit is contained in:
parent
2d30d1b7f2
commit
cc44b85e25
1 changed files with 56 additions and 49 deletions
|
|
@ -34,55 +34,21 @@ def sync(storage_a, storage_b, status):
|
||||||
items_a = {} # items prefetched for copy
|
items_a = {} # items prefetched for copy
|
||||||
items_b = {} # {uid: (item, etag)}
|
items_b = {} # {uid: (item, etag)}
|
||||||
|
|
||||||
storages = {
|
actions, prefetch_from_a, prefetch_from_b = \
|
||||||
'a': [storage_a, items_a, list_a],
|
get_actions(list_a, list_b, status)
|
||||||
'b': [storage_b, items_b, list_b]
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_actions():
|
|
||||||
already_handled = set()
|
|
||||||
prefetch_from_a = []
|
|
||||||
prefetch_from_b = []
|
|
||||||
actions = [] # list(tuple(action, uid, source, dest))
|
|
||||||
for uid in itertools.chain(list_a, list_b, status):
|
|
||||||
if uid in already_handled:
|
|
||||||
continue
|
|
||||||
already_handled.add(uid)
|
|
||||||
if uid not in status:
|
|
||||||
if uid in list_a and uid in list_b: # missing status
|
|
||||||
# TODO: might need some kind of diffing too?
|
|
||||||
status[uid] = (list_a[uid], list_b[uid])
|
|
||||||
elif uid in list_a and uid not in list_b: # new item in a
|
|
||||||
prefetch_from_a.append(uid)
|
|
||||||
actions.append(('upload', uid, 'a', 'b'))
|
|
||||||
elif uid not in list_a and uid in list_b: # new item in b
|
|
||||||
prefetch_from_b.append(uid)
|
|
||||||
actions.append(('upload', uid, 'b', 'a'))
|
|
||||||
else:
|
|
||||||
if uid in list_a and uid in list_b:
|
|
||||||
if list_a[uid] != status[uid][0] and list_b[uid] != status[uid][1]:
|
|
||||||
1/0 # conflict resolution TODO
|
|
||||||
elif list_a[uid] != status[uid][0]: # item update in a
|
|
||||||
prefetch_from_a.append(uid)
|
|
||||||
actions.append(('update', uid, 'a', 'b'))
|
|
||||||
elif list_b[uid] != status[uid][1]: # item update in b
|
|
||||||
prefetch_from_b.append(uid)
|
|
||||||
actions.append(('update', uid, 'b', 'a'))
|
|
||||||
else: # completely in sync!
|
|
||||||
pass
|
|
||||||
elif uid in list_a and uid not in list_b: # deleted from b
|
|
||||||
actions.append(('delete', uid, 'b', 'a'))
|
|
||||||
elif uid not in list_a and uid in list_b: # deleted from a
|
|
||||||
actions.append(('delete', uid, 'a', 'b'))
|
|
||||||
elif uid not in list_a and uid not in list_b: # deleted from a and b
|
|
||||||
del status[uid]
|
|
||||||
return actions, prefetch_from_a, prefetch_from_b
|
|
||||||
actions, prefetch_from_a, prefetch_from_b = get_actions()
|
|
||||||
|
|
||||||
|
def prefetch():
|
||||||
for item, uid, etag in storage_a.get_multi(prefetch_from_a):
|
for item, uid, etag in storage_a.get_multi(prefetch_from_a):
|
||||||
items_a[uid] = (item, etag)
|
items_a[uid] = (item, etag)
|
||||||
for item, uid, etag in storage_b.get_multi(prefetch_from_b):
|
for item, uid, etag in storage_b.get_multi(prefetch_from_b):
|
||||||
items_b[uid] = (item, etag)
|
items_b[uid] = (item, etag)
|
||||||
|
prefetch()
|
||||||
|
|
||||||
|
storages = {
|
||||||
|
'a': (storage_a, items_a, list_a),
|
||||||
|
'b': (storage_b, items_b, list_b),
|
||||||
|
None: (None, None, None)
|
||||||
|
}
|
||||||
|
|
||||||
for action, uid, source, dest in actions:
|
for action, uid, source, dest in actions:
|
||||||
source_storage, source_items, source_list = storages[source]
|
source_storage, source_items, source_list = storages[source]
|
||||||
|
|
@ -96,5 +62,46 @@ def sync(storage_a, storage_b, status):
|
||||||
dest_etag = dest_storage.update(item, dest_list[uid])
|
dest_etag = dest_storage.update(item, dest_list[uid])
|
||||||
status[uid] = (source_etag, dest_etag) if source == 'a' else (dest_etag, source_etag)
|
status[uid] = (source_etag, dest_etag) if source == 'a' else (dest_etag, source_etag)
|
||||||
elif action == 'delete':
|
elif action == 'delete':
|
||||||
|
if dest is not None:
|
||||||
dest_storage.delete(uid, dest_list[uid])
|
dest_storage.delete(uid, dest_list[uid])
|
||||||
del status[uid]
|
del status[uid]
|
||||||
|
|
||||||
|
def get_actions(list_a, list_b, status):
|
||||||
|
already_handled = set()
|
||||||
|
prefetch_from_a = []
|
||||||
|
prefetch_from_b = []
|
||||||
|
actions = []
|
||||||
|
for uid in itertools.chain(list_a, list_b, status):
|
||||||
|
if uid in already_handled:
|
||||||
|
continue
|
||||||
|
already_handled.add(uid)
|
||||||
|
if uid not in status:
|
||||||
|
if uid in list_a and uid in list_b: # missing status
|
||||||
|
# TODO: might need some kind of diffing too?
|
||||||
|
status[uid] = (list_a[uid], list_b[uid])
|
||||||
|
elif uid in list_a and uid not in list_b: # new item was created in a
|
||||||
|
prefetch_from_a.append(uid)
|
||||||
|
actions.append(('upload', uid, 'a', 'b'))
|
||||||
|
elif uid not in list_a and uid in list_b: # new item was created in b
|
||||||
|
prefetch_from_b.append(uid)
|
||||||
|
actions.append(('upload', uid, 'b', 'a'))
|
||||||
|
else:
|
||||||
|
if uid in list_a and uid in list_b:
|
||||||
|
if list_a[uid] != status[uid][0] and list_b[uid] != status[uid][1]:
|
||||||
|
1/0 # conflict resolution TODO
|
||||||
|
elif list_a[uid] != status[uid][0]: # item was updated in a
|
||||||
|
prefetch_from_a.append(uid)
|
||||||
|
actions.append(('update', uid, 'a', 'b'))
|
||||||
|
elif list_b[uid] != status[uid][1]: # item was updated in b
|
||||||
|
prefetch_from_b.append(uid)
|
||||||
|
actions.append(('update', uid, 'b', 'a'))
|
||||||
|
else: # completely in sync!
|
||||||
|
pass
|
||||||
|
elif uid in list_a and uid not in list_b: # was deleted from b
|
||||||
|
actions.append(('delete', uid, None, 'a'))
|
||||||
|
elif uid not in list_a and uid in list_b: # was deleted from a
|
||||||
|
actions.append(('delete', uid, None, 'b'))
|
||||||
|
elif uid not in list_a and uid not in list_b: # was deleted from a and b
|
||||||
|
actions.append(('delete', uid, None, None))
|
||||||
|
del status[uid]
|
||||||
|
return actions, prefetch_from_a, prefetch_from_b
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue