mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-04-27 14:57:41 +00:00
Fix bug with sync only using get
This commit is contained in:
parent
be2f0851f3
commit
afbbafdb69
1 changed files with 21 additions and 37 deletions
|
|
@ -22,27 +22,23 @@ import vdirsyncer.log
|
||||||
sync_logger = vdirsyncer.log.get('sync')
|
sync_logger = vdirsyncer.log.get('sync')
|
||||||
|
|
||||||
|
|
||||||
def prepare_list(storage, href_to_uid):
|
def prepare_list(storage, href_to_status):
|
||||||
|
download = []
|
||||||
for href, etag in storage.list():
|
for href, etag in storage.list():
|
||||||
props = {'etag': etag}
|
props = {'etag': etag}
|
||||||
if href in href_to_uid:
|
if href in href_to_status:
|
||||||
props['uid'] = href_to_uid[href]
|
uid, old_etag = href_to_status[href]
|
||||||
|
props['uid'] = uid
|
||||||
|
if etag != old_etag:
|
||||||
|
download.append(href)
|
||||||
else:
|
else:
|
||||||
item, new_etag = storage.get(href)
|
download.append(href)
|
||||||
assert etag == new_etag
|
|
||||||
props['uid'] = item.uid
|
|
||||||
props['item'] = item
|
|
||||||
yield href, props
|
yield href, props
|
||||||
|
|
||||||
|
if download:
|
||||||
def prefetch(storage, item_list, hrefs):
|
for href, item, etag in storage.get_multi(download):
|
||||||
hrefs_to_prefetch = []
|
props = {'item': item, 'uid': item.uid, 'etag': etag}
|
||||||
for href in hrefs:
|
yield href, props
|
||||||
if 'item' not in item_list[href]:
|
|
||||||
hrefs_to_prefetch.append(href)
|
|
||||||
for href, item, etag in storage.get_multi(hrefs_to_prefetch):
|
|
||||||
assert item_list[href]['etag'] == etag
|
|
||||||
item_list[href]['item'] = item
|
|
||||||
|
|
||||||
|
|
||||||
def sync(storage_a, storage_b, status, conflict_resolution=None):
|
def sync(storage_a, storage_b, status, conflict_resolution=None):
|
||||||
|
|
@ -60,32 +56,28 @@ def sync(storage_a, storage_b, status, conflict_resolution=None):
|
||||||
provided, the sync function will raise
|
provided, the sync function will raise
|
||||||
:py:exc:`vdirsyncer.exceptions.SyncConflict`.
|
:py:exc:`vdirsyncer.exceptions.SyncConflict`.
|
||||||
'''
|
'''
|
||||||
a_href_to_uid = dict(
|
a_href_to_status = dict(
|
||||||
(href_a, uid)
|
(href_a, (uid, etag_a))
|
||||||
for uid, (href_a, etag_a, href_b, etag_b) in status.iteritems()
|
for uid, (href_a, etag_a, href_b, etag_b) in status.iteritems()
|
||||||
)
|
)
|
||||||
b_href_to_uid = dict(
|
b_href_to_status = dict(
|
||||||
(href_b, uid)
|
(href_b, (uid, etag_b))
|
||||||
for uid, (href_a, etag_a, href_b, etag_b) in status.iteritems()
|
for uid, (href_a, etag_a, href_b, etag_b) in status.iteritems()
|
||||||
)
|
)
|
||||||
# href => {'etag': etag, 'item': optional item, 'uid': uid}
|
# href => {'etag': etag, 'item': optional item, 'uid': uid}
|
||||||
list_a = dict(prepare_list(storage_a, a_href_to_uid))
|
list_a = dict(prepare_list(storage_a, a_href_to_status))
|
||||||
list_b = dict(prepare_list(storage_b, b_href_to_uid))
|
list_b = dict(prepare_list(storage_b, b_href_to_status))
|
||||||
|
|
||||||
a_uid_to_href = dict((x['uid'], href) for href, x in list_a.iteritems())
|
a_uid_to_href = dict((x['uid'], href) for href, x in list_a.iteritems())
|
||||||
b_uid_to_href = dict((x['uid'], href) for href, x in list_b.iteritems())
|
b_uid_to_href = dict((x['uid'], href) for href, x in list_b.iteritems())
|
||||||
del a_href_to_uid, b_href_to_uid
|
del a_href_to_status, b_href_to_status
|
||||||
|
|
||||||
storages = {
|
storages = {
|
||||||
'a': (storage_a, list_a, a_uid_to_href),
|
'a': (storage_a, list_a, a_uid_to_href),
|
||||||
'b': (storage_b, list_b, b_uid_to_href)
|
'b': (storage_b, list_b, b_uid_to_href)
|
||||||
}
|
}
|
||||||
|
|
||||||
actions, prefetch_from_a, prefetch_from_b = \
|
actions = get_actions(storages, status)
|
||||||
get_actions(storages, status)
|
|
||||||
|
|
||||||
prefetch(storage_a, list_a, prefetch_from_a)
|
|
||||||
prefetch(storage_b, list_b, prefetch_from_b)
|
|
||||||
|
|
||||||
for action in actions:
|
for action in actions:
|
||||||
action(storages, status, conflict_resolution)
|
action(storages, status, conflict_resolution)
|
||||||
|
|
@ -180,8 +172,6 @@ def action_conflict_resolve(uid):
|
||||||
|
|
||||||
|
|
||||||
def get_actions(storages, status):
|
def get_actions(storages, status):
|
||||||
prefetch_from_a = []
|
|
||||||
prefetch_from_b = []
|
|
||||||
actions = []
|
actions = []
|
||||||
|
|
||||||
storage_a, list_a, a_uid_to_href = storages['a']
|
storage_a, list_a, a_uid_to_href = storages['a']
|
||||||
|
|
@ -203,23 +193,17 @@ def get_actions(storages, status):
|
||||||
if a and b: # missing status
|
if a and b: # missing status
|
||||||
actions.append(action_conflict_resolve(uid))
|
actions.append(action_conflict_resolve(uid))
|
||||||
elif a and not b: # new item was created in a
|
elif a and not b: # new item was created in a
|
||||||
prefetch_from_a.append(href_a)
|
|
||||||
actions.append(action_upload(uid, 'a', 'b'))
|
actions.append(action_upload(uid, 'a', 'b'))
|
||||||
elif not a and b: # new item was created in b
|
elif not a and b: # new item was created in b
|
||||||
prefetch_from_b.append(href_b)
|
|
||||||
actions.append(action_upload(uid, 'b', 'a'))
|
actions.append(action_upload(uid, 'b', 'a'))
|
||||||
else:
|
else:
|
||||||
_, status_etag_a, _, status_etag_b = status[uid]
|
_, status_etag_a, _, status_etag_b = status[uid]
|
||||||
if a and b:
|
if a and b:
|
||||||
if a['etag'] != status_etag_a and b['etag'] != status_etag_b:
|
if a['etag'] != status_etag_a and b['etag'] != status_etag_b:
|
||||||
prefetch_from_a.append(href_a)
|
|
||||||
prefetch_from_b.append(href_b)
|
|
||||||
actions.append(action_conflict_resolve(uid))
|
actions.append(action_conflict_resolve(uid))
|
||||||
elif a['etag'] != status_etag_a: # item was updated in a
|
elif a['etag'] != status_etag_a: # item was updated in a
|
||||||
prefetch_from_a.append(href_a)
|
|
||||||
actions.append(action_update(uid, 'a', 'b'))
|
actions.append(action_update(uid, 'a', 'b'))
|
||||||
elif b['etag'] != status_etag_b: # item was updated in b
|
elif b['etag'] != status_etag_b: # item was updated in b
|
||||||
prefetch_from_b.append(href_b)
|
|
||||||
actions.append(action_update(uid, 'b', 'a'))
|
actions.append(action_update(uid, 'b', 'a'))
|
||||||
elif a and not b: # was deleted from b
|
elif a and not b: # was deleted from b
|
||||||
actions.append(action_delete(uid, 'a'))
|
actions.append(action_delete(uid, 'a'))
|
||||||
|
|
@ -228,4 +212,4 @@ def get_actions(storages, status):
|
||||||
elif not a and not b: # was deleted from a and b
|
elif not a and not b: # was deleted from a and b
|
||||||
actions.append(action_delete(uid, None))
|
actions.append(action_delete(uid, None))
|
||||||
|
|
||||||
return actions, prefetch_from_a, prefetch_from_b
|
return actions
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue