calcurse-caldav: Compute diffs before synchronizing
Instead of computing the objects to push/pull on-demand, use a snapshot of the synchronization database taken before the synchronization process starts. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
parent
338e556f8d
commit
c8d3d87c84
@ -243,13 +243,10 @@ def push_object(conn, objhash):
|
|||||||
return (href, etag)
|
return (href, etag)
|
||||||
|
|
||||||
|
|
||||||
def push_objects(conn, syncdb, etagdict):
|
def push_objects(objhashes, conn, syncdb, etagdict):
|
||||||
objhashes = calcurse_hashset()
|
|
||||||
new = objhashes - set([entry[1] for entry in syncdb.values()])
|
|
||||||
|
|
||||||
# Copy new objects to the server.
|
# Copy new objects to the server.
|
||||||
added = 0
|
added = 0
|
||||||
for objhash in new:
|
for objhash in objhashes:
|
||||||
if verbose:
|
if verbose:
|
||||||
print("Pushing new object {} to the server.".format(objhash))
|
print("Pushing new object {} to the server.".format(objhash))
|
||||||
if dry_run:
|
if dry_run:
|
||||||
@ -267,13 +264,10 @@ def remove_remote_object(conn, etag, href):
|
|||||||
remote_query(conn, "DELETE", href, headers, None)
|
remote_query(conn, "DELETE", href, headers, None)
|
||||||
|
|
||||||
|
|
||||||
def remove_remote_objects(conn, syncdb, etagdict):
|
def remove_remote_objects(objhashes, conn, syncdb, etagdict):
|
||||||
objhashes = calcurse_hashset()
|
|
||||||
gone = set([entry[1] for entry in syncdb.values()]) - objhashes
|
|
||||||
|
|
||||||
# Remove locally deleted objects from the server.
|
# Remove locally deleted objects from the server.
|
||||||
deleted = 0
|
deleted = 0
|
||||||
for objhash in gone:
|
for objhash in objhashes:
|
||||||
queue = []
|
queue = []
|
||||||
for href, entry in syncdb.items():
|
for href, entry in syncdb.items():
|
||||||
if entry[1] == objhash:
|
if entry[1] == objhash:
|
||||||
@ -302,16 +296,8 @@ def remove_remote_objects(conn, syncdb, etagdict):
|
|||||||
return deleted
|
return deleted
|
||||||
|
|
||||||
|
|
||||||
def pull_objects(conn, syncdb, etagdict):
|
def pull_objects(hrefs_missing, hrefs_modified, conn, syncdb, etagdict):
|
||||||
missing = set()
|
if not hrefs_missing and not hrefs_modified:
|
||||||
modified = set()
|
|
||||||
for href in set(etagdict.keys()):
|
|
||||||
if href not in syncdb:
|
|
||||||
missing.add(href)
|
|
||||||
elif etagdict[href] != syncdb[href][0]:
|
|
||||||
modified.add(href)
|
|
||||||
|
|
||||||
if not missing and not modified:
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Download and import new objects from the server.
|
# Download and import new objects from the server.
|
||||||
@ -319,7 +305,7 @@ def pull_objects(conn, syncdb, etagdict):
|
|||||||
'<C:calendar-multiget xmlns:D="DAV:" '
|
'<C:calendar-multiget xmlns:D="DAV:" '
|
||||||
' xmlns:C="urn:ietf:params:xml:ns:caldav">'
|
' xmlns:C="urn:ietf:params:xml:ns:caldav">'
|
||||||
'<D:prop><D:getetag /><C:calendar-data /></D:prop>')
|
'<D:prop><D:getetag /><C:calendar-data /></D:prop>')
|
||||||
for href in (missing | modified):
|
for href in (hrefs_missing | hrefs_modified):
|
||||||
body += '<D:href>{}</D:href>'.format(href)
|
body += '<D:href>{}</D:href>'.format(href)
|
||||||
body += '</C:calendar-multiget>'
|
body += '</C:calendar-multiget>'
|
||||||
headers, body = remote_query(conn, "REPORT", path, {}, body)
|
headers, body = remote_query(conn, "REPORT", path, {}, body)
|
||||||
@ -345,7 +331,7 @@ def pull_objects(conn, syncdb, etagdict):
|
|||||||
die_atnode('Missing calendar data.', node)
|
die_atnode('Missing calendar data.', node)
|
||||||
cdata = cdatanode.text
|
cdata = cdatanode.text
|
||||||
|
|
||||||
if href in modified:
|
if href in hrefs_modified:
|
||||||
if verbose:
|
if verbose:
|
||||||
print("Replacing object {}.".format(etag))
|
print("Replacing object {}.".format(etag))
|
||||||
if dry_run:
|
if dry_run:
|
||||||
@ -365,12 +351,10 @@ def pull_objects(conn, syncdb, etagdict):
|
|||||||
return added
|
return added
|
||||||
|
|
||||||
|
|
||||||
def remove_local_objects(conn, syncdb, etagdict):
|
def remove_local_objects(hrefs, conn, syncdb, etagdict):
|
||||||
orphan = set(syncdb.keys()) - set(etagdict.keys())
|
|
||||||
|
|
||||||
# Delete objects that no longer exist on the server.
|
# Delete objects that no longer exist on the server.
|
||||||
deleted = 0
|
deleted = 0
|
||||||
for href in orphan:
|
for href in hrefs:
|
||||||
etag, objhash = syncdb[href]
|
etag, objhash = syncdb[href]
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
@ -545,17 +529,31 @@ try:
|
|||||||
# server.
|
# server.
|
||||||
etagdict = get_etags(conn)
|
etagdict = get_etags(conn)
|
||||||
|
|
||||||
# Retrieve new objects from the server
|
# Compute object diffs.
|
||||||
local_new = pull_objects(conn, syncdb, etagdict)
|
objhashes = calcurse_hashset()
|
||||||
|
new = objhashes - set([entry[1] for entry in syncdb.values()])
|
||||||
|
gone = set([entry[1] for entry in syncdb.values()]) - objhashes
|
||||||
|
|
||||||
|
missing = set()
|
||||||
|
modified = set()
|
||||||
|
for href in set(etagdict.keys()):
|
||||||
|
if href not in syncdb:
|
||||||
|
missing.add(href)
|
||||||
|
elif etagdict[href] != syncdb[href][0]:
|
||||||
|
modified.add(href)
|
||||||
|
orphan = set(syncdb.keys()) - set(etagdict.keys())
|
||||||
|
|
||||||
|
# Retrieve new objects from the server.
|
||||||
|
local_new = pull_objects(new, conn, syncdb, etagdict)
|
||||||
|
|
||||||
# Delete local items that no longer exist on the server.
|
# Delete local items that no longer exist on the server.
|
||||||
local_del = remove_local_objects(conn, syncdb, etagdict)
|
local_del = remove_local_objects(gone, conn, syncdb, etagdict)
|
||||||
|
|
||||||
# Push new objects to the server.
|
# Push new objects to the server.
|
||||||
remote_new = push_objects(conn, syncdb, etagdict)
|
remote_new = push_objects(missing, modified, conn, syncdb, etagdict)
|
||||||
|
|
||||||
# Remove items from the server if they no longer exist locally.
|
# Remove items from the server if they no longer exist locally.
|
||||||
remote_del = remove_remote_objects(conn, syncdb, etagdict)
|
remote_del = remove_remote_objects(orphan, conn, syncdb, etagdict)
|
||||||
|
|
||||||
# Write the synchronization database.
|
# Write the synchronization database.
|
||||||
save_syncdb(syncdbfn, syncdb)
|
save_syncdb(syncdbfn, syncdb)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user