[CalendarServer-changes] [6405] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Oct 6 13:31:13 PDT 2010
Revision: 6405
http://trac.macosforge.org/projects/calendarserver/changeset/6405
Author: cdaboo at apple.com
Date: 2010-10-06 13:31:12 -0700 (Wed, 06 Oct 2010)
Log Message:
-----------
Handle depth:infinity sync with sharing.
Modified Paths:
--------------
CalendarServer/trunk/twext/web2/dav/resource.py
CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py
CalendarServer/trunk/twistedcaldav/resource.py
CalendarServer/trunk/twistedcaldav/storebridge.py
CalendarServer/trunk/txdav/common/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
Modified: CalendarServer/trunk/twext/web2/dav/resource.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/resource.py 2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/twext/web2/dav/resource.py 2010-10-06 20:31:12 UTC (rev 6405)
@@ -719,6 +719,7 @@
# First find all depth 1 children
names1= []
namesDeep = []
+ collections1 = []
if names:
for name in names:
(names1 if name.rstrip("/").find("/") == -1 else namesDeep).append(name.rstrip("/"))
@@ -730,10 +731,12 @@
basepath = request.urlForResource(self)
childnames = list(self.listChildren())
for childname in childnames:
- if names1 and childname not in names1:
- continue
childpath = joinURL(basepath, urllib.quote(childname))
child = (yield request.locateChildResource(self, childname))
+ if child.isCollection():
+ collections1.append((child, childpath + "/"))
+ if names and childname not in names1:
+ continue
if child is None:
children.append((None, childpath + "/"))
else:
@@ -756,7 +759,6 @@
# Now determine whether each ace satisfies privileges
#print aclmap
- allowed_collections = []
for items in aclmap.itervalues():
checked = (yield self.checkACLPrivilege(
request, items[0], items[1], privileges, inherited_aces
@@ -765,8 +767,6 @@
for resource, url in items[2]:
if okcallback:
okcallback(resource, url)
- if resource.isCollection():
- allowed_collections.append((resource, url))
else:
if badcallback:
for resource, url in items[2]:
@@ -779,15 +779,15 @@
collection, name = name.split("/", 1)
child_collections.setdefault(collection, []).append(name)
- for collection, url in allowed_collections:
- collection_name = collection.name()
+ for collection, url in collections1:
+ collection_name = url.split("/")[-2]
if collection_name in child_collections:
collection_inherited_aces = (
yield collection.inheritedACEsforChildren(request)
)
yield collection.findChildrenFaster(
depth, request, okcallback, badcallback,
- child_collections[collection_name], privileges,
+ child_collections[collection_name] if names else None, privileges,
inherited_aces=collection_inherited_aces
)
Modified: CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py 2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py 2010-10-06 20:31:12 UTC (rev 6405)
@@ -106,7 +106,7 @@
# the child resource loop and supply those to the checkPrivileges on each child.
filteredaces = (yield self.inheritedACEsforChildren(request))
- changed, removed, newtoken = self.whatchanged(sync_collection.sync_token, depth)
+ changed, removed, notallowed, newtoken = self.whatchanged(sync_collection.sync_token, depth)
# Now determine which valid resources are readable and which are not
ok_resources = []
@@ -146,6 +146,10 @@
href = davxml.HRef.fromString(joinURL(request.uri, name))
responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.NOT_FOUND)))
+ for name in notallowed:
+ href = davxml.HRef.fromString(joinURL(request.uri, name))
+ responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.NOT_ALLOWED)))
+
if not hasattr(request, "extendedLogItems"):
request.extendedLogItems = {}
request.extendedLogItems["responses"] = len(responses)
Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py 2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/twistedcaldav/resource.py 2010-10-06 20:31:12 UTC (rev 6405)
@@ -1342,11 +1342,11 @@
revision = 0
try:
- changed, removed = self._indexWhatChanged(revision, depth)
+ changed, removed, notallowed = self._indexWhatChanged(revision, depth)
except SyncTokenValidException:
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (dav_namespace, "valid-sync-token")))
- return changed, removed, current_token
+ return changed, removed, notallowed, current_token
def _indexWhatChanged(self, revision, depth):
# Now handled directly by newstore
@@ -2189,14 +2189,17 @@
result.append(davxml.Report(SyncCollection(),))
return result
- def _indexWhatChanged(self, revision, depth):
- # The newstore implementation supports this directly
- return self._newStoreHome.resourceNamesSinceToken(revision, depth)
+ def _mergeSyncTokens(self, hometoken, notificationtoken):
+ """
+ Merge two sync tokens, choosing the higher revision number of the two, but keeping
+ the home resource-id intact.
+ """
+ homekey, homerev = hometoken.split("#", 1)
+ notrev = notificationtoken.split("#", 1)[1]
+ if int(notrev) > int(homerev):
+ hometoken = "%s#%s" % (homekey, notrev,)
+ return hometoken
- def getSyncToken(self):
- # The newstore implementation supports this directly
- return self._newStoreHome.syncToken()
-
def canShare(self):
raise NotImplementedError
@@ -2522,6 +2525,47 @@
return davxml.ACL(*aces)
+ def getSyncToken(self):
+ # The newstore implementation supports this directly
+ caltoken = self._newStoreHome.syncToken()
+
+ if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
+ notificationtoken = self.getChild("notification").getSyncToken()
+
+ # Merge tokens
+ caltoken = self._mergeSyncTokens(caltoken, notificationtoken)
+
+ return caltoken
+
+ def _indexWhatChanged(self, revision, depth):
+ # The newstore implementation supports this directly
+ changed, deleted = self._newStoreHome.resourceNamesSinceToken(revision, depth)
+ notallowed = []
+
+ # Need to insert some addition items on first sync
+ if revision == 0:
+ changed.append("outbox/")
+
+ if config.FreeBusyURL.Enabled:
+ changed.append("freebusy")
+
+ if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
+ changed.append("notification/")
+
+ # Dropbox is never synchronized
+ if config.EnableDropBox:
+ notallowed.append("dropbox/")
+
+ # Add in notification changes
+ if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
+ noti_changed, noti_deleted, noti_notallowed = self.getChild("notification")._indexWhatChanged(revision, depth)
+
+ changed.extend([joinURL("notification", name) for name in noti_changed])
+ deleted.extend([joinURL("notification", name) for name in noti_deleted])
+ notallowed.extend([joinURL("notification", name) for name in noti_notallowed])
+
+ return changed, deleted, notallowed
+
class AddressBookHomeResource (CommonHomeResource):
"""
Address book home collection resource.
@@ -2576,6 +2620,41 @@
return similar
+ def getSyncToken(self):
+ # The newstore implementation supports this directly
+ adbktoken = self._newStoreHome.syncToken()
+
+ if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
+ notifcationtoken = self.getChild("notification").getSyncToken()
+
+ # Merge tokens
+ adbkkey, adbkrev = adbktoken.split("#", 1)
+ notrev = notifcationtoken.split("#", 1)[1]
+ if int(notrev) > int(adbkrev):
+ adbktoken = "%s#%s" % (adbkkey, notrev,)
+
+ return adbktoken
+
+ def _indexWhatChanged(self, revision, depth):
+ # The newstore implementation supports this directly
+ changed, deleted = self._newStoreHome.resourceNamesSinceToken(revision, depth)
+ notallowed = []
+
+ # Need to insert some addition items on first sync
+ if revision == 0:
+ if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
+ changed.append("notification/")
+
+ # Add in notification changes
+ if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
+ noti_changed, noti_deleted, noti_notallowed = self.getChild("notification")._indexWhatChanged(revision, depth)
+
+ changed.extend([joinURL("notification", name) for name in noti_changed])
+ deleted.extend([joinURL("notification", name) for name in noti_deleted])
+ notallowed.extend([joinURL("notification", name) for name in noti_notallowed])
+
+ return changed, deleted, notallowed
+
class GlobalAddressBookResource (ReadOnlyResourceMixIn, CalDAVResource):
"""
Global address book. All we care about is making sure permissions are setup.
Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py 2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py 2010-10-06 20:31:12 UTC (rev 6405)
@@ -243,7 +243,7 @@
def _indexWhatChanged(self, revision, depth):
# The newstore implementation supports this directly
- return self._newStoreCalendar.resourceNamesSinceToken(revision)
+ return self._newStoreCalendar.resourceNamesSinceToken(revision) + ([],)
@classmethod
def transform(cls, self, calendar, home):
@@ -1279,7 +1279,7 @@
def _indexWhatChanged(self, revision, depth):
# The newstore implementation supports this directly
- return self._newStoreAddressBook.resourceNamesSinceToken(revision)
+ return self._newStoreAddressBook.resourceNamesSinceToken(revision) + ([],)
@classmethod
def transform(cls, self, addressbook, home):
@@ -1852,6 +1852,9 @@
self._initializeWithNotifications(notifications, home)
+ def name(self):
+ return "notification"
+
def listChildren(self):
l = []
for notification in self._newStoreNotifications.notificationObjects():
@@ -1865,7 +1868,7 @@
return self._newStoreNotifications.syncToken()
def _indexWhatChanged(self, revision, depth):
- return self._newStoreNotifications.resourceNamesSinceToken(revision)
+ return self._newStoreNotifications.resourceNamesSinceToken(revision) + ([],)
def addNotification(self, request, uid, xmltype, xmldata):
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2010-10-06 20:31:12 UTC (rev 6405)
@@ -299,6 +299,7 @@
self._resourceID = resourceID
self._shares = None
self._children = {}
+ self._sharedChildren = {}
self._notifier = notifier
# Needed for REVISION/BIND table join
@@ -350,15 +351,44 @@
@return: an iterable of C{str}s.
"""
+ return self._listChildren(owned=True)
+
+ def listSharedChildren(self):
+ """
+ Retrieve the names of the children in this home.
+
+ @return: an iterable of C{str}s.
+ """
+ return self._listChildren(owned=False)
+
+ def _listChildren(self, owned):
+ """
+ Retrieve the names of the children in this home.
+
+ @return: an iterable of C{str}s.
+ """
# FIXME: not specified on the interface or exercised by the tests, but
# required by clients of the implementation!
- rows = self._txn.execSQL(
- "select %(column_RESOURCE_NAME)s from %(name)s where "
- "%(column_HOME_RESOURCE_ID)s = %%s "
- "and %(column_BIND_MODE)s = %%s " % self._bindTable,
- # Right now, we only show owned calendars.
- [self._resourceID, _BIND_MODE_OWN]
- )
+ if owned:
+ rows = self._txn.execSQL("""
+ select %(column_RESOURCE_NAME)s from %(name)s
+ where
+ %(column_HOME_RESOURCE_ID)s = %%s and
+ %(column_BIND_MODE)s = %%s
+ """ % self._bindTable,
+ [self._resourceID, _BIND_MODE_OWN]
+ )
+ else:
+ rows = self._txn.execSQL("""
+ select %(column_RESOURCE_NAME)s from %(name)s
+ where
+ %(column_HOME_RESOURCE_ID)s = %%s and
+ %(column_BIND_MODE)s != %%s and
+ %(column_RESOURCE_NAME)s is not null
+ """ % self._bindTable,
+ [self._resourceID, _BIND_MODE_OWN]
+ )
+
names = [row[0] for row in rows]
return names
@@ -373,12 +403,65 @@
@return: an L{ICalendar} or C{None} if no such child
exists.
"""
- data = self._txn.execSQL(
- "select %(column_RESOURCE_ID)s from %(name)s where "
- "%(column_RESOURCE_NAME)s = %%s and %(column_HOME_RESOURCE_ID)s = %%s "
- "and %(column_BIND_MODE)s = %%s" % self._bindTable,
- [name, self._resourceID, _BIND_MODE_OWN]
- )
+ return self._childWithName(name, owned=True)
+
+ @memoized('name', '_sharedChildren')
+ def sharedChildWithName(self, name):
+ """
+ Retrieve the shared child with the given C{name} contained in this
+ home. Return a child object with this home and the name.
+
+ IMPORTANT: take care when using this. Shared calendars should normally
+ be accessed through the owner home collection, not the sharee home collection.
+ The only reason for access through sharee home is to do some housekeeping
+ for maintaining the revisions database to show shared calendars appearing and
+ disappearing in the sharee home.
+
+ @param name: a string.
+ @return: an L{ICalendar} or C{None} if no such child
+ exists.
+ """
+ return self._childWithName(name, owned=False)
+
+ def _childWithName(self, name, owned):
+ """
+ Retrieve the child with the given C{name} contained in this
+ home.
+
+ @param name: a string.
+ @return: an L{ICalendar} or C{None} if no such child
+ exists.
+ """
+
+ if owned:
+ data = self._txn.execSQL("""
+ select %(column_RESOURCE_ID)s from %(name)s
+ where
+ %(column_RESOURCE_NAME)s = %%s and
+ %(column_HOME_RESOURCE_ID)s = %%s and
+ %(column_BIND_MODE)s = %%s
+ """ % self._bindTable,
+ [
+ name,
+ self._resourceID,
+ _BIND_MODE_OWN
+ ]
+ )
+ else:
+ data = self._txn.execSQL("""
+ select %(column_RESOURCE_ID)s from %(name)s
+ where
+ %(column_RESOURCE_NAME)s = %%s and
+ %(column_HOME_RESOURCE_ID)s = %%s and
+ %(column_BIND_MODE)s != %%s
+ """ % self._bindTable,
+ [
+ name,
+ self._resourceID,
+ _BIND_MODE_OWN
+ ]
+ )
+
if not data:
return None
resourceID = data[0][0]
@@ -389,7 +472,6 @@
notifier = None
return self._childClass(self, name, resourceID, notifier)
-
def createChildWithName(self, name):
if name.startswith("."):
raise HomeChildNameNotAllowedError(name)
@@ -456,33 +538,46 @@
def syncToken(self):
revision = self._txn.execSQL(
"""
- select max(%(column_REVISION)s) from %(name)s
- where %(column_HOME_RESOURCE_ID)s = %%s
- """ % self._revisionsTable,
- [self._resourceID,]
+ select max(%(REV:column_REVISION)s) from %(REV:name)s
+ where %(REV:column_RESOURCE_ID)s in (
+ select %(BIND:column_RESOURCE_ID)s from %(BIND:name)s
+ where %(BIND:column_HOME_RESOURCE_ID)s = %%s
+ ) or (
+ %(REV:column_HOME_RESOURCE_ID)s = %%s and
+ %(REV:column_RESOURCE_ID)s is null
+ )
+ """ % self._revisionBindJoinTable,
+ [self._resourceID, self._resourceID,]
)[0][0]
return "%s#%s" % (self._resourceID, revision)
def resourceNamesSinceToken(self, token, depth):
+
results = [
(
path if path else (collection if collection else ""),
name if name else "",
- deleted
+ wasdeleted
)
- for path, collection, name, deleted in
+ for path, collection, name, wasdeleted in
self._txn.execSQL("""
select %(BIND:column_RESOURCE_NAME)s, %(REV:column_COLLECTION_NAME)s, %(REV:column_RESOURCE_NAME)s, %(REV:column_DELETED)s
from %(REV:name)s
- left outer join %(BIND:name)s on (%(REV:name)s.%(REV:column_RESOURCE_ID)s = %(BIND:name)s.%(BIND:column_RESOURCE_ID)s)
- where %(REV:column_REVISION)s > %%s and %(REV:name)s.%(REV:column_HOME_RESOURCE_ID)s = %%s
+ left outer join %(BIND:name)s on (
+ %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = %%s and
+ %(REV:name)s.%(REV:column_RESOURCE_ID)s = %(BIND:name)s.%(BIND:column_RESOURCE_ID)s
+ )
+ where
+ %(REV:column_REVISION)s > %%s and
+ %(REV:name)s.%(REV:column_HOME_RESOURCE_ID)s = %%s
""" % self._revisionBindJoinTable,
- [token, self._resourceID],
+ [self._resourceID, token, self._resourceID],
)
]
deleted = []
deleted_collections = set()
+ changed_collections = set()
for path, name, wasdeleted in results:
if wasdeleted:
if token:
@@ -494,7 +589,51 @@
for path, name, wasdeleted in results:
if path not in deleted_collections:
changed.append("%s/%s" % (path, name,))
+ if not name:
+ changed_collections.add(path)
+ # Now deal with shared collections
+ shares = self.listSharedChildren()
+ for sharename in shares:
+ sharetoken = 0 if sharename in changed_collections else token
+ shareID = self._txn.execSQL("""
+ select %(column_RESOURCE_ID)s from %(name)s
+ where
+ %(column_RESOURCE_NAME)s = %%s and
+ %(column_HOME_RESOURCE_ID)s = %%s and
+ %(column_BIND_MODE)s != %%s
+ """ % self._bindTable,
+ [
+ sharename,
+ self._resourceID,
+ _BIND_MODE_OWN
+ ]
+ )[0][0]
+ results = [
+ (
+ sharename,
+ name if name else "",
+ wasdeleted
+ )
+ for name, wasdeleted in
+ self._txn.execSQL("""
+ select %(column_RESOURCE_NAME)s, %(column_DELETED)s
+ from %(name)s
+ where %(column_REVISION)s > %%s and %(column_RESOURCE_ID)s = %%s
+ """ % self._revisionsTable,
+ [sharetoken, shareID],
+ ) if name
+ ]
+
+ for path, name, wasdeleted in results:
+ if wasdeleted:
+ if sharetoken:
+ deleted.append("%s/%s" % (path, name,))
+
+ for path, name, wasdeleted in results:
+ changed.append("%s/%s" % (path, name,))
+
+
changed.sort()
deleted.sort()
return changed, deleted,
@@ -712,11 +851,20 @@
def syncToken(self):
revision = self._txn.execSQL(
"""
- select %(column_REVISION)s from %(name)s
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+ select max(%(column_REVISION)s) from %(name)s
+ where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is not null
""" % self._revisionsTable,
[self._resourceID,]
)[0][0]
+ if revision is None:
+ revision = self._txn.execSQL(
+ """
+ select %(column_REVISION)s from %(name)s
+ where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+ """ % self._revisionsTable,
+ [self._resourceID,]
+ )[0][0]
+
return "%s#%s" % (self._resourceID, revision,)
def objectResourcesSinceToken(self, token):
@@ -796,7 +944,8 @@
[self._home._resourceID, self._resourceID,]
)
- # Then adjust collection entry to deleted state
+ # Then adjust collection entry to deleted state (do this for all entries with this collection's
+ # resource-id so that we deal with direct shares which are not normally removed thorugh an unshare
self._txn.execSQL("""
update %(name)s
set (%(column_RESOURCE_ID)s, %(column_REVISION)s, %(column_DELETED)s)
@@ -830,13 +979,6 @@
""" % self._revisionsTable,
[nextrevision, self._resourceID, name]
)
- self._txn.execSQL("""
- update %(name)s
- set (%(column_REVISION)s) = (%%s)
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
- """ % self._revisionsTable,
- [nextrevision, self._resourceID,]
- )
elif action == "update":
self._txn.execSQL("""
update %(name)s
@@ -845,13 +987,6 @@
""" % self._revisionsTable,
[nextrevision, self._resourceID, name]
)
- self._txn.execSQL("""
- update %(name)s
- set (%(column_REVISION)s) = (%%s)
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
- """ % self._revisionsTable,
- [nextrevision, self._resourceID,]
- )
elif action == "insert":
# Note that an "insert" may happen for a resource that previously existed and then
# was deleted. In that case an entry in the REVISIONS table still exists so we have to
@@ -880,13 +1015,6 @@
""" % self._revisionsTable,
[self._home._resourceID, self._resourceID, name, nextrevision]
)
- self._txn.execSQL("""
- update %(name)s
- set (%(column_REVISION)s) = (%%s)
- where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
- """ % self._revisionsTable,
- [nextrevision, self._resourceID,]
- )
@cached
def properties(self):
@@ -1153,11 +1281,20 @@
def syncToken(self):
revision = self._txn.execSQL(
"""
- select %(column_REVISION)s from %(name)s
- where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+ select max(%(column_REVISION)s) from %(name)s
+ where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is not null
""" % self._revisionsTable,
[self._resourceID,]
)[0][0]
+ if revision is None:
+ revision = self._txn.execSQL(
+ """
+ select %(column_REVISION)s from %(name)s
+ where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+ """ % self._revisionsTable,
+ [self._resourceID,]
+ )[0][0]
+
return "%s#%s" % (self._resourceID, revision,)
def objectResourcesSinceToken(self, token):
@@ -1230,13 +1367,6 @@
""" % self._revisionsTable,
[nextrevision, self._resourceID, name]
)
- self._txn.execSQL("""
- update %(name)s
- set (%(column_REVISION)s) = (%%s)
- where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
- """ % self._revisionsTable,
- [nextrevision, self._resourceID]
- )
elif action == "update":
self._txn.execSQL("""
update %(name)s
@@ -1245,13 +1375,6 @@
""" % self._revisionsTable,
[nextrevision, self._resourceID, name]
)
- self._txn.execSQL("""
- update %(name)s
- set (%(column_REVISION)s) = (%%s)
- where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
- """ % self._revisionsTable,
- [nextrevision, self._resourceID]
- )
elif action == "insert":
# Note that an "insert" may happen for a resource that previously existed and then
# was deleted. In that case an entry in the REVISIONS table still exists so we have to
@@ -1280,13 +1403,6 @@
""" % self._revisionsTable,
[self._resourceID, name, nextrevision]
)
- self._txn.execSQL("""
- update %(name)s
- set (%(column_REVISION)s) = (%%s)
- where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
- """ % self._revisionsTable,
- [nextrevision, self._resourceID]
- )
@cached
def properties(self):
Modified: CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_legacy.py 2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/txdav/common/datastore/sql_legacy.py 2010-10-06 20:31:12 UTC (rev 6405)
@@ -539,8 +539,16 @@
True,
record.summary,
])
+
+ shareeCollection = self._home.sharedChildWithName(record.localname)
+ shareeCollection._initSyncToken()
def removeRecordForLocalName(self, localname):
+
+ record = self.recordForLocalName(localname)
+ shareeCollection = self._home.sharedChildWithName(record.localname)
+ shareeCollection._deletedSyncToken()
+
self._txn.execSQL(
"""
update %(name)s
@@ -553,6 +561,11 @@
def removeRecordForShareUID(self, shareUID):
+
+ record = self.recordForShareUID(shareUID)
+ shareeCollection = self._home.sharedChildWithName(record.localname)
+ shareeCollection._deletedSyncToken()
+
if not shareUID.startswith("Direct"):
self._txn.execSQL(
"""
@@ -578,8 +591,8 @@
""" % self._bindTable,
[homeID, resourceID,]
)
-
+
class SQLLegacyCalendarShares(SQLLegacyShares):
"""
Emulator for the implicit interface specified by
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20101006/cc637e1a/attachment-0001.html>
More information about the calendarserver-changes
mailing list