<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[14559] CalendarServer/trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/14559">14559</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2015-03-11 11:00:51 -0700 (Wed, 11 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make trash collection creation occur only when it is needed. No longer use the name &quot;trash&quot;.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunkcalendarservertoolstrashpy">CalendarServer/trunk/calendarserver/tools/trash.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoresqlpy">CalendarServer/trunk/txdav/caldav/datastore/sql.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretesttest_sqlpy">CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastorepoddingmigrationtesttest_migrationpy">CalendarServer/trunk/txdav/common/datastore/podding/migration/test/test_migration.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresqlpy">CalendarServer/trunk/txdav/common/datastore/sql.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemacurrentoracledialectsql">CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemacurrentsql">CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_52_to_53sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_52_to_53.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_52_to_53sql">CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_52_to_53.sql</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoretesttest_trashpy">CalendarServer/trunk/txdav/common/datastore/test/test_trash.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoretestutilpy">CalendarServer/trunk/txdav/common/datastore/test/util.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunkcalendarservertoolstrashpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/tools/trash.py (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/tools/trash.py        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/calendarserver/tools/trash.py        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -91,6 +91,7 @@
</span><span class="cx">     )
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def listTrashedCollectionsForPrincipal(service, store, principalUID):
</span><span class="cx">     directory = store.directoryService()
</span><span class="lines">@@ -99,42 +100,48 @@
</span><span class="cx">         print(&quot;No record found for:&quot;, principalUID)
</span><span class="cx">         returnValue(None)
</span><span class="cx"> 
</span><del>-    txn = store.newTransaction(label=&quot;List trashed collections&quot;)
-    home = yield txn.calendarHomeWithUID(principalUID)
-    if home is None:
-        print(&quot;No home for principal&quot;)
-        returnValue(None)
</del><span class="cx"> 
</span><del>-    trash = yield home.childWithName(&quot;trash&quot;)
</del><ins>+    @inlineCallbacks
+    def doIt(txn):
+        home = yield txn.calendarHomeWithUID(principalUID)
+        if home is None:
+            print(&quot;No home for principal&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    trashedCollections = yield home.children(onlyInTrash=True)
-    if len(trashedCollections) == 0:
-        print(&quot;No trashed collections for:&quot;, prettyRecord(record))
-        returnValue(None)
</del><ins>+        trash = yield home.getTrash()
+        if trash is None:
+            print(&quot;No trash available&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    print(&quot;Listing trashed collections for:&quot;, prettyRecord(record))
-    for collection in trashedCollections:
-        displayName = displayNameForCollection(collection)
-        print(
-            &quot;Collection = \&quot;{}\&quot;, trashed = {}, id = {}&quot;.format(
-                displayName.encode(&quot;utf-8&quot;), collection.whenTrashed(),
-                collection._resourceID
</del><ins>+        trashedCollections = yield home.children(onlyInTrash=True)
+        if len(trashedCollections) == 0:
+            print(&quot;No trashed collections for:&quot;, prettyRecord(record))
+            returnValue(None)
+
+        print(&quot;Listing trashed collections for:&quot;, prettyRecord(record))
+        for collection in trashedCollections:
+            displayName = displayNameForCollection(collection)
+            print(
+                &quot;Collection = \&quot;{}\&quot;, trashed = {}, id = {}&quot;.format(
+                    displayName.encode(&quot;utf-8&quot;), collection.whenTrashed(),
+                    collection._resourceID
+                )
</ins><span class="cx">             )
</span><del>-        )
-        startTime = collection.whenTrashed() - datetime.timedelta(minutes=5)
-        children = yield trash.trashForCollection(
-            collection._resourceID, start=startTime
-        )
-        print(&quot; ...containing events:&quot;)
-        for child in children:
-            component = yield child.component()
-            summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
-            whenTrashed = yield child.whenTrashed()
-            print(&quot; \&quot;{}\&quot;, trashed = {}&quot;.format(summary.encode(&quot;utf-8&quot;), whenTrashed))
</del><ins>+            startTime = collection.whenTrashed() - datetime.timedelta(minutes=5)
+            children = yield trash.trashForCollection(
+                collection._resourceID, start=startTime
+            )
+            print(&quot; ...containing events:&quot;)
+            for child in children:
+                component = yield child.component()
+                summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
+                whenTrashed = yield child.whenTrashed()
+                print(&quot; \&quot;{}\&quot;, trashed = {}&quot;.format(summary.encode(&quot;utf-8&quot;), whenTrashed))
</ins><span class="cx"> 
</span><del>-    yield txn.commit()
</del><ins>+    yield store.inTransaction(label=&quot;List trashed collections&quot;, operation=doIt)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def listTrashedEventsForPrincipal(service, store, principalUID):
</span><span class="cx">     directory = store.directoryService()
</span><span class="lines">@@ -143,39 +150,45 @@
</span><span class="cx">         print(&quot;No record found for:&quot;, principalUID)
</span><span class="cx">         returnValue(None)
</span><span class="cx"> 
</span><del>-    txn = store.newTransaction(label=&quot;List trashed collections&quot;)
-    home = yield txn.calendarHomeWithUID(principalUID)
-    if home is None:
-        print(&quot;No home for principal&quot;)
-        returnValue(None)
</del><span class="cx"> 
</span><del>-    trash = yield home.childWithName(&quot;trash&quot;)
</del><ins>+    @inlineCallbacks
+    def doIt(txn):
+        home = yield txn.calendarHomeWithUID(principalUID)
+        if home is None:
+            print(&quot;No home for principal&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    untrashedCollections = yield home.children(onlyInTrash=False)
-    if len(untrashedCollections) == 0:
-        print(&quot;No untrashed collections for:&quot;, prettyRecord(record))
-        returnValue(None)
</del><ins>+        trash = yield home.getTrash()
+        if trash is None:
+            print(&quot;No trash available&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    for collection in untrashedCollections:
-        displayName = displayNameForCollection(collection)
-        children = yield trash.trashForCollection(collection._resourceID)
-        if len(children) == 0:
-            continue
</del><ins>+        untrashedCollections = yield home.children(onlyInTrash=False)
+        if len(untrashedCollections) == 0:
+            print(&quot;No untrashed collections for:&quot;, prettyRecord(record))
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-        print(&quot;Collection = \&quot;{}\&quot;&quot;.format(displayName.encode(&quot;utf-8&quot;)))
-        for child in children:
-            component = yield child.component()
-            summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
-            whenTrashed = yield child.whenTrashed()
-            print(
-                &quot; \&quot;{}\&quot;, trashed = {}, id = {}&quot;.format(
-                    summary.encode(&quot;utf-8&quot;), whenTrashed, child._resourceID
</del><ins>+        for collection in untrashedCollections:
+            displayName = displayNameForCollection(collection)
+            children = yield trash.trashForCollection(collection._resourceID)
+            if len(children) == 0:
+                continue
+
+            print(&quot;Collection = \&quot;{}\&quot;&quot;.format(displayName.encode(&quot;utf-8&quot;)))
+            for child in children:
+                component = yield child.component()
+                summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
+                whenTrashed = yield child.whenTrashed()
+                print(
+                    &quot; \&quot;{}\&quot;, trashed = {}, id = {}&quot;.format(
+                        summary.encode(&quot;utf-8&quot;), whenTrashed, child._resourceID
+                    )
</ins><span class="cx">                 )
</span><del>-            )
</del><span class="cx"> 
</span><del>-    yield txn.commit()
</del><ins>+    yield store.inTransaction(label=&quot;List trashed events&quot;, operation=doIt)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def restoreTrashedCollection(service, store, principalUID, resourceID):
</span><span class="cx">     directory = store.directoryService()
</span><span class="lines">@@ -184,24 +197,27 @@
</span><span class="cx">         print(&quot;No record found for:&quot;, principalUID)
</span><span class="cx">         returnValue(None)
</span><span class="cx"> 
</span><del>-    txn = store.newTransaction(label=&quot;Restore trashed collection&quot;)
-    home = yield txn.calendarHomeWithUID(principalUID)
-    if home is None:
-        print(&quot;No home for principal&quot;)
-        returnValue(None)
</del><span class="cx"> 
</span><del>-    collection = yield home.childWithID(resourceID, onlyInTrash=True)
-    if collection is None:
-        print(&quot;Collection {} is not in the trash&quot;.format(resourceID))
-        returnValue(None)
</del><ins>+    @inlineCallbacks
+    def doIt(txn):
+        home = yield txn.calendarHomeWithUID(principalUID)
+        if home is None:
+            print(&quot;No home for principal&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    yield collection.fromTrash(
-        restoreChildren=True, delta=datetime.timedelta(minutes=5), verbose=True
-    )
</del><ins>+        collection = yield home.childWithID(resourceID, onlyInTrash=True)
+        if collection is None:
+            print(&quot;Collection {} is not in the trash&quot;.format(resourceID))
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    yield txn.commit()
</del><ins>+        yield collection.fromTrash(
+            restoreChildren=True, delta=datetime.timedelta(minutes=5), verbose=True
+        )
</ins><span class="cx"> 
</span><ins>+    yield store.inTransaction(label=&quot;Restore trashed collection&quot;, operation=doIt)
</ins><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def restoreTrashedEvent(service, store, principalUID, resourceID):
</span><span class="cx">     directory = store.directoryService()
</span><span class="lines">@@ -210,27 +226,33 @@
</span><span class="cx">         print(&quot;No record found for:&quot;, principalUID)
</span><span class="cx">         returnValue(None)
</span><span class="cx"> 
</span><del>-    txn = store.newTransaction(label=&quot;Restore trashed collection&quot;)
-    home = yield txn.calendarHomeWithUID(principalUID)
-    if home is None:
-        print(&quot;No home for principal&quot;)
-        returnValue(None)
</del><span class="cx"> 
</span><del>-    trash = yield home.childWithName(&quot;trash&quot;)
-    child = yield trash.objectResourceWithID(resourceID)
-    if child is None:
-        print(&quot;Event not found&quot;)
-        returnValue(None)
</del><ins>+    @inlineCallbacks
+    def doIt(txn):
+        home = yield txn.calendarHomeWithUID(principalUID)
+        if home is None:
+            print(&quot;No home for principal&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    component = yield child.component()
-    summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
-    print(&quot;Restoring \&quot;{}\&quot;&quot;.format(summary.encode(&quot;utf-8&quot;)))
-    yield child.fromTrash()
</del><ins>+        trash = yield home.getTrash()
+        if trash is None:
+            print(&quot;No trash available&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    yield txn.commit()
</del><ins>+        child = yield trash.objectResourceWithID(resourceID)
+        if child is None:
+            print(&quot;Event not found&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><ins>+        component = yield child.component()
+        summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
+        print(&quot;Restoring \&quot;{}\&quot;&quot;.format(summary.encode(&quot;utf-8&quot;)))
+        yield child.fromTrash()
</ins><span class="cx"> 
</span><ins>+    yield store.inTransaction(label=&quot;Restore trashed event&quot;, operation=doIt)
</ins><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def emptyTrashForPrincipal(service, store, principalUID, days):
</span><span class="cx">     directory = store.directoryService()
</span><span class="lines">@@ -239,45 +261,50 @@
</span><span class="cx">         print(&quot;No record found for:&quot;, principalUID)
</span><span class="cx">         returnValue(None)
</span><span class="cx"> 
</span><del>-    txn = store.newTransaction(label=&quot;List trashed collections&quot;)
-    home = yield txn.calendarHomeWithUID(principalUID)
-    if home is None:
-        print(&quot;No home for principal&quot;)
-        returnValue(None)
</del><span class="cx"> 
</span><del>-    trash = yield home.childWithName(&quot;trash&quot;)
</del><ins>+    @inlineCallbacks
+    def doIt(txn):
+        home = yield txn.calendarHomeWithUID(principalUID)
+        if home is None:
+            print(&quot;No home for principal&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    untrashedCollections = yield home.children(onlyInTrash=False)
-    if len(untrashedCollections) == 0:
-        print(&quot;No untrashed collections for:&quot;, prettyRecord(record))
-        returnValue(None)
</del><ins>+        trash = yield home.getTrash()
+        if trash is None:
+            print(&quot;No trash available&quot;)
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-    endTime = datetime.datetime.utcnow() - datetime.timedelta(days=-days)
-    for collection in untrashedCollections:
-        displayName = displayNameForCollection(collection)
-        children = yield trash.trashForCollection(
-            collection._resourceID, end=endTime
-        )
-        if len(children) == 0:
-            continue
</del><ins>+        untrashedCollections = yield home.children(onlyInTrash=False)
+        if len(untrashedCollections) == 0:
+            print(&quot;No untrashed collections for:&quot;, prettyRecord(record))
+            returnValue(None)
</ins><span class="cx"> 
</span><del>-        print(&quot;Collection = \&quot;{}\&quot;&quot;.format(displayName.encode(&quot;utf-8&quot;)))
-        for child in children:
-            component = yield child.component()
-            summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
-            whenTrashed = yield child.whenTrashed()
-            print(
-                &quot; \&quot;{}\&quot;, trashed = {}, id = {}&quot;.format(
-                    summary.encode(&quot;utf-8&quot;), whenTrashed, child._resourceID
-                )
</del><ins>+        endTime = datetime.datetime.utcnow() - datetime.timedelta(days=-days)
+        for collection in untrashedCollections:
+            displayName = displayNameForCollection(collection)
+            children = yield trash.trashForCollection(
+                collection._resourceID, end=endTime
</ins><span class="cx">             )
</span><del>-            print(&quot;Removing...&quot;)
-            yield child.reallyRemove()
</del><ins>+            if len(children) == 0:
+                continue
</ins><span class="cx"> 
</span><del>-    yield txn.commit()
</del><ins>+            print(&quot;Collection = \&quot;{}\&quot;&quot;.format(displayName.encode(&quot;utf-8&quot;)))
+            for child in children:
+                component = yield child.component()
+                summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
+                whenTrashed = yield child.whenTrashed()
+                print(
+                    &quot; \&quot;{}\&quot;, trashed = {}, id = {}&quot;.format(
+                        summary.encode(&quot;utf-8&quot;), whenTrashed, child._resourceID
+                    )
+                )
+                print(&quot;Removing...&quot;)
+                yield child.reallyRemove()
</ins><span class="cx"> 
</span><ins>+    yield store.inTransaction(label=&quot;Empty trash&quot;, operation=doIt)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def displayNameForCollection(collection):
</span><span class="cx">     try:
</span><span class="cx">         displayName = collection.properties()[
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/sql.py        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -478,6 +478,7 @@
</span><span class="cx"> 
</span><span class="cx">         default_collections = tuple([cls._componentDefaultColumn[name] for name in sorted(cls._componentDefaultColumn.keys())])
</span><span class="cx">         return default_collections + (
</span><ins>+            cls._homeMetaDataSchema.TRASH,
</ins><span class="cx">             cls._homeMetaDataSchema.ALARM_VEVENT_TIMED,
</span><span class="cx">             cls._homeMetaDataSchema.ALARM_VEVENT_ALLDAY,
</span><span class="cx">             cls._homeMetaDataSchema.ALARM_VTODO_TIMED,
</span><span class="lines">@@ -500,6 +501,7 @@
</span><span class="cx"> 
</span><span class="cx">         default_attributes = tuple([cls._componentDefaultAttribute[name] for name in sorted(cls._componentDefaultAttribute.keys())])
</span><span class="cx">         return default_attributes + (
</span><ins>+            &quot;_trash&quot;,
</ins><span class="cx">             &quot;_alarm_vevent_timed&quot;,
</span><span class="cx">             &quot;_alarm_vevent_allday&quot;,
</span><span class="cx">             &quot;_alarm_vtodo_timed&quot;,
</span><span class="lines">@@ -541,7 +543,7 @@
</span><span class="cx">         values = {}
</span><span class="cx">         for attr, col in zip(self.metadataAttributes(), self.metadataColumns()):
</span><span class="cx">             value = getattr(other, attr)
</span><del>-            if attr in self._componentDefaultAttribute.values():
</del><ins>+            if attr in self._componentDefaultAttribute.values() + [&quot;_trash&quot;, ]:
</ins><span class="cx">                 value = calendarIDMap.get(value)
</span><span class="cx">             setattr(self, attr, value)
</span><span class="cx">             values[col] = value
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoretesttest_sqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -467,7 +467,7 @@
</span><span class="cx">         )
</span><span class="cx">         yield migrateHome(fromHome, toHome, lambda x: x.component())
</span><span class="cx">         toCalendars = yield toHome.calendars()
</span><del>-        self.assertEquals(set([c.name() for c in toCalendars if c.name() not in (&quot;inbox&quot;, &quot;trash&quot;)]),
</del><ins>+        self.assertEquals(set([c.name() for c in toCalendars if c.name() not in (&quot;inbox&quot;,)]),
</ins><span class="cx">                           set([k for k in self.requirements['home1'].keys()
</span><span class="cx">                                if self.requirements['home1'][k] is not None]))
</span><span class="cx">         fromCalendars = yield fromHome.calendars()
</span><span class="lines">@@ -499,7 +499,7 @@
</span><span class="cx">         supported_components = set()
</span><span class="cx">         self.assertEqual(len(toCalendars), 2 + len(ical.allowedStoreComponents))
</span><span class="cx">         for calendar in toCalendars:
</span><del>-            if calendar.name() in (&quot;inbox&quot;, &quot;trash&quot;):
</del><ins>+            if calendar.name() in (&quot;inbox&quot;,):
</ins><span class="cx">                 continue
</span><span class="cx">             result = yield calendar.getSupportedComponents()
</span><span class="cx">             supported_components.add(result)
</span><span class="lines">@@ -527,7 +527,7 @@
</span><span class="cx">         supported_components = set()
</span><span class="cx">         self.assertEqual(len(toCalendars), 3)
</span><span class="cx">         for calendar in toCalendars:
</span><del>-            if calendar.name() in (&quot;inbox&quot;, &quot;trash&quot;):
</del><ins>+            if calendar.name() in (&quot;inbox&quot;,):
</ins><span class="cx">                 continue
</span><span class="cx">             result = yield calendar.getSupportedComponents()
</span><span class="cx">             supported_components.add(result)
</span><span class="lines">@@ -1950,7 +1950,7 @@
</span><span class="cx"> 
</span><span class="cx">         home = yield self.homeUnderTest(name=&quot;user01&quot;)
</span><span class="cx">         children = yield home.loadChildren()
</span><del>-        self.assertEqual(len(children), 4)
</del><ins>+        self.assertEqual(len(children), 3)
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastorepoddingmigrationtesttest_migrationpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/podding/migration/test/test_migration.py (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/podding/migration/test/test_migration.py        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/common/datastore/podding/migration/test/test_migration.py        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -551,7 +551,7 @@
</span><span class="cx">         calnames = dict([(calendar.name(), calendar) for calendar in calendars])
</span><span class="cx">         self.assertEqual(
</span><span class="cx">             set(calnames.keys()),
</span><del>-            set((&quot;calendar&quot;, &quot;tasks&quot;, &quot;inbox&quot;, &quot;trash&quot;, self.stash[&quot;sharename_user02_to_user01&quot;], self.stash[&quot;sharename_puser02_to_user01&quot;],))
</del><ins>+            set((&quot;calendar&quot;, &quot;tasks&quot;, &quot;inbox&quot;, self.stash[&quot;sharename_user02_to_user01&quot;], self.stash[&quot;sharename_puser02_to_user01&quot;],))
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx">         # Check shared-by user01 on new pod
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/sql.py (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql.py        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -2320,8 +2320,37 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def createTrash(self):
-        child = yield self._trashClass.create(self, &quot;trash&quot;)
</del><ins>+    def getTrash(self, create=False):
+        child = None
+        if hasattr(self, &quot;_trash&quot;):
+            if self._trash:
+                child = yield self.childWithID(self._trash)
+            elif create:
+                schema = self._homeMetaDataSchema
+
+                # Use a lock to prevent others from creating at the same time
+                yield Select(
+                    From=schema,
+                    Where=(schema.RESOURCE_ID == self.id()),
+                    ForUpdate=True,
+                ).on(self._txn)
+
+                # Re-check to see if someone else created it whilst we were trying to lock
+                self._trash = (yield Select(
+                    [schema.TRASH],
+                    From=schema,
+                    Where=(schema.RESOURCE_ID == self.id()),
+                ).on(self._txn))[0][0]
+                if self._trash:
+                    child = yield self.childWithID(self._trash)
+                else:
+                    child = yield self._trashClass.create(self, str(uuid4()))
+                    self._trash = child.id()
+                    schema = self._homeMetaDataSchema
+                    yield Update(
+                        {schema.TRASH: self._trash},
+                        Where=(schema.RESOURCE_ID == self.id())
+                    ).on(self._txn)
</ins><span class="cx">         returnValue(child)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -3475,7 +3504,6 @@
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def toTrash(self):
</span><del>-        # print(&quot;XYZZY collection toTrash&quot;)
</del><span class="cx">         yield self.ownerDeleteShare()
</span><span class="cx"> 
</span><span class="cx">         for resource in (yield self.objectResources()):
</span><span class="lines">@@ -3542,17 +3570,18 @@
</span><span class="cx">         self._home._children[self._home._childrenKey(False)][self._resourceID] = self
</span><span class="cx"> 
</span><span class="cx">         if restoreChildren:
</span><del>-            trash = yield self._home.childWithName(&quot;trash&quot;)
-            childrenToRestore = yield trash.trashForCollection(
-                self._resourceID, start=startTime
-            )
-            for child in childrenToRestore:
-                if verbose:
-                    component = yield child.component()
-                    summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
-                    print(&quot;Recovering \&quot;{}\&quot;&quot;.format(summary.encode(&quot;utf-8&quot;)))
</del><ins>+            trash = yield self._home.getTrash()
+            if trash is not None:
+                childrenToRestore = yield trash.trashForCollection(
+                    self._resourceID, start=startTime
+                )
+                for child in childrenToRestore:
+                    if verbose:
+                        component = yield child.component()
+                        summary = component.mainComponent().propertyValue(&quot;SUMMARY&quot;, &quot;&lt;no title&gt;&quot;)
+                        print(&quot;Recovering \&quot;{}\&quot;&quot;.format(summary.encode(&quot;utf-8&quot;)))
</ins><span class="cx"> 
</span><del>-                yield child.fromTrash()
</del><ins>+                    yield child.fromTrash()
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @classproperty
</span><span class="lines">@@ -4980,7 +5009,7 @@
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def toTrash(self):
</span><span class="cx">         originalCollection = self._parentCollection._resourceID
</span><del>-        trash = yield self._parentCollection.ownerHome().childWithName(&quot;trash&quot;)
</del><ins>+        trash = yield self._parentCollection.ownerHome().getTrash(create=True)
</ins><span class="cx">         newName = str(uuid4())
</span><span class="cx">         yield self.moveTo(trash, name=newName)
</span><span class="cx">         yield self._updateToTrashQuery.on(
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemacurrentoracledialectsql"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/current-oracle-dialect.sql        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx"> create table CALENDAR_HOME_METADATA (
</span><span class="cx">     &quot;RESOURCE_ID&quot; integer primary key references CALENDAR_HOME on delete cascade,
</span><span class="cx">     &quot;QUOTA_USED_BYTES&quot; integer default 0 not null,
</span><ins>+    &quot;TRASH&quot; integer default null references CALENDAR on delete set null,
</ins><span class="cx">     &quot;DEFAULT_EVENTS&quot; integer default null references CALENDAR on delete set null,
</span><span class="cx">     &quot;DEFAULT_TASKS&quot; integer default null references CALENDAR on delete set null,
</span><span class="cx">     &quot;DEFAULT_POLLS&quot; integer default null references CALENDAR on delete set null,
</span><span class="lines">@@ -654,6 +655,10 @@
</span><span class="cx"> insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
</span><span class="cx"> insert into CALENDARSERVER (NAME, VALUE) values ('NOTIFICATION-DATAVERSION', '1');
</span><span class="cx"> insert into CALENDARSERVER (NAME, VALUE) values ('MIN-VALID-REVISION', '1');
</span><ins>+create index CALENDAR_HOME_METADAT_475de898 on CALENDAR_HOME_METADATA (
+    TRASH
+);
+
</ins><span class="cx"> create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
</span><span class="cx">     DEFAULT_EVENTS
</span><span class="cx"> );
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemacurrentsql"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/current.sql        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -107,6 +107,7 @@
</span><span class="cx"> create table CALENDAR_HOME_METADATA (
</span><span class="cx">   RESOURCE_ID              integer     primary key references CALENDAR_HOME on delete cascade, -- implicit index
</span><span class="cx">   QUOTA_USED_BYTES         integer     default 0 not null,
</span><ins>+  TRASH                    integer     default null references CALENDAR on delete set null,
</ins><span class="cx">   DEFAULT_EVENTS           integer     default null references CALENDAR on delete set null,
</span><span class="cx">   DEFAULT_TASKS            integer     default null references CALENDAR on delete set null,
</span><span class="cx">   DEFAULT_POLLS            integer     default null references CALENDAR on delete set null,
</span><span class="lines">@@ -119,6 +120,8 @@
</span><span class="cx">   MODIFIED                 timestamp   default timezone('UTC', CURRENT_TIMESTAMP)
</span><span class="cx"> );
</span><span class="cx"> 
</span><ins>+create index CALENDAR_HOME_METADATA_TRASH on
+  CALENDAR_HOME_METADATA(TRASH);
</ins><span class="cx"> create index CALENDAR_HOME_METADATA_DEFAULT_EVENTS on
</span><span class="cx">   CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
</span><span class="cx"> create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradesoracledialectupgrade_from_52_to_53sql"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_52_to_53.sql (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_52_to_53.sql        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_52_to_53.sql        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -19,6 +19,15 @@
</span><span class="cx"> ---------------------------------------------------
</span><span class="cx"> 
</span><span class="cx"> -- New columns
</span><ins>+alter table CALENDAR_HOME_METADATA
+  add (&quot;TRASH&quot; integer default null references CALENDAR on delete set null);
+
+create index CALENDAR_HOME_METADAT_475de898 on CALENDAR_HOME_METADATA (
+    TRASH
+);
+
+  
+-- New columns
</ins><span class="cx"> alter table CALENDAR_METADATA
</span><span class="cx">   add (&quot;CHILD_TYPE&quot; integer default 0 not null)
</span><span class="cx">   add (&quot;TRASHED&quot; timestamp default null)
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoresql_schemaupgradespostgresdialectupgrade_from_52_to_53sql"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_52_to_53.sql (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_52_to_53.sql        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_52_to_53.sql        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -19,6 +19,14 @@
</span><span class="cx"> ---------------------------------------------------
</span><span class="cx"> 
</span><span class="cx"> -- New columns
</span><ins>+alter table CALENDAR_HOME_METADATA
+  add column TRASH integer default null references CALENDAR on delete set null;
+
+create index CALENDAR_HOME_METADATA_TRASH on
+  CALENDAR_HOME_METADATA(TRASH);
+
+  
+-- New columns
</ins><span class="cx"> alter table CALENDAR_METADATA
</span><span class="cx">   add column CHILD_TYPE     integer      default 0 not null,
</span><span class="cx">   add column TRASHED        timestamp    default null,
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoretesttest_trashpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/test/test_trash.py (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/test/test_trash.py        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/common/datastore/test/test_trash.py        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -136,7 +136,7 @@
</span><span class="cx"> 
</span><span class="cx">         home = yield txn.calendarHomeWithUID(&quot;user01&quot;, create=True)
</span><span class="cx">         collection = yield home.childWithName(&quot;calendar&quot;)
</span><del>-        trash = yield home.childWithName(&quot;trash&quot;)
</del><ins>+        trash = yield home.getTrash(create=True)
</ins><span class="cx"> 
</span><span class="cx">         # No objects
</span><span class="cx">         objects = yield collection.listObjectResources()
</span><span class="lines">@@ -170,7 +170,7 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx"> 
</span><span class="cx">         # Verify it's in the trash
</span><del>-        resource = yield self._getResource(txn, &quot;user01&quot;, &quot;trash&quot;, newName)
</del><ins>+        resource = yield self._getResource(txn, &quot;user01&quot;, trash.name(), newName)
</ins><span class="cx">         self.assertTrue((yield resource.isInTrash()))
</span><span class="cx">         trashed = yield resource.whenTrashed()
</span><span class="cx">         self.assertFalse(trashed is None)
</span><span class="lines">@@ -180,7 +180,7 @@
</span><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><span class="cx">         # One object in trash
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user01&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user01&quot;, trash.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 1)
</span><span class="cx"> 
</span><span class="cx">         # Put back from trash
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx"> 
</span><span class="cx">         # Not in trash
</span><del>-        resource = yield self._getResource(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user01&quot;, trash.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue(resource is None)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -205,7 +205,7 @@
</span><span class="cx">         self.assertTrue(trashed is None)
</span><span class="cx"> 
</span><span class="cx">         # No objects in trash
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user01&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user01&quot;, trash.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><span class="cx">         yield txn.commit()
</span><span class="lines">@@ -305,17 +305,19 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user01&quot;, &quot;calendar&quot;, &quot;test.ics&quot;)
</span><span class="cx">         yield resource.remove()
</span><ins>+        home1 = yield self._homeForUser(txn, &quot;user01&quot;)
+        trash1 = yield home1.getTrash()
</ins><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
</span><span class="cx"> 
</span><span class="cx">         # user01's copy is in the trash, still with user02 accepted
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        resource = yield self._getResource(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue((yield resource.isInTrash()))
</span><span class="cx">         trashed = yield resource.whenTrashed()
</span><span class="cx">         self.assertFalse(trashed is None)
</span><del>-        data = yield self._getResourceData(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        data = yield self._getResourceData(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue(&quot;PARTSTAT=ACCEPTED&quot; in data)
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -329,14 +331,15 @@
</span><span class="cx">         self.assertTrue(&quot;STATUS:CANCELLED&quot; in data)
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user02&quot;, &quot;calendar&quot;, &quot;&quot;)
</span><span class="cx">         yield resource.remove()
</span><del>-        data = yield self._getResource(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
-        self.assertEquals(data, None)
</del><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
+        self.assertEquals(trash2, None)
</ins><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         # user01 restores event from the trash
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        resource = yield self._getResource(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
-        data = yield self._getResourceData(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
+        data = yield self._getResourceData(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
</ins><span class="cx">         yield resource.fromTrash()
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -491,6 +494,8 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user02&quot;, &quot;calendar&quot;, &quot;&quot;)
</span><span class="cx">         yield resource.remove()
</span><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
</ins><span class="cx"> 
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -510,7 +515,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">         # user02's copy is in the trash only, and still has ACCEPTED
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 1)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -519,7 +524,7 @@
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;inbox&quot;)
</span><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><del>-        data = yield self._getResourceData(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        data = yield self._getResourceData(txn, &quot;user02&quot;, trash2.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue(&quot;PARTSTAT=ACCEPTED&quot; in data)
</span><span class="cx"> 
</span><span class="cx">         # result = yield txn.execSQL(&quot;select * from calendar_object&quot;, [])
</span><span class="lines">@@ -543,7 +548,7 @@
</span><span class="cx"> 
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx"> 
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -597,7 +602,7 @@
</span><span class="cx"> 
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx"> 
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 1)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -742,6 +747,8 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user02&quot;, &quot;calendar&quot;, &quot;&quot;)
</span><span class="cx">         yield resource.remove()
</span><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
</ins><span class="cx"> 
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -760,7 +767,7 @@
</span><span class="cx">         yield resource.remove()
</span><span class="cx"> 
</span><span class="cx">         # user02's copy is in the trash only, and still has ACCEPTED
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 1)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -769,7 +776,7 @@
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;inbox&quot;)
</span><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><del>-        data = yield self._getResourceData(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        data = yield self._getResourceData(txn, &quot;user02&quot;, trash2.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue(&quot;PARTSTAT=ACCEPTED&quot; in data)
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -778,7 +785,7 @@
</span><span class="cx"> 
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx"> 
</span><del>-        resource = yield self._getResource(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user02&quot;, trash2.name(), &quot;&quot;)
</ins><span class="cx">         yield resource.reallyRemove()
</span><span class="cx"> 
</span><span class="cx">         yield txn.commit()
</span><span class="lines">@@ -794,7 +801,7 @@
</span><span class="cx"> 
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx"> 
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -815,7 +822,7 @@
</span><span class="cx"> 
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx"> 
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -926,6 +933,8 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user02&quot;, &quot;calendar&quot;, &quot;&quot;)
</span><span class="cx">         yield resource.remove()
</span><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
</ins><span class="cx"> 
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -948,7 +957,7 @@
</span><span class="cx">         #     print(&quot;ROW&quot;, row)
</span><span class="cx"> 
</span><span class="cx">         # user02's copy is in the trash only, and still has ACCEPTED
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 1)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -957,14 +966,14 @@
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;inbox&quot;)
</span><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><del>-        data = yield self._getResourceData(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        data = yield self._getResourceData(txn, &quot;user02&quot;, trash2.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue(&quot;PARTSTAT=ACCEPTED&quot; in data)
</span><span class="cx"> 
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         # user02 moves it from trash
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        resource = yield self._getResource(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user02&quot;, trash2.name(), &quot;&quot;)
</ins><span class="cx">         yield resource.fromTrash()
</span><span class="cx">         yield txn.commit()
</span><span class="cx">         yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
</span><span class="lines">@@ -982,7 +991,7 @@
</span><span class="cx">         yield resource.remove()
</span><span class="cx"> 
</span><span class="cx">         # user02 has nothing in trash
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -1089,13 +1098,15 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user01&quot;, &quot;calendar&quot;, &quot;test.ics&quot;)
</span><span class="cx">         yield resource.remove()
</span><ins>+        home1 = yield self._homeForUser(txn, &quot;user01&quot;)
+        trash1 = yield home1.getTrash()
</ins><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
</span><span class="cx"> 
</span><span class="cx">         # user01's copy is in the trash, still with user02 partstat
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        data = yield self._getResourceData(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        data = yield self._getResourceData(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue(&quot;PARTSTAT=TENTATIVE&quot; in data)
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -1109,14 +1120,15 @@
</span><span class="cx">         self.assertTrue(&quot;STATUS:CANCELLED&quot; in data)
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user02&quot;, &quot;calendar&quot;, &quot;&quot;)
</span><span class="cx">         yield resource.remove()
</span><del>-        data = yield self._getResource(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
-        self.assertEquals(data, None)
</del><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
+        self.assertEquals(trash2, None)
</ins><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         # user01 restores event from the trash
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        resource = yield self._getResource(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
-        data = yield self._getResourceData(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
+        data = yield self._getResourceData(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
</ins><span class="cx">         yield resource.fromTrash()
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -1232,6 +1244,8 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user02&quot;, &quot;calendar&quot;, &quot;&quot;)
</span><span class="cx">         yield resource.remove()
</span><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
</ins><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
</span><span class="lines">@@ -1249,7 +1263,7 @@
</span><span class="cx">         yield resource.remove()
</span><span class="cx"> 
</span><span class="cx">         # user02's copy is in the trash only, and still has TENTATIVE
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 1)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -1258,14 +1272,14 @@
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;inbox&quot;)
</span><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><del>-        data = yield self._getResourceData(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        data = yield self._getResourceData(txn, &quot;user02&quot;, trash2.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue(&quot;PARTSTAT=TENTATIVE&quot; in data)
</span><span class="cx"> 
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         # user02 moves it from trash
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        resource = yield self._getResource(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user02&quot;, trash2.name(), &quot;&quot;)
</ins><span class="cx">         yield resource.fromTrash()
</span><span class="cx">         yield txn.commit()
</span><span class="cx">         yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
</span><span class="lines">@@ -1283,7 +1297,7 @@
</span><span class="cx">         yield resource.remove()
</span><span class="cx"> 
</span><span class="cx">         # user02 has nothing in trash
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -1392,13 +1406,15 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user01&quot;, &quot;calendar&quot;, &quot;test.ics&quot;)
</span><span class="cx">         yield resource.remove()
</span><ins>+        home1 = yield self._homeForUser(txn, &quot;user01&quot;)
+        trash1 = yield home1.getTrash()
</ins><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
</span><span class="cx"> 
</span><span class="cx">         # user01's copy is in the trash, still with user02 accepted
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        data = yield self._getResourceData(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        data = yield self._getResourceData(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue(&quot;PARTSTAT=ACCEPTED&quot; in data)
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -1412,13 +1428,14 @@
</span><span class="cx">         self.assertTrue(&quot;STATUS:CANCELLED&quot; in data)
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user02&quot;, &quot;calendar&quot;, &quot;&quot;)
</span><span class="cx">         yield resource.remove()
</span><del>-        data = yield self._getResource(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
-        self.assertEquals(data, None)
</del><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
+        self.assertEquals(trash2, None)
</ins><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         # user01 restores event from the trash
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        resource = yield self._getResource(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
</ins><span class="cx">         trashedName = yield resource.fromTrash()
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -1427,7 +1444,7 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx"> 
</span><span class="cx">         # user01's trash should be empty
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user01&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user01&quot;, trash1.name())
</ins><span class="cx">         self.assertEquals(len(resourceNames), 0)
</span><span class="cx"> 
</span><span class="cx">         # user01 should have two .ics
</span><span class="lines">@@ -1451,8 +1468,9 @@
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="cx">         self.assertEquals(len(resourceNames), 1)
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
-        self.assertEquals(len(resourceNames), 0)
</del><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
+        self.assertEquals(trash2, None)
</ins><span class="cx"> 
</span><span class="cx">         data = yield self._getResourceData(txn, &quot;user02&quot;, &quot;calendar&quot;, &quot;&quot;)
</span><span class="cx">         self.assertTrue(&quot;PARTSTAT=NEEDS-ACTION&quot; in data)
</span><span class="lines">@@ -1554,6 +1572,8 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         resource = yield self._getResource(txn, &quot;user02&quot;, &quot;calendar&quot;, &quot;&quot;)
</span><span class="cx">         yield resource.remove()
</span><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
</ins><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
</span><span class="lines">@@ -1573,7 +1593,7 @@
</span><span class="cx">         yield resource.remove()
</span><span class="cx"> 
</span><span class="cx">         # user02's copy is in the trash only, and still has ACCEPTED
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 1)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -1582,13 +1602,13 @@
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;inbox&quot;)
</span><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><del>-        data = yield self._getResourceData(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        data = yield self._getResourceData(txn, &quot;user02&quot;, trash2.name(), &quot;&quot;)
</ins><span class="cx">         self.assertTrue(&quot;PARTSTAT=ACCEPTED&quot; in data)
</span><span class="cx"> 
</span><span class="cx">         yield txn.commit()
</span><span class="cx">         # user02 moves it from trash
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        resource = yield self._getResource(txn, &quot;user02&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user02&quot;, trash2.name(), &quot;&quot;)
</ins><span class="cx">         yield resource.fromTrash()
</span><span class="cx">         yield txn.commit()
</span><span class="cx">         yield JobItem.waitEmpty(self.store.newTransaction, reactor, 60)
</span><span class="lines">@@ -1606,7 +1626,7 @@
</span><span class="cx">         yield resource.remove()
</span><span class="cx"> 
</span><span class="cx">         # user02 has nothing in trash
</span><del>-        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
</del><ins>+        resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, trash2.name())
</ins><span class="cx">         self.assertEqual(len(resourceNames), 0)
</span><span class="cx"> 
</span><span class="cx">         resourceNames = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;calendar&quot;)
</span><span class="lines">@@ -1733,7 +1753,9 @@
</span><span class="cx">         self.assertEquals(len(objects), 1)
</span><span class="cx"> 
</span><span class="cx">         # No objects in trash
</span><del>-        trash = yield self._collectionForUser(txn, &quot;user01&quot;, &quot;trash&quot;)
</del><ins>+        home1 = yield self._homeForUser(txn, &quot;user01&quot;)
+        trash1 = yield home1.getTrash(create=True)
+        trash = yield self._collectionForUser(txn, &quot;user01&quot;, trash1.name())
</ins><span class="cx">         objects = yield trash.listObjectResources()
</span><span class="cx">         self.assertEquals(len(objects), 0)
</span><span class="cx"> 
</span><span class="lines">@@ -1755,7 +1777,7 @@
</span><span class="cx"> 
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         # One object in trash
</span><del>-        trash = yield self._collectionForUser(txn, &quot;user01&quot;, &quot;trash&quot;)
</del><ins>+        trash = yield self._collectionForUser(txn, &quot;user01&quot;, trash1.name())
</ins><span class="cx">         objects = yield trash.listObjectResources()
</span><span class="cx">         self.assertEquals(len(objects), 1)
</span><span class="cx"> 
</span><span class="lines">@@ -1837,30 +1859,34 @@
</span><span class="cx">         txn = self.store.newTransaction()
</span><span class="cx">         resource2 = yield self._getResource(txn, &quot;user02&quot;, calendarName2, &quot;test.ics&quot;)
</span><span class="cx">         yield resource2.remove()
</span><ins>+        home1 = yield self._homeForUser(txn, &quot;user01&quot;)
+        trash1 = yield home1.getTrash()
</ins><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        names = yield self._getResourceNames(txn, &quot;user01&quot;, &quot;trash&quot;)
</del><ins>+        names = yield self._getResourceNames(txn, &quot;user01&quot;, trash1.name())
</ins><span class="cx">         self.assertEquals(len(names), 1)
</span><span class="cx">         names = yield self._getResourceNames(txn, &quot;user01&quot;, &quot;calendar&quot;)
</span><span class="cx">         self.assertEquals(len(names), 0)
</span><del>-        names = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
-        self.assertEquals(len(names), 0)
</del><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
+        self.assertEquals(trash2, None)
</ins><span class="cx">         names = yield self._getResourceNames(txn, &quot;user02&quot;, calendarName2)
</span><span class="cx">         self.assertEquals(len(names), 0)
</span><span class="cx"> 
</span><del>-        resource = yield self._getResource(txn, &quot;user01&quot;, &quot;trash&quot;, &quot;&quot;)
</del><ins>+        resource = yield self._getResource(txn, &quot;user01&quot;, trash1.name(), &quot;&quot;)
</ins><span class="cx">         yield resource.fromTrash()
</span><span class="cx"> 
</span><span class="cx">         yield txn.commit()
</span><span class="cx"> 
</span><span class="cx">         txn = self.store.newTransaction()
</span><del>-        names = yield self._getResourceNames(txn, &quot;user01&quot;, &quot;trash&quot;)
</del><ins>+        names = yield self._getResourceNames(txn, &quot;user01&quot;, trash1.name())
</ins><span class="cx">         self.assertEquals(len(names), 0)
</span><span class="cx">         names = yield self._getResourceNames(txn, &quot;user01&quot;, &quot;calendar&quot;)
</span><span class="cx">         self.assertEquals(len(names), 1)
</span><del>-        names = yield self._getResourceNames(txn, &quot;user02&quot;, &quot;trash&quot;)
-        self.assertEquals(len(names), 0)
</del><ins>+        home2 = yield self._homeForUser(txn, &quot;user02&quot;)
+        trash2 = yield home2.getTrash()
+        self.assertEquals(trash2, None)
</ins><span class="cx">         names = yield self._getResourceNames(txn, &quot;user02&quot;, calendarName2)
</span><span class="cx">         self.assertEquals(len(names), 1)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoretestutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/test/util.py (14558 => 14559)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/test/util.py        2015-03-11 02:18:03 UTC (rev 14558)
+++ CalendarServer/trunk/txdav/common/datastore/test/util.py        2015-03-11 18:00:51 UTC (rev 14559)
</span><span class="lines">@@ -483,7 +483,6 @@
</span><span class="cx">                 else:
</span><span class="cx">                     yield home.removeCalendarWithName(&quot;calendar&quot;)
</span><span class="cx">                 yield home.removeCalendarWithName(&quot;inbox&quot;)
</span><del>-                yield home.removeCalendarWithName(&quot;trash&quot;)
</del><span class="cx">             except NoSuchHomeChildError:
</span><span class="cx">                 pass
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>