<!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>[14382] CalendarServer/branches/users/cdaboo/pod2pod-migration</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/14382">14382</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2015-02-06 11:17:54 -0800 (Fri, 06 Feb 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge from trunk.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationbin_buildsh">CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/_build.sh</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationbinpackage">CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/package</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarserverdashboard_servicepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/dashboard_service.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertapcaldavpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tap/caldav.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolsagentpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/agent.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolsdkimtoolpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/dkimtool.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolstesttest_calverifypy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/test/test_calverify.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationrequirementsdevtxt">CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-dev.txt</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationrequirementsstabletxt">CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-stable.txt</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationsupportApplemake">CalendarServer/branches/users/cdaboo/pod2pod-migration/support/Apple.make</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavresourcepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/resource.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavsharingpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/sharing.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavstdconfigpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/stdconfig.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavstorebridgepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/storebridge.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavtesttest_sharingpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/test/test_sharing.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavupgradepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/upgrade.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduledkimpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/dkim.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduleresourcepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/resource.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduletesttest_dkimpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingitippy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/itip.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingprocessingpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/processing.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingschedulerpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/scheduler.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingtesttest_itippy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/test/test_itip.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoresqlpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/sql.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoretesttest_sqlpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/test/test_sql.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcommondatastoretestutilpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/common/datastore/test/util.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxweb2davresourcepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txweb2/dav/resource.py</a></li>
</ul>

<h3>Property Changed</h3>
<ul>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigration">CalendarServer/branches/users/cdaboo/pod2pod-migration/</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserscdaboopod2podmigration"></a>
<div class="propset"><h4>Property changes: CalendarServer/branches/users/cdaboo/pod2pod-migration</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnmergeinfo"></a>
<div class="modfile"><h4>Modified: svn:mergeinfo</h4></div>
<span class="cx">/CalendarServer/branches/config-separation:4379-4443
</span><span class="cx">/CalendarServer/branches/egg-info-351:4589-4625
</span><span class="cx">/CalendarServer/branches/generic-sqlstore:6167-6191
</span><span class="cx">/CalendarServer/branches/new-store:5594-5934
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile:5911-5935
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.2-dev:11972,12357-12358,12794,12814
</span><span class="cx">/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
</span><span class="cx">/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cross-pod-sharing:12038-12191
</span><span class="cx">/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
</span><span class="cx">/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
</span><span class="cx">/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
</span><span class="cx">/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
</span><span class="cx">/CalendarServer/branches/users/cdaboo/json:11622-11912
</span><span class="cx">/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
</span><span class="cx">/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
</span><span class="cx">/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
</span><span class="cx">/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pods:7297-7377
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycard:7227-7237
</span><span class="cx">/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
</span><span class="cx">/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
</span><span class="cx">/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
</span><span class="cx">/CalendarServer/branches/users/cdaboo/scheduling-queue-refresh:11783-12557
</span><span class="cx">/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
</span><span class="cx">/CalendarServer/branches/users/cdaboo/sharing-in-the-store:11935-12016
</span><span class="cx">/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
</span><span class="cx">/CalendarServer/branches/users/cdaboo/timezones:7443-7699
</span><span class="cx">/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
</span><span class="cx">/CalendarServer/branches/users/gaya/cleanrevisions:12152-12334
</span><span class="cx">/CalendarServer/branches/users/gaya/groupsharee2:13669-13773
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroupfixes:12120-12142
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
</span><span class="cx">/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
</span><span class="cx">/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
</span><span class="cx">/CalendarServer/branches/users/glyph/conn-limit:6574-6577
</span><span class="cx">/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
</span><span class="cx">/CalendarServer/branches/users/glyph/dalify:6932-7023
</span><span class="cx">/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
</span><span class="cx">/CalendarServer/branches/users/glyph/deploybuild:7563-7572
</span><span class="cx">/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
</span><span class="cx">/CalendarServer/branches/users/glyph/disable-quota:7718-7727
</span><span class="cx">/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
</span><span class="cx">/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
</span><span class="cx">/CalendarServer/branches/users/glyph/hang-fix:11465-11491
</span><span class="cx">/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
</span><span class="cx">/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
</span><span class="cx">/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
</span><span class="cx">/CalendarServer/branches/users/glyph/linux-tests:6893-6900
</span><span class="cx">/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
</span><span class="cx">/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
</span><span class="cx">/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
</span><span class="cx">/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
</span><span class="cx">/CalendarServer/branches/users/glyph/new-export:7444-7485
</span><span class="cx">/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle:7106-7155
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
</span><span class="cx">/CalendarServer/branches/users/glyph/other-html:8062-8091
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
</span><span class="cx">/CalendarServer/branches/users/glyph/q:9560-9688
</span><span class="cx">/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
</span><span class="cx">/CalendarServer/branches/users/glyph/quota:7604-7637
</span><span class="cx">/CalendarServer/branches/users/glyph/sendfdport:5388-5424
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
</span><span class="cx">/CalendarServer/branches/users/glyph/sharedpool:6490-6550
</span><span class="cx">/CalendarServer/branches/users/glyph/sharing-api:9192-9205
</span><span class="cx">/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
</span><span class="cx">/CalendarServer/branches/users/glyph/sql-store:5929-6073
</span><span class="cx">/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
</span><span class="cx">/CalendarServer/branches/users/glyph/subtransactions:7248-7258
</span><span class="cx">/CalendarServer/branches/users/glyph/table-alias:8651-8664
</span><span class="cx">/CalendarServer/branches/users/glyph/uidexport:7673-7676
</span><span class="cx">/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
</span><span class="cx">/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
</span><span class="cx">/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
</span><span class="cx">/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
</span><span class="cx">/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
</span><span class="cx">/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
</span><span class="cx">/CalendarServer/branches/users/sagen/applepush:8126-8184
</span><span class="cx">/CalendarServer/branches/users/sagen/inboxitems:7380-7381
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources:5032-5051
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who:12819-12860
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-2:12861-12898
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-3:12899-12913
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-4:12914-13157
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-5:13158-13163
</span><span class="cx">/CalendarServer/branches/users/sagen/newcua:13309-13327
</span><span class="cx">/CalendarServer/branches/users/sagen/newcua-1:13328-13330
</span><span class="cx">/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
</span><span class="cx">/CalendarServer/branches/users/sagen/recordtypes:13648-13656
</span><span class="cx">/CalendarServer/branches/users/sagen/recordtypes-2:13657
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
</span><span class="cx">/CalendarServer/branches/users/sagen/resources-2:5084-5093
</span><span class="cx">/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
</span><span class="cx">/CalendarServer/branches/users/wsanchez/transations:5515-5593
</span><span class="cx">   + /CalDAVTester/trunk:11193-11198
</span><span class="cx">/CalendarServer/branches/config-separation:4379-4443
</span><span class="cx">/CalendarServer/branches/egg-info-351:4589-4625
</span><span class="cx">/CalendarServer/branches/generic-sqlstore:6167-6191
</span><span class="cx">/CalendarServer/branches/new-store:5594-5934
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile:5911-5935
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.2-dev:11972,12357-12358,12794,12814
</span><span class="cx">/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
</span><span class="cx">/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cross-pod-sharing:12038-12191
</span><span class="cx">/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
</span><span class="cx">/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
</span><span class="cx">/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
</span><span class="cx">/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
</span><span class="cx">/CalendarServer/branches/users/cdaboo/json:11622-11912
</span><span class="cx">/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
</span><span class="cx">/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
</span><span class="cx">/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
</span><span class="cx">/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pods:7297-7377
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycard:7227-7237
</span><span class="cx">/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
</span><span class="cx">/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
</span><span class="cx">/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
</span><span class="cx">/CalendarServer/branches/users/cdaboo/scheduling-queue-refresh:11783-12557
</span><span class="cx">/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
</span><span class="cx">/CalendarServer/branches/users/cdaboo/sharing-in-the-store:11935-12016
</span><span class="cx">/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
</span><span class="cx">/CalendarServer/branches/users/cdaboo/timezones:7443-7699
</span><span class="cx">/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
</span><span class="cx">/CalendarServer/branches/users/gaya/cleanrevisions:12152-12334
</span><span class="cx">/CalendarServer/branches/users/gaya/groupsharee2:13669-13773
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroupfixes:12120-12142
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
</span><span class="cx">/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
</span><span class="cx">/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
</span><span class="cx">/CalendarServer/branches/users/glyph/conn-limit:6574-6577
</span><span class="cx">/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
</span><span class="cx">/CalendarServer/branches/users/glyph/dalify:6932-7023
</span><span class="cx">/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
</span><span class="cx">/CalendarServer/branches/users/glyph/deploybuild:7563-7572
</span><span class="cx">/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
</span><span class="cx">/CalendarServer/branches/users/glyph/disable-quota:7718-7727
</span><span class="cx">/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
</span><span class="cx">/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
</span><span class="cx">/CalendarServer/branches/users/glyph/hang-fix:11465-11491
</span><span class="cx">/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
</span><span class="cx">/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
</span><span class="cx">/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
</span><span class="cx">/CalendarServer/branches/users/glyph/linux-tests:6893-6900
</span><span class="cx">/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
</span><span class="cx">/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
</span><span class="cx">/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
</span><span class="cx">/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
</span><span class="cx">/CalendarServer/branches/users/glyph/new-export:7444-7485
</span><span class="cx">/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle:7106-7155
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
</span><span class="cx">/CalendarServer/branches/users/glyph/other-html:8062-8091
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
</span><span class="cx">/CalendarServer/branches/users/glyph/q:9560-9688
</span><span class="cx">/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
</span><span class="cx">/CalendarServer/branches/users/glyph/quota:7604-7637
</span><span class="cx">/CalendarServer/branches/users/glyph/sendfdport:5388-5424
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
</span><span class="cx">/CalendarServer/branches/users/glyph/sharedpool:6490-6550
</span><span class="cx">/CalendarServer/branches/users/glyph/sharing-api:9192-9205
</span><span class="cx">/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
</span><span class="cx">/CalendarServer/branches/users/glyph/sql-store:5929-6073
</span><span class="cx">/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
</span><span class="cx">/CalendarServer/branches/users/glyph/subtransactions:7248-7258
</span><span class="cx">/CalendarServer/branches/users/glyph/table-alias:8651-8664
</span><span class="cx">/CalendarServer/branches/users/glyph/uidexport:7673-7676
</span><span class="cx">/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
</span><span class="cx">/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
</span><span class="cx">/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
</span><span class="cx">/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
</span><span class="cx">/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
</span><span class="cx">/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
</span><span class="cx">/CalendarServer/branches/users/sagen/applepush:8126-8184
</span><span class="cx">/CalendarServer/branches/users/sagen/inboxitems:7380-7381
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources:5032-5051
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who:12819-12860
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-2:12861-12898
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-3:12899-12913
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-4:12914-13157
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-5:13158-13163
</span><span class="cx">/CalendarServer/branches/users/sagen/newcua:13309-13327
</span><span class="cx">/CalendarServer/branches/users/sagen/newcua-1:13328-13330
</span><span class="cx">/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
</span><span class="cx">/CalendarServer/branches/users/sagen/recordtypes:13648-13656
</span><span class="cx">/CalendarServer/branches/users/sagen/recordtypes-2:13657
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
</span><span class="cx">/CalendarServer/branches/users/sagen/resources-2:5084-5093
</span><span class="cx">/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
</span><span class="cx">/CalendarServer/branches/users/wsanchez/transations:5515-5593
</span><span class="cx">/CalendarServer/trunk:14338-14381
</span><a id="CalendarServerbranchesuserscdaboopod2podmigrationbin_buildsh"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/_build.sh (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/_build.sh        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/_build.sh        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -516,7 +516,7 @@
</span><span class="cx">     local p=&quot;${n}-${v}&quot;;
</span><span class="cx"> 
</span><span class="cx">     c_dependency -m &quot;a7f4e5e559a0e37b3ffc438c9456e425&quot; \
</span><del>-      &quot;Cyrus SASL&quot; &quot;${p}&quot; \
</del><ins>+      &quot;CyrusSASL&quot; &quot;${p}&quot; \
</ins><span class="cx">       &quot;ftp://ftp.cyrusimap.org/cyrus-sasl/${p}.tar.gz&quot; \
</span><span class="cx">       --disable-macos-framework;
</span><span class="cx">   fi;
</span><span class="lines">@@ -640,9 +640,9 @@
</span><span class="cx">   mkdir -p &quot;${py_ve_tools}/junk&quot;;
</span><span class="cx"> 
</span><span class="cx">   for pkg in             \
</span><del>-      setuptools-5.4.1   \
-      pip-6.0.6          \
-      virtualenv-1.11.6  \
</del><ins>+      setuptools-12.0.5  \
+      pip-6.0.8          \
+      virtualenv-12.0.7  \
</ins><span class="cx">   ; do
</span><span class="cx">       local    name=&quot;${pkg%-*}&quot;;
</span><span class="cx">       local version=&quot;${pkg#*-}&quot;;
</span><span class="lines">@@ -695,7 +695,6 @@
</span><span class="cx"> pip_download_and_install () {
</span><span class="cx">   &quot;${python}&quot; -m pip install                 \
</span><span class="cx">     --pre --allow-all-external               \
</span><del>-    --download-cache=&quot;${dev_home}/pip_cache&quot; \
</del><span class="cx">     --log-file=&quot;${dev_home}/pip.log&quot;         \
</span><span class="cx">     &quot;$@&quot;;
</span><span class="cx"> }
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationbinpackage"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/package (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/package        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/package        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> parse_options () {
</span><del>-  OPTIND=1;
</del><ins>+  local OPTIND=1;
</ins><span class="cx">   while getopts &quot;hFfn&quot; option; do
</span><span class="cx">     case &quot;${option}&quot; in
</span><span class="cx">       '?') usage; ;;
</span><span class="lines">@@ -93,37 +93,35 @@
</span><span class="cx"> 
</span><span class="cx">   parse_options &quot;$@&quot;;
</span><span class="cx"> 
</span><del>-  # Build the product
</del><ins>+  #
+  # Build everything
+  #
</ins><span class="cx"> 
</span><span class="cx">   if &quot;${clean}&quot;; then
</span><span class="cx">     develop_clean;
</span><span class="cx">   fi;
</span><span class="cx"> 
</span><del>-  develop;
-
</del><span class="cx">   install -d &quot;${destination}&quot;;
</span><ins>+  local destination=&quot;$(cd &quot;${destination}&quot; &amp;&amp; pwd)&quot;;
</ins><span class="cx"> 
</span><del>-  install -d &quot;${destination}/virtualenv&quot;;
-  cp -pR &quot;${py_virtualenv}/&quot; &quot;${destination}/virtualenv&quot;;
</del><ins>+  init_build;
</ins><span class="cx"> 
</span><del>-  # Make the python virtualenv relocatable
-  &quot;${bootstrap_python}&quot; -m virtualenv --relocatable &quot;${destination}/virtualenv&quot;;
</del><ins>+      dev_roots=&quot;${destination}/roots&quot;;
+  py_virtualenv=&quot;${destination}/virtualenv&quot;;
+      py_bindir=&quot;${py_virtualenv}/bin&quot;;
</ins><span class="cx"> 
</span><del>-  cp -pR &quot;${dev_roots}&quot;/*/ &quot;${destination}/virtualenv/&quot;;
</del><ins>+  c_dependencies;
+  py_dependencies;
</ins><span class="cx"> 
</span><span class="cx">   install -d &quot;${destination}/bin&quot;;
</span><del>-  install -m 555 &quot;${wd}/support/_run_from_ve&quot; &quot;${destination}/bin&quot;;
-  ln -fsv _run_from_ve &quot;${destination}/bin/caldavd&quot;;
</del><span class="cx"> 
</span><del>-  for script in $(
-    python -c 'import setup; print &quot;\n&quot;.join(&quot;calendarserver_{}&quot;.format(n) for n in setup.script_entry_points.keys())';
-  ); do
-    ln -fsv _run_from_ve &quot;${destination}/bin/${script}&quot;;
-  done;
</del><ins>+  (
+    cd &quot;${destination}/bin&quot; &amp;&amp; \
+      find ../virtualenv/bin \
+        '(' -name 'caldavd' -o -name 'calendarserver_*' -o -name 'python' ')' \
+        -exec ln -fs '{}' . ';';
+  );
</ins><span class="cx"> 
</span><del>-  # More here...
-  # Looks like we need to install calendarserver.
-  # Maybe should rebuild virtualenv insted of copying it.
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarserverdashboard_servicepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/dashboard_service.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/dashboard_service.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/dashboard_service.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -151,9 +151,9 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         if self.factory.store:
</span><del>-            queuer = self.factory.store.queuer
-            loads = queuer.workerPool.eachWorkerLoad()
-            level = queuer.workerPool.loadLevel()
</del><ins>+            pool = self.factory.store.pool
+            loads = pool.workerPool.eachWorkerLoad()
+            level = pool.workerPool.loadLevel()
</ins><span class="cx">         else:
</span><span class="cx">             loads = []
</span><span class="cx">             level = 0
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertapcaldavpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tap/caldav.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tap/caldav.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tap/caldav.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -193,7 +193,9 @@
</span><span class="cx">         &quot;PATH&quot;,
</span><span class="cx">         &quot;PYTHONPATH&quot;,
</span><span class="cx">         &quot;LD_LIBRARY_PATH&quot;,
</span><ins>+        &quot;LD_PRELOAD&quot;,
</ins><span class="cx">         &quot;DYLD_LIBRARY_PATH&quot;,
</span><ins>+        &quot;DYLD_INSERT_LIBRARIES&quot;,
</ins><span class="cx">     ]
</span><span class="cx"> 
</span><span class="cx">     optionalVars = [
</span><span class="lines">@@ -1262,6 +1264,7 @@
</span><span class="cx">             )
</span><span class="cx">             self._initJobQueue(pool)
</span><span class="cx">             store.queuer = store.queuer.transferProposalCallbacks(pool)
</span><ins>+            store.pool = pool
</ins><span class="cx">             pool.setServiceParent(result)
</span><span class="cx"> 
</span><span class="cx">             # Optionally set up mail retrieval
</span><span class="lines">@@ -1856,6 +1859,7 @@
</span><span class="cx"> 
</span><span class="cx">             # The master should not perform queued work
</span><span class="cx">             store.queuer = NonPerformingQueuer()
</span><ins>+            store.pool = pool
</ins><span class="cx"> 
</span><span class="cx">             controlSocket.addFactory(
</span><span class="cx">                 _QUEUE_ROUTE, pool.workerListenerFactory()
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolsagentpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/agent.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/agent.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/agent.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -34,7 +34,7 @@
</span><span class="cx"> from plistlib import readPlistFromString, writePlistToString
</span><span class="cx"> import socket
</span><span class="cx"> 
</span><del>-from twext.python.launchd import getLaunchDSocketFDs
</del><ins>+from twext.python.launchd import launchActivateSocket
</ins><span class="cx"> from twext.python.log import Logger
</span><span class="cx"> from twext.who.checker import HTTPDigestCredentialChecker
</span><span class="cx"> from twext.who.opendirectory import (
</span><span class="lines">@@ -153,8 +153,8 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     from twisted.internet import reactor
</span><span class="cx"> 
</span><del>-    sockets = getLaunchDSocketFDs()
-    fd = sockets[&quot;AgentSocket&quot;][0]
</del><ins>+    sockets = launchActivateSocket(&quot;AgentSocket&quot;)
+    fd = sockets[0]
</ins><span class="cx"> 
</span><span class="cx">     family = socket.AF_INET
</span><span class="cx">     endpoint = AdoptedStreamServerEndpoint(reactor, fd, family)
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolsdkimtoolpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/dkimtool.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/dkimtool.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/dkimtool.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -15,6 +15,7 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><ins>+import os
</ins><span class="cx"> import sys
</span><span class="cx"> from Crypto.PublicKey import RSA
</span><span class="cx"> from StringIO import StringIO
</span><span class="lines">@@ -24,9 +25,7 @@
</span><span class="cx"> from twisted.python.usage import Options
</span><span class="cx"> 
</span><span class="cx"> from twext.python.log import Logger, LogLevel, StandardIOObserver
</span><del>-from txweb2.client.http import ClientRequest
</del><span class="cx"> from txweb2.http_headers import Headers
</span><del>-from txweb2.stream import MemoryStream
</del><span class="cx"> 
</span><span class="cx"> from txdav.caldav.datastore.scheduling.ischedule.dkim import RSA256, DKIMRequest, \
</span><span class="cx">     PublicKeyLookup, DKIMVerifier, DKIMVerificationError
</span><span class="lines">@@ -114,19 +113,17 @@
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def _doVerify(options):
</span><span class="cx">     # Parse the HTTP file
</span><del>-    verify = open(options[&quot;verify&quot;]).read()
-    method, uri, headers, stream = _parseRequest(verify)
</del><ins>+    verify = open(os.path.expanduser(options[&quot;verify&quot;])).read()
+    _method, _uri, headers, body = _parseRequest(verify)
</ins><span class="cx"> 
</span><del>-    request = ClientRequest(method, uri, headers, stream)
-
</del><span class="cx">     # Check for local public key
</span><span class="cx">     if options[&quot;pub-key&quot;]:
</span><del>-        PublicKeyLookup_File.pubkeyfile = options[&quot;pub-key&quot;]
</del><ins>+        PublicKeyLookup_File.pubkeyfile = os.path.expanduser(options[&quot;pub-key&quot;])
</ins><span class="cx">         lookup = (PublicKeyLookup_File,)
</span><span class="cx">     else:
</span><span class="cx">         lookup = None
</span><span class="cx"> 
</span><del>-    dkim = DKIMVerifier(request, lookup)
</del><ins>+    dkim = DKIMVerifier(headers, body, lookup)
</ins><span class="cx">     if options[&quot;fake-time&quot;]:
</span><span class="cx">         dkim.time = 0
</span><span class="cx"> 
</span><span class="lines">@@ -162,7 +159,7 @@
</span><span class="cx">         name, value = hdr.split(':', 1)
</span><span class="cx">         headers.addRawHeader(name, value.strip())
</span><span class="cx"> 
</span><del>-    stream = MemoryStream(&quot;&quot;.join(body))
</del><ins>+    stream = &quot;&quot;.join(body)
</ins><span class="cx"> 
</span><span class="cx">     return method, uri, headers, stream
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolstesttest_calverifypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/test/test_calverify.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/test/test_calverify.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/test/test_calverify.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -2507,8 +2507,8 @@
</span><span class="cx"> UID:INVITE_VALID_ORGANIZER_ICS
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> SUMMARY:INVITE_VALID_ORGANIZER_ICS
</span><span class="lines">@@ -2524,8 +2524,8 @@
</span><span class="cx"> UID:INVITE_VALID_ORGANIZER_ICS
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> SUMMARY:INVITE_VALID_ORGANIZER_ICS
</span><span class="lines">@@ -2541,8 +2541,8 @@
</span><span class="cx"> UID:INVITE_VALID_ORGANIZER_ICS
</span><span class="cx"> DTSTART:%(now_fwd11)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="lines">@@ -2560,8 +2560,8 @@
</span><span class="cx"> UID:INVITE_VALID_ORGANIZER_ICS
</span><span class="cx"> DTSTART:%(now_fwd11)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="lines">@@ -2579,8 +2579,8 @@
</span><span class="cx"> UID:%(uid)s
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
</span><span class="cx"> RRULE:FREQ=DAILY;UNTIL=%(now_fwd11_1)s
</span><span class="lines">@@ -2598,8 +2598,8 @@
</span><span class="cx"> UID:%(uid)s
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
</span><span class="cx"> RRULE:FREQ=DAILY;UNTIL=%(now_fwd11_1)s
</span><span class="lines">@@ -2617,8 +2617,8 @@
</span><span class="cx"> UID:VALID_ORGANIZER_OVERRIDE_ICS
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> SUMMARY:INVITE_VALID_ORGANIZER_ICS
</span><span class="lines">@@ -2628,8 +2628,8 @@
</span><span class="cx"> RECURRENCE-ID:%(now_fwd11)s
</span><span class="cx"> DTSTART:%(now_fwd11)s
</span><span class="cx"> DURATION:PT2H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> SUMMARY:INVITE_VALID_ORGANIZER_ICS
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationrequirementsdevtxt"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-dev.txt (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-dev.txt        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-dev.txt        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -8,4 +8,4 @@
</span><span class="cx"> q
</span><span class="cx"> tl.eggdeps
</span><span class="cx"> --editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVClientLibrary/trunk@13420#egg=CalDAVClientLibrary
</span><del>---editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVTester/trunk@14306#egg=CalDAVTester
</del><ins>+--editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVTester/trunk@14377#egg=CalDAVTester
</ins></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationrequirementsstabletxt"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-stable.txt (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-stable.txt        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-stable.txt        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -20,7 +20,7 @@
</span><span class="cx"> 
</span><span class="cx"> --editable .  # calendarserver
</span><span class="cx"> 
</span><del>-    zope.interface==4.1.1
</del><ins>+    zope.interface==4.1.2
</ins><span class="cx"> 
</span><span class="cx">     Twisted==14.0.2
</span><span class="cx">         #zope.interface
</span><span class="lines">@@ -30,19 +30,19 @@
</span><span class="cx">         #   added to calendarserver.
</span><span class="cx">         #pyOpenSSL
</span><span class="cx">         service_identity==14.0.0
</span><del>-            characteristic==14.0.0
</del><ins>+            characteristic==14.3.0
</ins><span class="cx">             pyasn1==0.1.7
</span><span class="cx">             pyasn1-modules==0.0.5
</span><span class="cx">             #pyOpenSSL
</span><span class="cx">         pycrypto==2.6.1
</span><span class="cx"> 
</span><del>-    --editable svn+http://svn.calendarserver.org/repository/calendarserver/twext/trunk@14327#egg=twextpy
</del><ins>+    --editable svn+http://svn.calendarserver.org/repository/calendarserver/twext/trunk@14351#egg=twextpy
</ins><span class="cx">         cffi==0.8.6
</span><span class="cx">             pycparser==2.10
</span><span class="cx">         #twisted
</span><span class="cx"> 
</span><span class="cx">         # [LDAP] extra
</span><del>-            python-ldap==2.4.18
</del><ins>+            python-ldap==2.4.19
</ins><span class="cx">                 #setuptools
</span><span class="cx"> 
</span><span class="cx">         # [DAL] extra
</span><span class="lines">@@ -55,14 +55,14 @@
</span><span class="cx">             PyGreSQL==4.1.1
</span><span class="cx"> 
</span><span class="cx">         # [Oracle] extra
</span><del>-            #cx_Oracle  # Not in PyPI
</del><ins>+            #cx_Oracle==5.1.3  # Not in PyPI
</ins><span class="cx"> 
</span><span class="cx">     pyOpenSSL==0.14
</span><del>-        cryptography==0.7.1
</del><ins>+        cryptography==0.7.2
</ins><span class="cx">             #pyasn1
</span><span class="cx">             #cffi
</span><span class="cx">             enum34==1.0.4
</span><del>-            setuptools==11.3.1
</del><ins>+            setuptools==12.0.5
</ins><span class="cx">             #six
</span><span class="cx">         six==1.9.0
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationsupportApplemake"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/support/Apple.make (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/support/Apple.make        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/support/Apple.make        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx">         @# Use --system-site-packages so that we use the packages provided by the
</span><span class="cx">         @# OS, such as PyObjC.
</span><span class="cx">         @# Use --always-copy because we want copies of, not links to, the system
</span><del>-        @# python, as Server.app is an indenpendant product train.
</del><ins>+        @# python, as Server.app is an independent product train.
</ins><span class="cx">         @#
</span><span class="cx">         @echo &quot;Creating virtual environment...&quot;;
</span><span class="cx">         $(_v) $(RMDIR) &quot;$(DSTROOT)$(CS_VIRTUALENV)&quot;;
</span><span class="lines">@@ -138,19 +138,6 @@
</span><span class="cx">         @echo &quot;Putting comments into empty files...&quot;;
</span><span class="cx">         $(_v) find &quot;$(DSTROOT)$(CS_VIRTUALENV)&quot; -type f -size 0 -name &quot;*.py&quot; -exec sh -c 'printf &quot;# empty\n&quot; &gt; {}' &quot;;&quot;;
</span><span class="cx">         $(_v) find &quot;$(DSTROOT)$(CS_VIRTUALENV)&quot; -type f -size 0 -name &quot;*.h&quot; -exec sh -c 'printf &quot;/* empty */\n&quot; &gt; {}' &quot;;&quot;;
</span><del>-        @# This is obsoleted by using --always-copy when we create the virtualenv:
-        @# @echo &quot;Replacing symbolic links...&quot;;
-        @# $(_v) find &quot;$(DSTROOT)$(CS_VIRTUALENV)&quot; -type l |                       \
-        @#           while read link; do                                           \
-        @#               target=&quot;$$(readlink &quot;$${link}&quot;)&quot;;                         \
-        @#               if [ &quot;$$(echo $${target} | cut -f 1 -d /)&quot; == &quot;&quot; ]; then  \
-        @#                   rm -fv &quot;$${link}&quot;;                                    \
-        @#                   cp -aLfv &quot;$${target}&quot; &quot;$${link}&quot; || {                 \
-        @#                       rm -rfv &quot;$${link}&quot;;                               \
-        @#                       ln -sfv &quot;$${target}&quot; &quot;$${link}&quot;;                  \
-        @#                   }                                                     \
-        @#               fi;                                                       \
-        @#           done;
</del><span class="cx"> 
</span><span class="cx"> install:: install-config
</span><span class="cx"> install-config::
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/resource.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/resource.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/resource.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -776,7 +776,7 @@
</span><span class="cx">             else:
</span><span class="cx">                 home = self._newStoreObject.ownerHome()
</span><span class="cx">             principal = (yield self.principalForUID(home.uid()))
</span><del>-            returnValue(element.HRef(principal.principalURL()))
</del><ins>+            returnValue(element.HRef(principal.principalURL()) if principal else None)
</ins><span class="cx">         else:
</span><span class="cx">             parent = (yield self.locateParent(request, request.urlForResource(self)))
</span><span class="cx">         if parent and isinstance(parent, CalDAVResource):
</span><span class="lines">@@ -1162,7 +1162,8 @@
</span><span class="cx">         sharedParent = None
</span><span class="cx">         if self.isShareeResource():
</span><span class="cx">             # A sharee collection's quota root is the resource owner's root
</span><del>-            sharedParent = (yield request.locateResource(parentForURL(self._share_url)))
</del><ins>+            if self._share_url:
+                sharedParent = (yield request.locateResource(parentForURL(self._share_url)))
</ins><span class="cx">         else:
</span><span class="cx">             parent = (yield self.locateParent(request, request.urlForResource(self)))
</span><span class="cx">             if isCalendarCollectionResource(parent) or isAddressBookCollectionResource(parent):
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavsharingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/sharing.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/sharing.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/sharing.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -424,8 +424,7 @@
</span><span class="cx">         if principal:
</span><span class="cx">             if request:
</span><span class="cx">                 ownerPrincipal = (yield self.ownerPrincipal(request))
</span><del>-                owner = ownerPrincipal.principalURL()
-                if owner == principal.principalURL():
</del><ins>+                if ownerPrincipal is None or ownerPrincipal.principalURL() == principal.principalURL():
</ins><span class="cx">                     returnValue(None)
</span><span class="cx">             returnValue(principal.principalURL())
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavstdconfigpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/stdconfig.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/stdconfig.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/stdconfig.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -15,30 +15,27 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> 
</span><ins>+import copy
</ins><span class="cx"> import os
</span><del>-import copy
</del><ins>+from plistlib import PlistParser  # @UnresolvedImport
</ins><span class="cx"> import re
</span><span class="cx"> from socket import getfqdn, gethostbyname
</span><span class="cx"> 
</span><ins>+from calendarserver.push.util import getAPNTopicFromCertificate
+from twext.python.log import Logger, InvalidLogLevelError, LogLevel
+from twisted.python.filepath import FilePath
</ins><span class="cx"> from twisted.python.runtime import platform
</span><del>-
-from plistlib import PlistParser  # @UnresolvedImport
-from twext.python.log import Logger, InvalidLogLevelError, LogLevel
-from txweb2.dav.resource import TwistedACLInheritable
-
-from txdav.xml import element as davxml
-
</del><span class="cx"> from twistedcaldav import caldavxml, customxml, carddavxml, mkcolxml
</span><ins>+from twistedcaldav import ical
</ins><span class="cx"> from twistedcaldav.config import ConfigProvider, ConfigurationError, ConfigDict
</span><span class="cx"> from twistedcaldav.config import config, mergeData, fullServerPath
</span><del>-from twistedcaldav.util import getPasswordFromKeychain
</del><ins>+from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
</ins><span class="cx"> from twistedcaldav.util import KeychainAccessError, KeychainPasswordNotFound
</span><span class="cx"> from twistedcaldav.util import computeProcessCount
</span><del>-from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
</del><ins>+from twistedcaldav.util import getPasswordFromKeychain
+from txdav.xml import element as davxml
+from txweb2.dav.resource import TwistedACLInheritable
</ins><span class="cx"> 
</span><del>-from calendarserver.push.util import getAPNTopicFromCertificate
-from twistedcaldav import ical
-
</del><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -1363,8 +1360,18 @@
</span><span class="cx">             if param not in DEFAULT_RESOURCE_PARAMS[configDict.ResourceService.type]:
</span><span class="cx">                 del configDict.ResourceService.params[param]
</span><span class="cx"> 
</span><ins>+    # Upgrading resources.xml must be done prior to using the store/directory
+    if configDict.ResourceService.Enabled and configDict.ResourceService.type == &quot;xml&quot;:
+        resourcesFileName = configDict.ResourceService.params.xmlFile
+        if resourcesFileName[0] not in (&quot;/&quot;, &quot;.&quot;):
+            resourcesFileName = os.path.join(configDict.DataRoot, resourcesFileName)
+        resourcesFilePath = FilePath(resourcesFileName)
+        if resourcesFilePath.exists():
+            from twistedcaldav.upgrade import upgradeResourcesXML
+            upgradeResourcesXML(resourcesFilePath)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def _preUpdateDirectoryAddressBookBackingDirectoryService(configDict, items, reloading=False):
</span><span class="cx">     #
</span><span class="cx">     # Special handling for directory address book configs
</span><span class="lines">@@ -1402,8 +1409,18 @@
</span><span class="cx">                 log.warn(&quot;Parameter %s is not supported by service %s&quot; % (param, configDict.AugmentService.type))
</span><span class="cx">                 del configDict.AugmentService.params[param]
</span><span class="cx"> 
</span><ins>+    # Upgrading augments.xml must be done prior to using the store/directory
+    if configDict.AugmentService.type == &quot;twistedcaldav.directory.augment.AugmentXMLDB&quot;:
+        for fileName in configDict.AugmentService.params.xmlFiles:
+            if fileName[0] not in (&quot;/&quot;, &quot;.&quot;):
+                fileName = os.path.join(configDict.DataRoot, fileName)
+            filePath = FilePath(fileName)
+            if filePath.exists():
+                from twistedcaldav.upgrade import upgradeAugmentsXML
+                upgradeAugmentsXML(filePath)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def _updateACLs(configDict, reloading=False):
</span><span class="cx">     #
</span><span class="cx">     # Base resource ACLs
</span><span class="lines">@@ -1714,6 +1731,7 @@
</span><span class="cx">     _updateCompliance,
</span><span class="cx"> )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def _cleanup(configDict, defaultDict):
</span><span class="cx">     cleanDict = copy.deepcopy(configDict)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavstorebridgepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/storebridge.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/storebridge.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/storebridge.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -301,7 +301,7 @@
</span><span class="cx"> 
</span><span class="cx">     def owner_url(self):
</span><span class="cx">         if self.isShareeResource():
</span><del>-            return joinURL(self._share_url, &quot;/&quot;)
</del><ins>+            return joinURL(self._share_url, &quot;/&quot;) if self._share_url else &quot;&quot;
</ins><span class="cx">         else:
</span><span class="cx">             return self.url()
</span><span class="cx"> 
</span><span class="lines">@@ -2982,6 +2982,16 @@
</span><span class="cx">         if not self.exists():
</span><span class="cx">             raise HTTPError(NOT_FOUND)
</span><span class="cx"> 
</span><ins>+        # Do schedule tag check
+        try:
+            self.validIfScheduleMatch(request)
+        except HTTPError as e:
+            if e.response.code == responsecode.PRECONDITION_FAILED:
+                response = yield self._processPrefer(request, e.response)
+                raise HTTPError(response)
+            else:
+                raise
+
</ins><span class="cx">         # Split point is in the rid query parameter
</span><span class="cx">         rid = request.args.get(&quot;rid&quot;)
</span><span class="cx">         if rid is None:
</span><span class="lines">@@ -3007,11 +3017,11 @@
</span><span class="cx"> 
</span><span class="cx">         try:
</span><span class="cx">             otherStoreObject = yield self._newStoreObject.splitAt(rid, pastUID)
</span><del>-        except InvalidSplit:
</del><ins>+        except InvalidSplit as e:
</ins><span class="cx">             raise HTTPError(ErrorResponse(
</span><span class="cx">                 FORBIDDEN,
</span><del>-                (calendarserver_namespace, &quot;invalid-split&quot;,),
-                &quot;The rid parameter in the request-URI contains an invalid value&quot;,
</del><ins>+                (calendarserver_namespace, &quot;valid-split&quot;,),
+                str(e),
</ins><span class="cx">             ))
</span><span class="cx"> 
</span><span class="cx">         other = yield request.locateChildResource(self._parentResource, otherStoreObject.name())
</span><span class="lines">@@ -3029,6 +3039,8 @@
</span><span class="cx">                 raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, &quot;Cannot generate requested data type&quot;))
</span><span class="cx">             etag1 = yield self.etag()
</span><span class="cx">             etag2 = yield other.etag()
</span><ins>+            scheduletag1 = self.scheduleTag
+            scheduletag2 = otherStoreObject.scheduleTag
</ins><span class="cx">             cal1 = yield self.component()
</span><span class="cx">             cal2 = yield other.component()
</span><span class="cx"> 
</span><span class="lines">@@ -3038,6 +3050,7 @@
</span><span class="cx">                     davxml.PropertyStatus(
</span><span class="cx">                         davxml.PropertyContainer(
</span><span class="cx">                             davxml.GETETag.fromString(etag1.generate()),
</span><ins>+                            caldavxml.ScheduleTag.fromString(scheduletag1),
</ins><span class="cx">                             caldavxml.CalendarData.fromComponent(cal1, accepted_type),
</span><span class="cx">                         ),
</span><span class="cx">                         davxml.Status.fromResponseCode(OK),
</span><span class="lines">@@ -3048,6 +3061,7 @@
</span><span class="cx">                     davxml.PropertyStatus(
</span><span class="cx">                         davxml.PropertyContainer(
</span><span class="cx">                             davxml.GETETag.fromString(etag2.generate()),
</span><ins>+                            caldavxml.ScheduleTag.fromString(scheduletag2),
</ins><span class="cx">                             caldavxml.CalendarData.fromComponent(cal2, accepted_type),
</span><span class="cx">                         ),
</span><span class="cx">                         davxml.Status.fromResponseCode(OK),
</span><span class="lines">@@ -3920,15 +3934,21 @@
</span><span class="cx"> 
</span><span class="cx">         if jsondata[&quot;notification-type&quot;] == &quot;invite-notification&quot;:
</span><span class="cx">             ownerPrincipal = yield self.principalForUID(jsondata[&quot;owner&quot;])
</span><del>-            ownerCN = ownerPrincipal.displayName()
-            ownerHomeURL = ownerPrincipal.calendarHomeURLs()[0] if jsondata[&quot;shared-type&quot;] == &quot;calendar&quot; else ownerPrincipal.addressBookHomeURLs()[0]
-
-            # FIXME:  use urn:uuid always?
-            if jsondata[&quot;shared-type&quot;] == &quot;calendar&quot;:
-                owner = ownerPrincipal.principalURL()
</del><ins>+            if ownerPrincipal is None:
+                ownerCN = &quot;&quot;
+                ownerCollectionURL = &quot;&quot;
+                owner = &quot;urn:x-uid:&quot; + jsondata[&quot;owner&quot;]
</ins><span class="cx">             else:
</span><del>-                owner = &quot;urn:x-uid:&quot; + ownerPrincipal.principalUID()
</del><ins>+                ownerCN = ownerPrincipal.displayName()
+                ownerHomeURL = ownerPrincipal.calendarHomeURLs()[0] if jsondata[&quot;shared-type&quot;] == &quot;calendar&quot; else ownerPrincipal.addressBookHomeURLs()[0]
+                ownerCollectionURL = urljoin(ownerHomeURL, jsondata[&quot;ownerName&quot;])
</ins><span class="cx"> 
</span><ins>+                # FIXME:  use urn:uuid always?
+                if jsondata[&quot;shared-type&quot;] == &quot;calendar&quot;:
+                    owner = ownerPrincipal.principalURL()
+                else:
+                    owner = &quot;urn:x-uid:&quot; + ownerPrincipal.principalUID()
+
</ins><span class="cx">             shareePrincipal = yield self.principalForUID(jsondata[&quot;sharee&quot;])
</span><span class="cx"> 
</span><span class="cx">             if &quot;supported-components&quot; in jsondata:
</span><span class="lines">@@ -3952,7 +3972,7 @@
</span><span class="cx">                     invitationBindStatusToXMLMap[jsondata[&quot;status&quot;]](),
</span><span class="cx">                     customxml.InviteAccess(invitationBindModeToXMLMap[jsondata[&quot;access&quot;]]()),
</span><span class="cx">                     customxml.HostURL(
</span><del>-                        element.HRef.fromString(urljoin(ownerHomeURL, jsondata[&quot;ownerName&quot;])),
</del><ins>+                        element.HRef.fromString(ownerCollectionURL),
</ins><span class="cx">                     ),
</span><span class="cx">                     customxml.Organizer(
</span><span class="cx">                         element.HRef.fromString(owner),
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavtesttest_sharingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/test/test_sharing.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/test/test_sharing.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/test/test_sharing.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -102,6 +102,66 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><ins>+    def _doPROPFINDHome(self, resultcode=responsecode.MULTI_STATUS):
+        body = &quot;&quot;&quot;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:add-member/&gt;
+    &lt;C:allowed-sharing-modes xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;D:autoprovisioned xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;E:bulk-requests xmlns:E=&quot;http://me.com/_namespace/&quot;/&gt;
+    &lt;D:calendar-color xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;B:calendar-description xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:calendar-free-busy-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;D:calendar-order xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;B:calendar-timezone xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-privilege-set/&gt;
+    &lt;B:default-alarm-vevent-date xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:default-alarm-vevent-datetime xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:getctag xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:invite xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;D:language-code xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;D:location-code xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;A:owner/&gt;
+    &lt;C:pre-publish-url xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:publish-url xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:push-transports xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:pushkey xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:quota-available-bytes/&gt;
+    &lt;A:quota-used-bytes/&gt;
+    &lt;D:refreshrate xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;A:resourcetype/&gt;
+    &lt;B:schedule-calendar-transp xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:schedule-default-calendar-URL xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:source xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-alarms xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-attachments xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-todos xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:supported-calendar-component-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:supported-calendar-component-sets xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+    &lt;A:sync-token/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
+&quot;&quot;&quot;
+        authPrincipal = yield self.actualRoot.findPrincipalForAuthID(&quot;user02&quot;)
+        request = SimpleStoreRequest(self, &quot;PROPFIND&quot;, &quot;/calendars/__uids__/user02/&quot;, content=body, authPrincipal=authPrincipal)
+        request.headers.setHeader(&quot;content-type&quot;, MimeType(&quot;text&quot;, &quot;xml&quot;))
+        request.headers.setHeader(&quot;depth&quot;, &quot;1&quot;)
+        response = yield self.send(request)
+        response = IResponse(response)
+        self.assertEqual(response.code, resultcode)
+
+        if response.stream:
+            data = yield allDataFromStream(response.stream)
+            returnValue(data)
+        else:
+            returnValue(None)
+
+
+    @inlineCallbacks
</ins><span class="cx">     def _getResource(self):
</span><span class="cx">         request = SimpleStoreRequest(self, &quot;GET&quot;, &quot;/calendars/__uids__/user01/calendar/&quot;)
</span><span class="cx">         resource = yield request.locateResource(&quot;/calendars/__uids__/user01/calendar/&quot;)
</span><span class="lines">@@ -1234,6 +1294,9 @@
</span><span class="cx">         record = yield self.userRecordWithShortName(&quot;user01&quot;)
</span><span class="cx">         yield self.changeRecord(record, self.directory.fieldName.hasCalendars, False)
</span><span class="cx"> 
</span><ins>+        data = yield self._doPROPFINDHome()
+        self.assertTrue(data is not None)
+
</ins><span class="cx">         resource = (yield self._getResourceSharer(href))
</span><span class="cx">         propInvite = yield resource.inviteProperty(None)
</span><span class="cx">         self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite(
</span><span class="lines">@@ -1297,6 +1360,9 @@
</span><span class="cx">         yield self.directory.removeRecords(((yield self.userUIDFromShortName(&quot;user01&quot;)),))
</span><span class="cx">         self.assertTrue((yield self.userUIDFromShortName(&quot;user01&quot;)) is None)
</span><span class="cx"> 
</span><ins>+        data = yield self._doPROPFINDHome()
+        self.assertTrue(data is not None)
+
</ins><span class="cx">         resource = (yield self._getResourceSharer(href))
</span><span class="cx">         propInvite = yield resource.inviteProperty(None)
</span><span class="cx">         self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite(
</span><span class="lines">@@ -1314,6 +1380,33 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><ins>+    def test_shareeNotificationWithMissingSharer(self):
+
+        yield self.resource.upgradeToShare()
+
+        yield self._doPOST(&quot;&quot;&quot;&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
+            &lt;CS:share xmlns:D=&quot;DAV:&quot; xmlns:CS=&quot;http://calendarserver.org/ns/&quot;&gt;
+                &lt;CS:set&gt;
+                    &lt;D:href&gt;mailto:user02@example.com&lt;/D:href&gt;
+                    &lt;CS:summary&gt;My Shared Calendar&lt;/CS:summary&gt;
+                    &lt;CS:read-write/&gt;
+                &lt;/CS:set&gt;
+            &lt;/CS:share&gt;
+            &quot;&quot;&quot;)
+
+        yield self.directory.removeRecords(((yield self.userUIDFromShortName(&quot;user01&quot;)),))
+        self.assertTrue((yield self.userUIDFromShortName(&quot;user01&quot;)) is None)
+
+        request = SimpleStoreRequest(self, &quot;GET&quot;, &quot;/calendars/__uids__/user02/notification/&quot;)
+        notification = yield request.locateResource(&quot;/calendars/__uids__/user02/notification/&quot;)
+        names = yield notification.listChildren()
+        self.assertEqual(len(names), 1)
+        note_child = yield notification.getChild(names[0])
+        note = yield note_child.text()
+        self.assertTrue(isinstance(note, str))
+
+
+    @inlineCallbacks
</ins><span class="cx">     def test_hideInvalidSharers(self):
</span><span class="cx"> 
</span><span class="cx">         yield self.resource.upgradeToShare()
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavupgradepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/upgrade.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/upgrade.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/upgrade.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -758,22 +758,6 @@
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def upgradeData(config, directory):
</span><span class="cx"> 
</span><del>-    if config.ResourceService.Enabled:
-        resourcesFileName = config.ResourceService.params.xmlFile
-        if resourcesFileName[0] not in (&quot;/&quot;, &quot;.&quot;):
-            resourcesFileName = os.path.join(config.DataRoot, resourcesFileName)
-        resourcesFilePath = FilePath(resourcesFileName)
-        if resourcesFilePath.exists():
-            upgradeResourcesXML(resourcesFilePath)
-
-    if config.AugmentService.type == &quot;twistedcaldav.directory.augment.AugmentXMLDB&quot;:
-        for fileName in config.AugmentService.params.xmlFiles:
-            if fileName[0] not in (&quot;/&quot;, &quot;.&quot;):
-                fileName = os.path.join(config.DataRoot, fileName)
-            filePath = FilePath(fileName)
-            if filePath.exists():
-                upgradeAugmentsXML(filePath)
-
</del><span class="cx">     triggerPath = os.path.join(config.ServerRoot, TRIGGER_FILE)
</span><span class="cx">     if os.path.exists(triggerPath):
</span><span class="cx">         try:
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduledkimpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/dkim.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/dkim.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/dkim.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -294,8 +294,16 @@
</span><span class="cx"> 
</span><span class="cx">     @staticmethod
</span><span class="cx">     def canonicalizeBody(data):
</span><del>-        if not data.endswith(&quot;\r\n&quot;):
-            data += &quot;\r\n&quot;
</del><ins>+        &quot;&quot;&quot;
+        DKIM simple body canonicalization: remove empty lines at the end
+        and ensure it ends with one \r\n.
+
+        @param data: data to canonicalize
+        @type data: L{str}
+        &quot;&quot;&quot;
+        while data.endswith(&quot;\r\n&quot;):
+            data = data[:-2]
+        data += &quot;\r\n&quot;
</ins><span class="cx">         return data
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduleresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/resource.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/resource.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/resource.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -179,31 +179,35 @@
</span><span class="cx">                     &quot;version&quot;: &quot;2.0&quot;,
</span><span class="cx">                 })
</span><span class="cx">             )
</span><del>-        result = ischedulexml.QueryResult(
</del><span class="cx"> 
</span><del>-            ischedulexml.Capabilities(
-                ischedulexml.Version.fromString(config.Scheduling.iSchedule.SerialNumber),
-                ischedulexml.Versions(
-                    ischedulexml.Version.fromString(&quot;1.0&quot;),
-                ),
-                ischedulexml.SchedulingMessages(
</del><ins>+        componentTypes = []
+        from twistedcaldav.ical import allowedSchedulingComponents
+        for name in allowedSchedulingComponents:
+            if name == &quot;VFREEBUSY&quot;:
+                componentTypes.append(
</ins><span class="cx">                     ischedulexml.Component(
</span><span class="cx">                         ischedulexml.Method(name=&quot;REQUEST&quot;),
</span><del>-                        ischedulexml.Method(name=&quot;CANCEL&quot;),
-                        ischedulexml.Method(name=&quot;REPLY&quot;),
-                        name=&quot;VEVENT&quot;
-                    ),
</del><ins>+                        name=name
+                    )
+                )
+            else:
+                componentTypes.append(
</ins><span class="cx">                     ischedulexml.Component(
</span><span class="cx">                         ischedulexml.Method(name=&quot;REQUEST&quot;),
</span><span class="cx">                         ischedulexml.Method(name=&quot;CANCEL&quot;),
</span><span class="cx">                         ischedulexml.Method(name=&quot;REPLY&quot;),
</span><del>-                        name=&quot;VTODO&quot;
-                    ),
-                    ischedulexml.Component(
-                        ischedulexml.Method(name=&quot;REQUEST&quot;),
-                        name=&quot;VFREEBUSY&quot;
-                    ),
</del><ins>+                        name=name
+                    )
+                )
+
+        result = ischedulexml.QueryResult(
+
+            ischedulexml.Capabilities(
+                ischedulexml.Version.fromString(config.Scheduling.iSchedule.SerialNumber),
+                ischedulexml.Versions(
+                    ischedulexml.Version.fromString(&quot;1.0&quot;),
</ins><span class="cx">                 ),
</span><ins>+                ischedulexml.SchedulingMessages(*componentTypes),
</ins><span class="cx">                 ischedulexml.CalendarDataTypes(*dataTypes),
</span><span class="cx">                 ischedulexml.Attachments(
</span><span class="cx">                     ischedulexml.External(),
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduletesttest_dkimpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -389,6 +389,33 @@
</span><span class="cx">             self.assertEqual(extracted, result.replace(&quot;\n&quot;, &quot;\r\n&quot;))
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    def test_canonicalize_body(self):
+        &quot;&quot;&quot;
+        L{DKIMUtils.canonicalizeBody} correctly canonicalizes bodies.
+        &quot;&quot;&quot;
+
+        data = (
+            (
+                &quot;&quot;&quot;Simple&quot;&quot;&quot;,
+                &quot;&quot;&quot;Simple\n&quot;&quot;&quot;,
+            ),
+            (
+                &quot;&quot;&quot;Simple\n&quot;&quot;&quot;,
+                &quot;&quot;&quot;Simple\n&quot;&quot;&quot;,
+            ),
+            (
+                &quot;&quot;&quot;Simple\n\n&quot;&quot;&quot;,
+                &quot;&quot;&quot;Simple\n&quot;&quot;&quot;,
+            ),
+        )
+
+        for text, result in data:
+            self.assertEqual(
+                DKIMUtils.canonicalizeBody(text.replace(&quot;\n&quot;, &quot;\r\n&quot;)),
+                result.replace(&quot;\n&quot;, &quot;\r\n&quot;),
+            )
+
+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_locate_public_key(self):
</span><span class="cx">         &quot;&quot;&quot;
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingitippy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/itip.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/itip.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/itip.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -358,6 +358,40 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @staticmethod
</span><ins>+    def processPollStatus(itip_message, calendar, recipient):
+        &quot;&quot;&quot;
+        Process a METHOD=POLLSTATUS.
+
+        @param itip_message: the iTIP message to process.
+        @type itip_message: L{Component}
+        @param calendar: the calendar object to apply the POLLSTATUS to
+        @type calendar: L{Component}
+
+        @return: the update calendar component or C{None}
+        &quot;&quot;&quot;
+
+        # Check sequencing
+        if not iTipProcessing.sequenceComparison(itip_message, calendar):
+            # Ignore out of sequence message
+            return None
+
+        calendar_master = calendar.masterComponent()
+        itip_master = itip_message.masterComponent()
+
+        # Remove each VVOTER in the original (except for the recipients)
+        for component in tuple(calendar_master.subcomponents()):
+            if component.name() == &quot;VVOTER&quot; and component.propertyValue(&quot;VOTER&quot;) != recipient:
+                calendar_master.removeComponent(component)
+
+        # Add each VVOTER in the iTip message
+        for component in itip_master.subcomponents():
+            if component.name() == &quot;VVOTER&quot; and component.propertyValue(&quot;VOTER&quot;) != recipient:
+                calendar_master.addComponent(component.duplicate())
+
+        return calendar
+
+
+    @staticmethod
</ins><span class="cx">     def processReply(itip_message, calendar):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Process a METHOD=REPLY.
</span><span class="lines">@@ -576,7 +610,7 @@
</span><span class="cx">             # Do VPOLL transfer
</span><span class="cx">             if reply_component.name() == &quot;VPOLL&quot;:
</span><span class="cx">                 # TODO: figure out how to report changes back
</span><del>-                iTipProcessing.updateVPOLLDataFromReply(reply_component, organizer_component, attendee)
</del><ins>+                partstat_changed = iTipProcessing.updateVPOLLDataFromReply(reply_component, organizer_component, attendee)
</ins><span class="cx"> 
</span><span class="cx">         return attendee.value(), partstat_changed, private_comment_changed
</span><span class="cx"> 
</span><span class="lines">@@ -595,6 +629,8 @@
</span><span class="cx">         @type attendee: L{Property}
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><ins>+        partstat_changed = False
+
</ins><span class="cx">         # Get REQUEST-STATUS as we need to write that into the saved ATTENDEE property
</span><span class="cx">         reqstatus = tuple(reply_component.properties(&quot;REQUEST-STATUS&quot;))
</span><span class="cx">         if reqstatus:
</span><span class="lines">@@ -607,12 +643,13 @@
</span><span class="cx">         organizerVoter = organizer_component.voterComponentForVoter(attendee.value())
</span><span class="cx"> 
</span><span class="cx">         if replyVoter is None:
</span><del>-            return
</del><ins>+            return partstat_changed
</ins><span class="cx"> 
</span><span class="cx">         if organizerVoter is None:
</span><span class="cx">             # Add in the new one
</span><span class="cx">             organizerVoter = replyVoter.duplicate()
</span><span class="cx">             reply_component.addComponent(organizerVoter)
</span><ins>+            partstat_changed = True
</ins><span class="cx">         else:
</span><span class="cx">             # Merge each vote
</span><span class="cx">             replyMap = replyVoter.voteMap()
</span><span class="lines">@@ -621,9 +658,12 @@
</span><span class="cx">             # Add new ones
</span><span class="cx">             for vote in set(replyMap.keys()) - set(organizerMap.keys()):
</span><span class="cx">                 organizerVoter.addComponent(replyMap[vote].duplicate())
</span><ins>+                partstat_changed = True
</ins><span class="cx"> 
</span><span class="cx">             # Replace existing ones
</span><span class="cx">             for vote in set(replyMap.keys()) &amp; set(organizerMap.keys()):
</span><ins>+                if organizerMap[vote].propertyValue(&quot;RESPONSE&quot;) != replyMap[vote].propertyValue(&quot;RESPONSE&quot;):
+                    partstat_changed = True
</ins><span class="cx">                 organizerVoter.removeComponent(organizerMap[vote])
</span><span class="cx">                 organizerVoter.addComponent(replyMap[vote].duplicate())
</span><span class="cx"> 
</span><span class="lines">@@ -635,7 +675,9 @@
</span><span class="cx">         except KeyError:
</span><span class="cx">             pass
</span><span class="cx"> 
</span><ins>+        return partstat_changed
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @staticmethod
</span><span class="cx">     def transferItems(from_calendar, to_component, needs_action_rids, reschedule, master_details, remove_matched=False):
</span><span class="cx">         &quot;&quot;&quot;
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingprocessingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/processing.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/processing.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/processing.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -90,8 +90,9 @@
</span><span class="cx">         @param recipient: calendar user receiving the message
</span><span class="cx">         @type recipient: C{str}
</span><span class="cx"> 
</span><del>-        @return: a C{tuple} of (C{bool}, C{bool}) indicating whether the message was processed, and if it was whether
-            auto-processing has taken place.
</del><ins>+        @return: a C{tuple} of (C{bool}, C{bool}, C{bool}, C{bool}) indicating whether the message was processed,
+            and if it was whether auto-processing has taken place, whether it needs to be stored in the inbox, and
+            the changes property for the inbox item.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         self.txn = txn
</span><span class="lines">@@ -151,7 +152,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def isAttendeeReceivingMessage(self):
</span><del>-        return self.method in (&quot;REQUEST&quot;, &quot;ADD&quot;, &quot;CANCEL&quot;)
</del><ins>+        return self.method in (&quot;REQUEST&quot;, &quot;ADD&quot;, &quot;CANCEL&quot;, &quot;POLLSTATUS&quot;)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -393,6 +394,8 @@
</span><span class="cx">         elif self.method == &quot;ADD&quot;:
</span><span class="cx">             # TODO: implement ADD
</span><span class="cx">             result = (False, False, False, None)
</span><ins>+        elif self.method == &quot;POLLSTATUS&quot;:
+            result = (yield self.doImplicitAttendeePollStatus())
</ins><span class="cx">         else:
</span><span class="cx">             # NB We should never get here as we will have rejected unsupported METHODs earlier.
</span><span class="cx">             result = (True, True, False, None,)
</span><span class="lines">@@ -552,7 +555,7 @@
</span><span class="cx">             else:
</span><span class="cx">                 # Request needs to be ignored
</span><span class="cx">                 log.debug(&quot;ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:REQUEST, UID: '%s' - ignoring&quot; % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
</span><del>-                result = (True, True, False, None,)
</del><ins>+                result = (True, False, False, None,)
</ins><span class="cx"> 
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><span class="lines">@@ -570,7 +573,7 @@
</span><span class="cx">         # If there is no existing copy, then ignore
</span><span class="cx">         if self.recipient_calendar is None:
</span><span class="cx">             log.debug(&quot;ImplicitProcessing - originator '%s' to recipient '%s' ignoring METHOD:CANCEL, UID: '%s' - attendee has no copy&quot; % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
</span><del>-            result = (True, True, True, None)
</del><ins>+            result = (True, False, True, None)
</ins><span class="cx">         else:
</span><span class="cx">             # Need to check for auto-respond attendees. These need to suppress the inbox message
</span><span class="cx">             # if the cancel is processed. However, if the principal is a user we always force the
</span><span class="lines">@@ -631,12 +634,36 @@
</span><span class="cx">                     result = (True, autoprocessed, store_inbox, changes)
</span><span class="cx">             else:
</span><span class="cx">                 log.debug(&quot;ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:CANCEL, UID: '%s' - ignoring&quot; % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
</span><del>-                result = (True, True, False, None)
</del><ins>+                result = (True, False, False, None)
</ins><span class="cx"> 
</span><span class="cx">         returnValue(result)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><ins>+    def doImplicitAttendeePollStatus(self):
+        &quot;&quot;&quot;
+        An iTIP message status update has been sent to an attendee by the organizer. We need to update the
+        attendee state based on the nature of the iTIP message.
+        &quot;&quot;&quot;
+        # If there is no existing copy, then we must fail
+        if self.new_resource:
+            log.debug(&quot;ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:POLLSTATUS, UID: '%s' - attendee has no copy&quot; % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
+            returnValue((True, False, False, None,))
+
+        processed_message = iTipProcessing.processPollStatus(self.message, self.recipient_calendar)
+
+        # Let the store know that no time-range info has changed for a refresh (assuming that
+        # no auto-accept changes were made)
+        processed_message.noInstanceIndexing = True
+
+        # Update the attendee's copy of the event
+        log.debug(&quot;ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:POLLSTATUS, UID: '%s' - updating poll&quot; % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
+        yield self.writeCalendarResource(None, self.recipient_calendar_resource, processed_message)
+
+        returnValue((True, False, False, None,))
+
+
+    @inlineCallbacks
</ins><span class="cx">     def checkAttendeeAutoReply(self, calendar, automode):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Check whether a reply to the given iTIP message is needed and if so make the
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingschedulerpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/scheduler.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/scheduler.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/scheduler.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -515,7 +515,7 @@
</span><span class="cx">             yield self.generateRemoteSchedulingResponses(otherserver_recipients, responses, freebusy, getattr(self.txn, 'doing_attendee_refresh', False))
</span><span class="cx"> 
</span><span class="cx">         # To reduce chatter, we suppress certain messages
</span><del>-        if not self.suppress_refresh:
</del><ins>+        if not self.suppress_refresh or self.calendar.mainType() == &quot;VPOLL&quot;:
</ins><span class="cx"> 
</span><span class="cx">             # Now process remote recipients
</span><span class="cx">             if remote_recipients:
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingtesttest_itippy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/test/test_itip.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/test/test_itip.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/test/test_itip.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -21,7 +21,7 @@
</span><span class="cx"> from twisted.trial import unittest
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav.stdconfig import config
</span><del>-from twistedcaldav.ical import Component
</del><ins>+from twistedcaldav.ical import Component, normalize_iCalStr
</ins><span class="cx"> 
</span><span class="cx"> from txdav.caldav.datastore.scheduling.itip import iTipProcessing, iTipGenerator
</span><span class="cx"> 
</span><span class="lines">@@ -1289,6 +1289,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;1.2 Simple Reply - recurring no overrides&quot;,
</span><span class="lines">@@ -1335,6 +1336,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;1.3 Simple Reply - recurring with missing master&quot;,
</span><span class="lines">@@ -1389,6 +1391,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;1.4 Simple Reply - recurring with overrides in master but not reply&quot;,
</span><span class="lines">@@ -1453,6 +1456,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;1.5 Simple Reply - recurring with overrides in master invalid in reply&quot;,
</span><span class="lines">@@ -1517,6 +1521,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;1.6 Simple Reply - recurring with overrides in master, invalid ones in reply&quot;,
</span><span class="lines">@@ -1590,6 +1595,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;2.1 X-CALENDARSERVER-RESET-PARTSTAT Reply - non recurring&quot;,
</span><span class="lines">@@ -1636,6 +1642,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;2.2 X-CALENDARSERVER-RESET-PARTSTAT Reply - non recurring&quot;,
</span><span class="lines">@@ -1682,6 +1689,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;2.3 X-CALENDARSERVER-RESET-PARTSTAT Reply - non recurring&quot;,
</span><span class="lines">@@ -1728,6 +1736,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;2.4 X-CALENDARSERVER-RESET-PARTSTAT Reply - non recurring&quot;,
</span><span class="lines">@@ -1774,6 +1783,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                None,
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;3.1 Simple VPOLL Reply - response added&quot;,
</span><span class="lines">@@ -1874,6 +1884,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                ('mailto:user2@example.com', set([(&quot;&quot;, True, False,)])),
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;3.2 Simple VPOLL Reply - response changed&quot;,
</span><span class="lines">@@ -1978,6 +1989,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                ('mailto:user2@example.com', set([(&quot;&quot;, True, False,)])),
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;3.3 Simple VPOLL Reply - response added and changed&quot;,
</span><span class="lines">@@ -2090,6 +2102,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                ('mailto:user2@example.com', set([(&quot;&quot;, True, False,)])),
</ins><span class="cx">             ),
</span><span class="cx">             (
</span><span class="cx">                 &quot;3.4 Simple VPOLL Reply - response one changed&quot;,
</span><span class="lines">@@ -2202,21 +2215,475 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;,
</span><span class="cx">                 True,
</span><ins>+                ('mailto:user2@example.com', set([(&quot;&quot;, True, False,)])),
</ins><span class="cx">             ),
</span><ins>+            (
+                &quot;3.5 Simple VPOLL Reply - no changes&quot;,
+                &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=&quot;User 01&quot;:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:50
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN=&quot;User 01&quot;:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ORGANIZER;CN=&quot;User 01&quot;:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+&quot;&quot;&quot;,
+                &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:REPLY
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=&quot;User 01&quot;:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:50
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+END:VPOLL
+END:VCALENDAR
+&quot;&quot;&quot;,
+                &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=&quot;User 01&quot;:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;SCHEDULE-STATUS=2.0:mailto:user2@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:50
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN=&quot;User 01&quot;:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ORGANIZER;CN=&quot;User 01&quot;:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+&quot;&quot;&quot;,
+                True,
+                ('mailto:user2@example.com', set([])),
+            ),
</ins><span class="cx">         )
</span><span class="cx"> 
</span><del>-        for title, calendar_txt, itip_txt, changed_txt, expected in data:
</del><ins>+        for title, calendar_txt, itip_txt, changed_txt, expected, processed in data:
</ins><span class="cx">             calendar = Component.fromString(calendar_txt)
</span><span class="cx">             itip = Component.fromString(itip_txt)
</span><span class="cx">             if expected:
</span><span class="cx">                 changed = Component.fromString(changed_txt)
</span><span class="cx"> 
</span><del>-            result, _ignore = iTipProcessing.processReply(itip, calendar)
</del><ins>+            result, result_processed = iTipProcessing.processReply(itip, calendar)
</ins><span class="cx">             self.assertEqual(result, expected, msg=&quot;Result mismatch: %s&quot; % (title,))
</span><span class="cx">             if expected:
</span><span class="cx">                 self.assertEqual(changed, calendar, msg=&quot;Calendar mismatch: %s&quot; % (title,))
</span><ins>+            if processed is not None:
+                self.assertEqual(result_processed, processed, msg=&quot;Process mismatch: %s&quot; % (title,))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    def test_processPollStatus(self):
+        &quot;&quot;&quot;
+        Test iTIPProcessing.processPollStatus
+        &quot;&quot;&quot;
+
+        data = (
+            (
+                &quot;3.1 Simple VPOLL - response added&quot;,
+                &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+&quot;&quot;&quot;,
+                &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:POLLSTATUS
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+END:VPOLL
+END:VCALENDAR
+&quot;&quot;&quot;,
+                &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+&quot;&quot;&quot;,
+            ),
+            (
+                &quot;3.2 Simple VPOLL - recipient response not changed&quot;,
+                &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+&quot;&quot;&quot;,
+                &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:POLLSTATUS
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:50
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+END:VPOLL
+END:VCALENDAR
+&quot;&quot;&quot;,
+                &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+&quot;&quot;&quot;,
+            ),
+        )
+
+        for title, calendar_txt, itip_txt, changed_txt in data:
+            calendar = Component.fromString(calendar_txt)
+            itip = Component.fromString(itip_txt)
+
+            result = iTipProcessing.processPollStatus(itip, calendar, &quot;mailto:user2@example.com&quot;)
+            self.assertEqual(normalize_iCalStr(result), normalize_iCalStr(changed_txt), msg=&quot;Calendar mismatch: %s&quot; % (title,))
+
+
</ins><span class="cx">     def test_update_attendee_partstat(self):
</span><span class="cx"> 
</span><span class="cx">         data = (
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/sql.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/sql.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/sql.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -2303,7 +2303,9 @@
</span><span class="cx">         self._cachedComponent = None
</span><span class="cx">         self._cachedCommponentPerUser = {}
</span><span class="cx"> 
</span><ins>+        self._lockedUID = False
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _createInternal(cls, parent, name, component, internal_state, options=None, split_details=None):
</span><span class="lines">@@ -3116,8 +3118,8 @@
</span><span class="cx">                 internal_request=is_internal,
</span><span class="cx">             ))
</span><span class="cx"> 
</span><del>-            # group attendees
-            if scheduler.state == &quot;organizer&quot;:
</del><ins>+            # Group attendees - though not during a split
+            if scheduler.state == &quot;organizer&quot; and internal_state != ComponentUpdateState.SPLIT_OWNER:
</ins><span class="cx">                 changed = yield self.reconcileGroupAttendees(component, inserting)
</span><span class="cx">                 if changed:
</span><span class="cx">                     yield scheduler.extractAttendees()
</span><span class="lines">@@ -3214,15 +3216,26 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def _lockUID(self, component, inserting, internal_state):
</del><ins>+    def _lockUID(self, uid, internal_state):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Create a lock on the component's UID and verify, after getting the lock, that the incoming UID
</span><span class="cx">         meets the requirements of the store.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><ins>+        if not self._lockedUID and internal_state in (ComponentUpdateState.NORMAL, ComponentUpdateState.SPLIT_OWNER):
+            yield NamedLock.acquire(self._txn, &quot;ImplicitUIDLock:%s&quot; % (hashlib.md5(uid).hexdigest(),))
+            self._lockedUID = True
+
+
+    @inlineCallbacks
+    def _lockAndCheckUID(self, component, inserting, internal_state):
+        &quot;&quot;&quot;
+        Create a lock on the component's UID and verify, after getting the lock, that the incoming UID
+        meets the requirements of the store.
+        &quot;&quot;&quot;
+
</ins><span class="cx">         new_uid = component.resourceUID()
</span><del>-        if internal_state == ComponentUpdateState.NORMAL:
-            yield NamedLock.acquire(self._txn, &quot;ImplicitUIDLock:{0}&quot;.format(hashlib.md5(new_uid).hexdigest(),))
</del><ins>+        yield self._lockUID(new_uid, internal_state)
</ins><span class="cx"> 
</span><span class="cx">         # UID conflict check - note we do this after reserving the UID to avoid a race condition where two requests
</span><span class="cx">         # try to write the same calendar data to two different resource URIs.
</span><span class="lines">@@ -3302,9 +3315,27 @@
</span><span class="cx"> 
</span><span class="cx">             # Do scheduling only for owner split
</span><span class="cx">             if internal_state == ComponentUpdateState.SPLIT_OWNER:
</span><del>-                yield self.doImplicitScheduling(component, inserting, internal_state, options, split_details)
</del><ins>+                # UID lock - this will remain active until the end of the current txn
+                yield self._lockAndCheckUID(component, inserting, internal_state)
</ins><span class="cx"> 
</span><del>-            self.isScheduleObject = True
</del><ins>+                # Make sure various bits of scheduling meta-data are correctly setup to ensure the
+                # new resource created by a split has the proper state
+                implicit_result = yield self.doImplicitScheduling(component, inserting, internal_state, options, split_details)
+                if isinstance(implicit_result, int):
+                    msg = &quot;Invalid return status code from ImplicitScheduler during split: %s&quot; % (implicit_result,)
+                    log.error(msg)
+                    raise InvalidObjectResourceError(msg)
+
+                self.isScheduleObject, new_component, did_implicit_action, schedule_state = implicit_result
+                if new_component is not None:
+                    component = new_component
+                if did_implicit_action:
+                    self._componentChanged = True
+
+            elif internal_state == ComponentUpdateState.SPLIT_ATTENDEE:
+                # This must always be set since the only time we get is is during scheduling
+                self.isScheduleObject = True
+
</ins><span class="cx">             self.processScheduleTags(component, inserting, internal_state)
</span><span class="cx"> 
</span><span class="cx">         elif internal_state != ComponentUpdateState.RAW:
</span><span class="lines">@@ -3312,7 +3343,7 @@
</span><span class="cx">             yield self.fullValidation(component, inserting, internal_state)
</span><span class="cx"> 
</span><span class="cx">             # UID lock - this will remain active until the end of the current txn
</span><del>-            yield self._lockUID(component, inserting, internal_state)
</del><ins>+            yield self._lockAndCheckUID(component, inserting, internal_state)
</ins><span class="cx"> 
</span><span class="cx">             # Preserve private comments
</span><span class="cx">             yield self.preservePrivateComments(component, inserting, internal_state)
</span><span class="lines">@@ -4691,25 +4722,32 @@
</span><span class="cx">         @type pastuid: L{str}
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><ins>+        # Cannot create one with the same UID as this
+        if pastUID and pastUID == self._uid:
+            raise InvalidSplit(&quot;Cannot split an event and re-use the same UID.&quot;)
+
</ins><span class="cx">         # Must be recurring
</span><span class="cx">         component = yield self.component()
</span><span class="cx">         if not component.isRecurring():
</span><del>-            raise InvalidSplit()
</del><ins>+            raise InvalidSplit(&quot;Cannot split a non-recurring event.&quot;)
</ins><span class="cx"> 
</span><span class="cx">         # Cannot be attendee
</span><span class="cx">         organizer = component.getOrganizer()
</span><span class="cx">         organizerAddress = (yield calendarUserFromCalendarUserAddress(organizer, self._txn)) if organizer else None
</span><span class="cx">         if organizer is not None and organizerAddress.record.uid != self.calendar().ownerHome().uid():
</span><del>-            raise InvalidSplit()
</del><ins>+            raise InvalidSplit(&quot;Only organizers can split events.&quot;)
</ins><span class="cx"> 
</span><span class="cx">         # Determine valid split point
</span><span class="cx">         splitter = iCalSplitter(1024, 14)
</span><span class="cx">         rid = splitter.whereSplit(component, break_point=rid, allow_past_the_end=False)
</span><span class="cx">         if rid is None:
</span><del>-            raise InvalidSplit()
</del><ins>+            raise InvalidSplit(&quot;Cannot find a suitable recurrence-id to split at.&quot;)
</ins><span class="cx"> 
</span><span class="cx">         # Do split and return new resource
</span><del>-        olderObject = yield self.split(rid=rid, olderUID=pastUID)
</del><ins>+        try:
+            olderObject = yield self.split(rid=rid, olderUID=pastUID)
+        except (UIDExistsError, UIDExistsElsewhereError):
+            raise InvalidSplit(&quot;Chosen UID exists elsewhere.&quot;)
</ins><span class="cx">         returnValue(olderObject)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -4747,7 +4785,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # First job is to grab a UID lock on this entire series of events
</span><del>-        yield NamedLock.acquire(self._txn, &quot;ImplicitUIDLock:{0}&quot;.format(hashlib.md5(self._uid).hexdigest(),))
</del><ins>+        yield self._lockUID(self._uid, internal_state=ComponentUpdateState.SPLIT_OWNER)
</ins><span class="cx"> 
</span><span class="cx">         # Find all other calendar objects on this server with the same UID
</span><span class="cx">         if onlyThis:
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoretesttest_sqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/test/test_sql.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/test/test_sql.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/test/test_sql.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -5455,7 +5455,10 @@
</span><span class="cx"> 
</span><span class="cx">             responses = ScheduleResponseQueue(&quot;REQUEST&quot;, responsecode.OK)
</span><span class="cx">             for recipient in recipients:
</span><del>-                responses.add(recipient, responsecode.OK, reqstatus=iTIPRequestStatus.MESSAGE_DELIVERED)
</del><ins>+                if recipient.startswith(&quot;urn:x-uid&quot;):
+                    responses.add(recipient, responsecode.OK, reqstatus=iTIPRequestStatus.MESSAGE_DELIVERED)
+                else:
+                    responses.add(recipient, responsecode.NOT_FOUND, reqstatus=iTIPRequestStatus.INVALID_CALENDAR_USER)
</ins><span class="cx">             return succeed(responses)
</span><span class="cx"> 
</span><span class="cx">         component = Component.fromString(data % self.subs)
</span><span class="lines">@@ -6867,13 +6870,13 @@
</span><span class="cx"> 
</span><span class="cx">         # Get the existing and new object data
</span><span class="cx">         cobj1 = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        self.assertTrue(cobj1.isScheduleObject)
</del><ins>+        self.assertFalse(cobj1.isScheduleObject)
</ins><span class="cx">         ical1 = yield cobj1.component()
</span><span class="cx">         relID = ical1.masterComponent().propertyValue(&quot;RELATED-TO&quot;)
</span><span class="cx"> 
</span><span class="cx">         cobj2 = yield self.calendarObjectUnderTest(name=oldname, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         self.assertTrue(cobj2 is not None)
</span><del>-        self.assertTrue(cobj2.isScheduleObject)
</del><ins>+        self.assertFalse(cobj2.isScheduleObject)
</ins><span class="cx">         ical2 = yield cobj2.component()
</span><span class="cx">         newUID = ical2.masterComponent().propertyValue(&quot;UID&quot;)
</span><span class="cx"> 
</span><span class="lines">@@ -7013,7 +7016,57 @@
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_inbox), normalize_iCalStr(data_inbox2) % relsubs, &quot;Failed inbox: %s&quot; % (title,))
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    @inlineCallbacks
+    def test_calendarObjectSplit_splitat_no_same_uid(self):
+        &quot;&quot;&quot;
+        Test that user triggered splitting of calendar objects does not work if the specified UID is the same
+        as the resource being split.
+        &quot;&quot;&quot;
</ins><span class="cx"> 
</span><ins>+        yield self._setupSplitAt()
+
+        # Update it
+        cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
+        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.subs), pastUID=&quot;12345-67890&quot;), InvalidSplit)
+
+
+    @inlineCallbacks
+    def test_calendarObjectSplit_splitat_no_existing_uid(self):
+        &quot;&quot;&quot;
+        Test that user triggered splitting of calendar objects does not work if the specified UID is the same
+        as another resource.
+        &quot;&quot;&quot;
+
+        data_existing = &quot;&quot;&quot;BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-existing
+DTSTART:%(now_back28)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+RRULE:FREQ=DAILY;COUNT=50
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+END:VCALENDAR
+&quot;&quot;&quot;
+
+        yield self._setupSplitAt()
+
+        calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
+        component = Component.fromString(data_existing % self.subs)
+        yield calendar.createCalendarObjectWithName(&quot;data2.ics&quot;, component)
+        yield self.commit()
+
+        # Update it
+        cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
+        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.subs), pastUID=&quot;12345-67890-existing&quot;), InvalidSplit)
+
+
+
</ins><span class="cx"> class TimeRangeUpdateOptimization(CommonCommonTests, unittest.TestCase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     CalendarObject time range optimization tests.
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcommondatastoretestutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/common/datastore/test/util.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/common/datastore/test/util.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/common/datastore/test/util.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -262,6 +262,7 @@
</span><span class="cx">                 reactor, store.newTransaction, None, useWorkerPool=False
</span><span class="cx">             )
</span><span class="cx">             store.queuer = store.queuer.transferProposalCallbacks(pool)
</span><ins>+            store.pool = pool
</ins><span class="cx">             pool.startService()
</span><span class="cx"> 
</span><span class="cx">         returnValue(store)
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxweb2davresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txweb2/dav/resource.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txweb2/dav/resource.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txweb2/dav/resource.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -706,7 +706,7 @@
</span><span class="cx">         def gotChildren(listChildrenResult):
</span><span class="cx">             children[:] = list(listChildrenResult)
</span><span class="cx">             getChild()
</span><del>-        maybeDeferred(self.listChildren).addCallback(gotChildren)
</del><ins>+        maybeDeferred(self.listChildren).addCallback(gotChildren).addErrback(completionDeferred.errback)
</ins><span class="cx"> 
</span><span class="cx">         return completionDeferred
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>