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