[CalendarServer-changes] [12322] CalendarServer/branches/users/gaya/cleanrevisions

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 12 11:15:48 PDT 2014


Revision: 12322
          http://trac.calendarserver.org//changeset/12322
Author:   gaya at apple.com
Date:     2014-01-12 11:10:08 -0800 (Sun, 12 Jan 2014)
Log Message:
-----------
merge from trunk through r12321

Revision Links:
--------------
    http://trac.calendarserver.org//changeset/12321

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/cleanrevisions/README
    CalendarServer/branches/users/gaya/cleanrevisions/benchmark
    CalendarServer/branches/users/gaya/cleanrevisions/benchreport
    CalendarServer/branches/users/gaya/cleanrevisions/bin/_calendarserver_preamble.py
    CalendarServer/branches/users/gaya/cleanrevisions/bin/caldavd
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_backup
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_bootstrap_database
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_command_gateway
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_config
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_dbinspect
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_dkimtool
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_export
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_icalendar_validate
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_load_augmentdb
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_postgres
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_principals
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_push
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_timezones
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_migrate_resources
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_amp_notifications
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_notifications
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_work
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_attachments
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_events
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_principals
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_shell
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_upgrade
    CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_verify_data
    CalendarServer/branches/users/gaya/cleanrevisions/bin/icalendar_split
    CalendarServer/branches/users/gaya/cleanrevisions/bin/proxyclean
    CalendarServer/branches/users/gaya/cleanrevisions/bin/trial
    CalendarServer/branches/users/gaya/cleanrevisions/bin/twistd
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/accesslog.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/controlsocket.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/logAnalysis.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/_sacl.c
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/dsattributes.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/dsquery.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/opendirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/setup_directory.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/setup_testusers.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/test/test_opendirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/wiki.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/root.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/test/test_root.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/amppush.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/applepush.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/notifier.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_amppush.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_applepush.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_notifier.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/caldav.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/cfgchild.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/profiling.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/longlines.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/test_caldav.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/test_util.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/test/test_logAnalysis.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/agent.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/ampnotifications.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/anonymize.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/backup.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/backup_pg.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/bootstrapdatabase.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/calverify.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/calverify_diff.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/changeip_calendar.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/cmdline.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/config.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/dbinspect.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/dkimtool.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/export.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/gateway.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/icalsplit.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/loadaugmentdb.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/managepostgres.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/managetimezones.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/migrate.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/migrate_verify.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/notifications.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/obliterate.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/principals.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/purge.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/push.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/resources.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/cmd.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/directory.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/terminal.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/test_cmd.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/test_vfs.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/vfs.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/tables.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/calverify/accounts.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/calverify/augments.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/augments.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/caldavd.plist
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/resources-locations.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/users-groups.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/augments.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/caldavd.plist
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/resources-locations.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/users-groups.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/augments.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/caldavd.plist
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/resources-locations.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/users-groups.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/purge/accounts.xml
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_agent.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_calverify.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_changeip.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_config.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_export.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_gateway.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_principals.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_purge.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_purge_old_events.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_resources.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_util.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/upgrade.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/validcalendardata.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/workitems.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/test/test_resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/test/test_resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts-test.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts.dtd
    CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/augments-default.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/augments.dtd
    CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies-test-pod.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies-test.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies.dtd
    CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-apple.plist
    CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-test-podB.plist
    CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-test.plist
    CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd.plist
    CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers-test.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers.dtd
    CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers-test.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers.dtd
    CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/caldavd-resources.plist
    CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/locations-resources-orig.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/locations-resources.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/users-groups.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/resources.xml
    CalendarServer/branches/users/gaya/cleanrevisions/conf/test/accounts.xml
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/launchd/calendarserver.plist
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/_event_change.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/_event_create.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchlib.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchlib.sh
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmark
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmark.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/bounded_recurrence.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/bounded_recurrence_autoaccept.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_add_attendee.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_autoaccept.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_change_date.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_change_summary.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_delete.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_delete_attendee.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_move.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/find_calendars.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/find_events.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/unbounded_recurrence.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/unbounded_recurrence_autoaccept.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/vfreebusy.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/vfreebusy_vary_attendees.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/compare
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/compare.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/display-calendar-events.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/extractconf
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/fix-units.sql
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/graph
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/graph.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/httpauth.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/httpclient.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/io_measure.d
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/ampsim.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/clients.plist
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/config.dist.plist
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/config.plist
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/ical.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/logger.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/population.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/profiles.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/sim.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_ical.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_population.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_profiles.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_sim.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_trafficlogger.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_webadmin.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/trafficlogger.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/webadmin.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/massupload
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/massupload.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/nightly.sh
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/pgsql.d
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/profile.sh
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report_principals.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/reupload.sh
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sample-many.sh
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sample.sh
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/setbackend
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/setbackend.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sim
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/some-more-data.sh
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/speedcenter.tac
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sql_measure.d
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/httpTests.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/invite.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/multiget.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/propfind.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/propfind_invite.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/put.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/query.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/sync.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/sqlusage.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlwatch
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlwatch.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/stackedbar.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/stats.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sudo-run.sh
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/svn-committime
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/svn-revno
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_benchmark.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_event_change_date.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_httpauth.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_stats.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/upload
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/upload.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/anonymous_log.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/dtraceanalyze.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/fakecalendardata.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/fix_calendar
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/harpoon.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/monitoranalysis.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/monitorsplit.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/netstatus.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/pg_stats_analysis.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/pgtrace.d
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/protocolanalysis.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/readStats.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/request_monitor.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/sortrecurrences.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/sqldata_from_path.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/tables.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/test_protocolanalysis.py
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/Makefile
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/caldav.js
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/jcal.js
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/utils.js
    CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/webpoll.js
    CalendarServer/branches/users/gaya/cleanrevisions/doc/caldavd.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_bootstrap_database.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_command_gateway.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_config.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_export.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_principals.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_push.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_timezones.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_migrate_resources.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_monitor_notifications.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_attachments.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_events.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_principals.8
    CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_shell.8
    CalendarServer/branches/users/gaya/cleanrevisions/locales/en_EN.ISO8859-1/LC_MESSAGES/calendarserver.po
    CalendarServer/branches/users/gaya/cleanrevisions/pydoctor
    CalendarServer/branches/users/gaya/cleanrevisions/run
    CalendarServer/branches/users/gaya/cleanrevisions/setup.py
    CalendarServer/branches/users/gaya/cleanrevisions/sim
    CalendarServer/branches/users/gaya/cleanrevisions/support/Apple.make
    CalendarServer/branches/users/gaya/cleanrevisions/support/XCode.make
    CalendarServer/branches/users/gaya/cleanrevisions/support/build.sh
    CalendarServer/branches/users/gaya/cleanrevisions/support/gendocs
    CalendarServer/branches/users/gaya/cleanrevisions/support/patchapply
    CalendarServer/branches/users/gaya/cleanrevisions/support/patchmaker
    CalendarServer/branches/users/gaya/cleanrevisions/support/py.sh
    CalendarServer/branches/users/gaya/cleanrevisions/support/shell.sh
    CalendarServer/branches/users/gaya/cleanrevisions/support/submit
    CalendarServer/branches/users/gaya/cleanrevisions/support/version.py
    CalendarServer/branches/users/gaya/cleanrevisions/test
    CalendarServer/branches/users/gaya/cleanrevisions/testserver
    CalendarServer/branches/users/gaya/cleanrevisions/twisted/plugins/caldav.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/accounting.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/authkerb.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/backup.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/bind.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/cache.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/caldavxml.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/carddavxml.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/geturl.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/pool.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/reverseproxy.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/test/test_reverseproxy.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/config.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/customxml.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/database.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/addressdata.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/calendardata.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/filter.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/hiddeninstance.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/peruserdata.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/privateevents.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_calendardata.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_hiddeninstances.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_peruserdata.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_privateevents.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/dateops.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/addressbook.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/aggregate.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/augment.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/cachingdirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendar.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendaruserproxy.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendaruserproxyloader.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/common.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/digest.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/directory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/idirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/internal.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/ldapdirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/opendirectorybacker.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/principal.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/resourceinfo.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/accounts-modified.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/accounts.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-normalization.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-test-default.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-test.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/augments.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/resources-locations.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/users-groups.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/proxies.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/augments.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/caldavd.plist
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/resources-locations.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/users-groups.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources.xml
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_aggregate.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_augment.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_buildquery.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_cachedirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_calendar.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_digest.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_directory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_guidchange.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_ldapdirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_livedirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_modify.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_opendirectory.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_opendirectorybacker.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_principal.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_proxyprincipaldb.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_proxyprincipalmembers.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_resources.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_util.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_wiki.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_xmlfile.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/wiki.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlaccountsparser.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlaugmentsparser.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlfile.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directorybackedaddressbook.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/dropbox.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/extensions.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/freebusyurl.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/ical.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/icaldav.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/instance.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/linkresource.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/localization.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcachelock.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcachepool.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcacheprops.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcacher.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/acl.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/get.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/mkcalendar.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/mkcol.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/post.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/propfind.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_addressbook_multiget.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_addressbook_query.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_calendar_multiget.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_calendar_query.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_common.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_freebusy.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_multiget_common.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_sync_collection.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/mkcolxml.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/notifications.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/test/test_resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/sharing.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/simpleresource.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/stdconfig.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/storebridge.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_accounting.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_addressbookmultiget.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_addressbookquery.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_cache.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_caldavxml.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_calendarquery.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_collectioncontents.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_config.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_customxml.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_database.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_dateops.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_extensions.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_freebusyquery.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_icalendar.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_kerberos.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_link.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_localization.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_memcachepool.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_memcacheprops.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_mkcalendar.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_multiget.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_options.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_props.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_sharing.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_stdconfig.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_timezones.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_timezonestdservice.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_upgrade.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_util.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_wrapping.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_xml.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_xmlutil.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezones.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezoneservice.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezonestdservice.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezonexml.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/upgrade.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/vcard.py
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/xmlutil.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/dbapiclient.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/subpostgres.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/test/test_subpostgres.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/appledouble_xattr.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/base.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/none.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/base.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_appledouble.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_base.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_none.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_xattr.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/xattr.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/index_file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/schedule.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/addressmapping.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/delivery.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/scheduler.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/test_delivery.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/cuaddress.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/delivery.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/freebusy.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/icaldiff.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/icalsplitter.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/delivery.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/inbound.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/mailgateway.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/outbound.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/scheduler.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/smtpsender.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_mailgateway.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/implicit.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/delivery.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/dkim.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/localservers.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/remoteservers.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/scheduler.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_remoteservers.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_utils.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/utils.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/xml.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/itip.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/processing.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/scheduler.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_freebusy.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_icaldiff.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_implicit.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_itip.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_pocessing.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_utils.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/utils.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/attachments/accounts.xml
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/common.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_attachments.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_implicit.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_index_file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_schedule.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql_sharing.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/icalendardirectoryservice.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/icalendarstore.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/index_file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/common.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_index_file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_sql_sharing.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/iaddressbookstore.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/common.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/file.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_dump.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/current.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v27.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v28.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v29.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v30.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v31.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v32.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v10.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v11.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v12.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v13.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v14.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v15.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v16.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v17.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v18.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v19.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v20.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v21.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v22.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v23.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v26.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v27.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v28.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v29.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v3.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v30.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v31.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v32.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v4.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v5.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v6.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v7.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v8.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v9.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_10_to_11.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_11_to_12.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_12_to_13.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_13_to_14.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_14_to_15.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_15_to_16.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_16_to_17.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_17_to_18.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_19_to_20.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_20_to_21.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_21_to_22.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_22_to_23.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_23_to_24.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_26_to_27.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_27_to_28.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_28_to_29.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_29_to_30.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_30_to_31.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_31_to_32.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_3_to_4.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_4_to_5.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_5_to_6.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_6_to_7.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_7_to_8.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_8_to_9.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_9_to_10.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_10_to_11.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_11_to_12.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_12_to_13.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_13_to_14.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_14_to_15.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_15_to_16.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_16_to_17.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_17_to_18.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_19_to_20.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_20_to_21.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_21_to_22.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_22_to_23.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_23_to_24.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_26_to_27.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_27_to_28.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_28_to_29.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_29_to_30.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_30_to_31.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_31_to_32.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_3_to_4.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_4_to_5.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_5_to_6.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_6_to_7.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_7_to_8.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_8_to_9.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_9_to_10.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/upgrade_template.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_tables.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/test_sql.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/test_sql_schema_files.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/test_sql_tables.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/file/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/migrate.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/attachment_migration.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/test/test_attachment_migration.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema1/current.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema1/upgrades/fake_dialect/upgrade_from_3_to_4.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema2/current.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema2/upgrades/fake_dialect/upgrade_from_3_to_4.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema2/upgrades/fake_dialect/upgrade_from_3_to_5.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema2/upgrades/fake_dialect/upgrade_from_4_to_5.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema3/current.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema3/upgrades/fake_dialect/upgrade_from_3_to_4.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema3/upgrades/fake_dialect/upgrade_from_4_to_5.sql
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/test_upgrade.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrade.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/addressbook_upgrade_from_1_to_2.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_1_to_2.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_2_to_3.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/notification_upgrade_from_0_to_1.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/test/test_notification_upgrade_from_0_to_1.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_4_to_5.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/test/test_migrate.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/work/test/test_revision_cleanup.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/icommondatastore.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/idirectoryservice.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/inotifications.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/idav.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/base.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/element.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/extensions.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser_base.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser_etree.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser_sax.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc2518.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc3253.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc3744.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc4331.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc5397.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc5842.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc5995.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc6578.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_base.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_xml.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_xml_rfc3744.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/basic.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/digest.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/interfaces.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/wrapper.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/channel/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/channel/http.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/client/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/client/http.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/client/interfaces.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/auth.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/fileop.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/http.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/idav.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/acl.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/copymove.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/delete.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/delete_common.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/get.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/lock.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/mkcol.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/propfind.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/proppatch.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/put.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/put_common.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_acl_principal_prop_set.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_expand.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_principal_match.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_principal_property_search.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_principal_search_property_set.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/noneprops.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/static.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/__init__.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_acl.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_auth.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_copy.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_delete.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_http.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_lock.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_mkcol.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_move.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_options.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_pipeline.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_prop.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_put.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_quota.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_report.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_report_expand.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_static.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/util.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/xattrprops.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/error.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/fileupload.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/http.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/http_headers.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/iweb.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/log.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/metafd.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/resource.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/responsecode.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/server.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/static.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/stream.py
    CalendarServer/branches/users/gaya/cleanrevisions/txweb2/test/test_metafd.py

Added Paths:
-----------
    CalendarServer/branches/users/gaya/cleanrevisions/doc/Extensions/caldav-recursplit.txt
    CalendarServer/branches/users/gaya/cleanrevisions/doc/Extensions/caldav-recursplit.xml
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/query/
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/sql_external.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql_external.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/query/
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/sql_external.py
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/podding/
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/query/
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_external.py

Removed Paths:
-------------
    CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/query/
    CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_legacy.py

Property Changed:
----------------
    CalendarServer/branches/users/gaya/cleanrevisions/


Property changes on: CalendarServer/branches/users/gaya/cleanrevisions
___________________________________________________________________
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/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/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/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/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/purge_old_events:6735-6746
/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
/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/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/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/purge_old_events:6735-6746
/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

Modified: CalendarServer/branches/users/gaya/cleanrevisions/README
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/README	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/README	2014-01-12 19:10:08 UTC (rev 12322)
@@ -12,7 +12,7 @@
 Copyright and License
 =====================
 
-Copyright (c) 2005-2013 Apple Inc.  All rights reserved.
+Copyright (c) 2005-2014 Apple Inc.  All rights reserved.
 
 This software is licensed under the Apache License, Version 2.0.  The
 Apache License is a well-established open source license, enabling

Modified: CalendarServer/branches/users/gaya/cleanrevisions/benchmark
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/benchmark	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/benchmark	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/benchreport
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/benchreport	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/benchreport	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/_calendarserver_preamble.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/_calendarserver_preamble.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/_calendarserver_preamble.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/caldavd
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/caldavd	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/caldavd	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 # -*- sh-basic-offset: 2 -*-
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_backup
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_backup	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_backup	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_bootstrap_database
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_bootstrap_database	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_bootstrap_database	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_command_gateway
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_command_gateway	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_command_gateway	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_config
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_config	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_config	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_dbinspect
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_dbinspect	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_dbinspect	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_dkimtool
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_dkimtool	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_dkimtool	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_export
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_export	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_export	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_icalendar_validate
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_icalendar_validate	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_icalendar_validate	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_load_augmentdb
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_load_augmentdb	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_load_augmentdb	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_postgres
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_postgres	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_postgres	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_principals
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_principals	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_principals	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_push
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_push	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_push	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_timezones
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_timezones	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_manage_timezones	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_migrate_resources
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_migrate_resources	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_migrate_resources	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_amp_notifications
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_amp_notifications	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_amp_notifications	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_notifications
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_notifications	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_notifications	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_work
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_work	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_monitor_work	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_attachments
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_attachments	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_attachments	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_events
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_events	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_events	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_principals
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_principals	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_purge_principals	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_shell
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_shell	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_shell	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_upgrade
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_upgrade	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_upgrade	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_verify_data
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_verify_data	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/calendarserver_verify_data	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/icalendar_split
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/icalendar_split	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/icalendar_split	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/proxyclean
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/proxyclean	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/proxyclean	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/trial
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/trial	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/trial	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/bin/twistd
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/bin/twistd	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/bin/twistd	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: calendarserver -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/accesslog.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/accesslog.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/accesslog.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/controlsocket.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/controlsocket.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/controlsocket.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/logAnalysis.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/logAnalysis.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/logAnalysis.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/_sacl.c
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/_sacl.c	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/_sacl.c	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2006-2014 Apple Inc. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/dsattributes.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/dsattributes.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/dsattributes.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/dsquery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/dsquery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/dsquery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/opendirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/opendirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/opendirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/setup_directory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/setup_directory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/setup_directory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/setup_testusers.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/setup_testusers.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/setup_testusers.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/test/test_opendirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/test/test_opendirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/od/test/test_opendirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/wiki.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/wiki.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/platform/darwin/wiki.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/root.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/root.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/root.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: calendarserver.provision.test.test_root -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/test/test_root.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/test/test_root.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/provision/test/test_root.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/amppush.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/amppush.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/amppush.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/applepush.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/applepush.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/applepush.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: calendarserver.push.test.test_applepush -*-
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/notifier.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/notifier.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/notifier.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_amppush.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_amppush.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_amppush.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_applepush.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_applepush.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_applepush.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_notifier.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_notifier.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/test/test_notifier.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -184,10 +184,10 @@
 class NotifierFactory(StoreTestCase):
 
     requirements = {
-        "home1" : {
+        "user01" : {
             "calendar_1" : {}
         },
-        "home2" : {
+        "user02" : {
             "calendar_1" : {}
         },
     }
@@ -208,23 +208,23 @@
     @inlineCallbacks
     def test_homeNotifier(self):
 
-        home = yield self.homeUnderTest()
+        home = yield self.homeUnderTest(name="user01")
         yield home.notifyChanged(category=ChangeCategory.default)
         self.assertEquals(self.notifierFactory.history,
-            [("/CalDAV/example.com/home1/", PushPriority.high)])
+            [("/CalDAV/example.com/user01/", PushPriority.high)])
         yield self.commit()
 
 
     @inlineCallbacks
     def test_calendarNotifier(self):
 
-        calendar = yield self.calendarUnderTest()
+        calendar = yield self.calendarUnderTest(home="user01")
         yield calendar.notifyChanged(category=ChangeCategory.default)
         self.assertEquals(
             set(self.notifierFactory.history),
             set([
-                ("/CalDAV/example.com/home1/", PushPriority.high),
-                ("/CalDAV/example.com/home1/calendar_1/", PushPriority.high)])
+                ("/CalDAV/example.com/user01/", PushPriority.high),
+                ("/CalDAV/example.com/user01/calendar_1/", PushPriority.high)])
         )
         yield self.commit()
 
@@ -232,28 +232,28 @@
     @inlineCallbacks
     def test_shareWithNotifier(self):
 
-        calendar = yield self.calendarUnderTest()
-        yield calendar.inviteUserToShare("home2", _BIND_MODE_WRITE, "")
+        calendar = yield self.calendarUnderTest(home="user01")
+        yield calendar.inviteUserToShare("user02", _BIND_MODE_WRITE, "")
         self.assertEquals(
             set(self.notifierFactory.history),
             set([
-                ("/CalDAV/example.com/home1/", PushPriority.high),
-                ("/CalDAV/example.com/home1/calendar_1/", PushPriority.high),
-                ("/CalDAV/example.com/home2/", PushPriority.high),
-                ("/CalDAV/example.com/home2/notification/", PushPriority.high),
+                ("/CalDAV/example.com/user01/", PushPriority.high),
+                ("/CalDAV/example.com/user01/calendar_1/", PushPriority.high),
+                ("/CalDAV/example.com/user02/", PushPriority.high),
+                ("/CalDAV/example.com/user02/notification/", PushPriority.high),
             ])
         )
         yield self.commit()
 
-        calendar = yield self.calendarUnderTest()
-        yield calendar.uninviteUserFromShare("home2")
+        calendar = yield self.calendarUnderTest(home="user01")
+        yield calendar.uninviteUserFromShare("user02")
         self.assertEquals(
             set(self.notifierFactory.history),
             set([
-                ("/CalDAV/example.com/home1/", PushPriority.high),
-                ("/CalDAV/example.com/home1/calendar_1/", PushPriority.high),
-                ("/CalDAV/example.com/home2/", PushPriority.high),
-                ("/CalDAV/example.com/home2/notification/", PushPriority.high),
+                ("/CalDAV/example.com/user01/", PushPriority.high),
+                ("/CalDAV/example.com/user01/calendar_1/", PushPriority.high),
+                ("/CalDAV/example.com/user02/", PushPriority.high),
+                ("/CalDAV/example.com/user02/notification/", PushPriority.high),
             ])
         )
         yield self.commit()
@@ -262,20 +262,20 @@
     @inlineCallbacks
     def test_sharedCalendarNotifier(self):
 
-        calendar = yield self.calendarUnderTest()
-        shareeView = yield calendar.inviteUserToShare("home2", _BIND_MODE_WRITE, "")
+        calendar = yield self.calendarUnderTest(home="user01")
+        shareeView = yield calendar.inviteUserToShare("user02", _BIND_MODE_WRITE, "")
         yield shareeView.acceptShare("")
         shareName = shareeView.name()
         yield self.commit()
         self.notifierFactory.reset()
 
-        shared = yield self.calendarUnderTest(home="home2", name=shareName)
+        shared = yield self.calendarUnderTest(home="user02", name=shareName)
         yield shared.notifyChanged(category=ChangeCategory.default)
         self.assertEquals(
             set(self.notifierFactory.history),
             set([
-                ("/CalDAV/example.com/home1/", PushPriority.high),
-                ("/CalDAV/example.com/home1/calendar_1/", PushPriority.high)])
+                ("/CalDAV/example.com/user01/", PushPriority.high),
+                ("/CalDAV/example.com/user01/calendar_1/", PushPriority.high)])
         )
         yield self.commit()
 
@@ -283,12 +283,12 @@
     @inlineCallbacks
     def test_notificationNotifier(self):
 
-        notifications = yield self.transactionUnderTest().notificationsWithUID("home1")
+        notifications = yield self.transactionUnderTest().notificationsWithUID("user01")
         yield notifications.notifyChanged(category=ChangeCategory.default)
         self.assertEquals(
             set(self.notifierFactory.history),
             set([
-                ("/CalDAV/example.com/home1/", PushPriority.high),
-                ("/CalDAV/example.com/home1/notification/", PushPriority.high)])
+                ("/CalDAV/example.com/user01/", PushPriority.high),
+                ("/CalDAV/example.com/user01/notification/", PushPriority.high)])
         )
         yield self.commit()

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/push/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/caldav.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/caldav.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: calendarserver.tap.test.test_caldav -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -1693,11 +1693,9 @@
                 raise StoreNotAvailable()
 
             from twisted.internet import reactor
-            pool = PeerConnectionPool(reactor, store.newTransaction,
-                                      7654, schema)
+            pool = PeerConnectionPool(reactor, store.newTransaction, config.WorkQueue.ampPort, schema)
             store.queuer = store.queuer.transferProposalCallbacks(pool)
-            controlSocket.addFactory(_QUEUE_ROUTE,
-                                     pool.workerListenerFactory())
+            controlSocket.addFactory(_QUEUE_ROUTE, pool.workerListenerFactory())
             # TODO: now that we have the shared control socket, we should get
             # rid of the connection dispenser and make a shared / async
             # connection pool implementation that can dispense transactions

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/cfgchild.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/cfgchild.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/cfgchild.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/profiling.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/profiling.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/profiling.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/longlines.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/longlines.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/longlines.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2007-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/test_caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/test_caldav.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/test_caldav.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2007-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/test_util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/test/test_util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2007-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tap/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: calendarserver.tap.test.test_caldav -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -92,6 +92,7 @@
 from calendarserver.webadmin.resource import WebAdminResource
 from calendarserver.webcal.resource import WebCalendarResource
 
+from txdav.common.datastore.podding.resource import ConduitResource
 from txdav.common.datastore.sql import CommonDataStore as CommonSQLDataStore
 from txdav.common.datastore.file import CommonDataStore as CommonFileDataStore
 from txdav.common.datastore.sql import current_sql_schema
@@ -407,6 +408,7 @@
     rootResourceClass = RootResource
     calendarResourceClass = DirectoryCalendarHomeProvisioningResource
     iScheduleResourceClass = IScheduleInboxResource
+    conduitResourceClass = ConduitResource
     timezoneServiceResourceClass = TimezoneServiceResource
     timezoneStdServiceResourceClass = TimezoneStdServiceResource
     webCalendarResourceClass = WebCalendarResource
@@ -636,7 +638,7 @@
             addSystemEventTrigger("after", "startup", timezoneStdService.onStartup)
 
     #
-    # iSchedule service for podding
+    # iSchedule/cross-pod service for podding
     #
     if config.Servers.Enabled:
         log.info("Setting up iSchedule podding inbox resource: {cls}", cls=iScheduleResourceClass)
@@ -648,6 +650,14 @@
         )
         root.putChild(config.Servers.InboxName, ischedule)
 
+        log.info("Setting up podding conduit resource: {cls}", cls=conduitResourceClass)
+
+        conduit = conduitResourceClass(
+            root,
+            newStore,
+        )
+        root.putChild(config.Servers.ConduitName, conduit)
+
     #
     # iSchedule service (not used for podding)
     #

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/test/test_logAnalysis.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/test/test_logAnalysis.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/test/test_logAnalysis.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/agent.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/agent.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/agent.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- test-case-name: calendarserver.tools.test.test_agent -*-
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/ampnotifications.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/ampnotifications.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/ampnotifications.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/anonymize.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/anonymize.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/anonymize.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/backup.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/backup.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/backup.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/backup_pg.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/backup_pg.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/backup_pg.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/bootstrapdatabase.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/bootstrapdatabase.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/bootstrapdatabase.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/calverify.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/calverify.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/calverify.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- test-case-name: calendarserver.tools.test.test_calverify -*-
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -72,6 +72,9 @@
 from twistedcaldav.util import normalizationLookup
 
 from txdav.caldav.icalendarstore import ComponentUpdateState
+from txdav.caldav.datastore.scheduling.icalsplitter import iCalSplitter
+from txdav.caldav.datastore.scheduling.implicit import ImplicitScheduler
+from txdav.caldav.datastore.sql import CalendarStoreFeatures
 from txdav.common.datastore.sql_tables import schema, _BIND_MODE_OWN
 from txdav.common.icommondatastore import InternalDataStoreError
 
@@ -206,7 +209,7 @@
 if not hasattr(Component, "maxAlarmCounts"):
     Component.hasDuplicateAlarms = new_hasDuplicateAlarms
 
-VERSION = "10"
+VERSION = "11"
 
 def printusage(e=None):
     if e:
@@ -240,6 +243,7 @@
                       with either --ical or --mismatch.
 --double            : detect double-bookings.
 --dark-purge        : purge room/resource events with invalid organizer
+--split             : split recurring event
 
 --nuke PATH|RID     : remove specific calendar resources - can
                       only be used by itself. PATH is the full
@@ -275,6 +279,10 @@
 --summary  : report only which GUIDs have double-bookings - no details.
 --days     : number of days ahead to scan [DEFAULT: 365]
 
+Options for --double:
+If none of (--no-organizer, --invalid-organizer, --disabled-organizer) is present, it
+will default to (--invalid-organizer, --disabled-organizer).
+
 Options for --dark-purge:
 
 --uuid     : only scan specified calendar homes. Can be a partial GUID
@@ -285,9 +293,12 @@
 --invalid-organizer  : only detect events with an organizer not in the directory
 --disabled-organizer : only detect events with an organizer disabled for calendaring
 
-If none of (--no-organizer, --invalid-organizer, --disabled-organizer) is present, it
-will default to (--invalid-organizer, --disabled-organizer).
+Options for --split:
 
+--path     : URI path to resource to split.
+--rid      : UTC date-time where split occurs (YYYYMMDDTHHMMSSZ).
+--summary  : only print a list of recurrences in the resource - no splitting.
+
 CHANGES
 v8: Detects ORGANIZER or ATTENDEE properties with mailto: calendar user
     addresses for users that have valid directory records. Fix is to
@@ -295,6 +306,10 @@
 
 v9: Detects double-bookings.
 
+v10: Purges data for invalid users.
+
+v11: Allows manual splitting of recurring events.
+
 """ % (VERSION,)
 
 
@@ -319,10 +334,11 @@
         ['missing', 'm', "Show 'orphaned' homes."],
         ['double', 'd', "Detect double-bookings."],
         ['dark-purge', 'p', "Purge room/resource events with invalid organizer."],
+        ['split', 'l', "Split an event."],
         ['fix', 'x', "Fix problems."],
         ['verbose', 'v', "Verbose logging."],
         ['details', 'V', "Detailed logging."],
-        ['summary', 'S', "Summary of double-bookings."],
+        ['summary', 'S', "Summary of double-bookings/split."],
         ['tzid', 't', "Timezone to adjust displayed times to."],
 
         ['no-organizer', '', "Detect dark events without an organizer"],
@@ -335,7 +351,9 @@
         ['uuid', 'u', "", "Only check this user."],
         ['uid', 'U', "", "Only this event UID."],
         ['nuke', 'e', "", "Remove event given its path."],
-        ['days', 'T', "365", "Number of days for scanning events into the future."]
+        ['days', 'T', "365", "Number of days for scanning events into the future."],
+        ['path', '', "", "Split event given its path."],
+        ['rid', '', "", "Split date-time."],
     ]
 
 
@@ -2670,6 +2688,122 @@
 
 
 
+class EventSplitService(CalVerifyService):
+    """
+    Service which splits a recurring event at a specific date-time value.
+    """
+
+    def title(self):
+        return "Event Split Service"
+
+
+    @inlineCallbacks
+    def doAction(self):
+        """
+        Split a resource using either its path or resource id.
+        """
+
+        self.txn = self.store.newTransaction()
+
+        path = self.options["path"]
+        if path.startswith("/calendars/__uids__/"):
+            try:
+                pathbits = path.split("/")
+            except TypeError:
+                printusage("Not a valid calendar object resource path: %s" % (path,))
+            if len(pathbits) != 6:
+                printusage("Not a valid calendar object resource path: %s" % (path,))
+            homeName = pathbits[3]
+            calendarName = pathbits[4]
+            resourceName = pathbits[5]
+
+            resid = yield self.getResourceID(homeName, calendarName, resourceName)
+            if resid is None:
+                yield self.txn.commit()
+                self.txn = None
+                self.output.write("\n")
+                self.output.write("Path does not exist. Nothing split.\n")
+                returnValue(None)
+            resid = int(resid)
+        else:
+            try:
+                resid = int(path)
+            except ValueError:
+                printusage("path argument must be a calendar object path or an SQL resource-id")
+
+        calendarObj = yield CalendarStoreFeatures(self.txn._store).calendarObjectWithID(self.txn, resid)
+        ical = yield calendarObj.component()
+
+        # Must be the ORGANIZER's copy
+        organizer = ical.getOrganizer()
+        if organizer is None:
+            printusage("Calendar object has no ORGANIZER property - cannot split")
+
+        # Only allow organizers to split
+        scheduler = ImplicitScheduler()
+        is_attendee = (yield scheduler.testAttendeeEvent(calendarObj.calendar(), calendarObj, ical,))
+        if is_attendee:
+            printusage("Calendar object is not owned by the ORGANIZER - cannot split")
+
+        if self.options["summary"]:
+            result = self.doSummary(ical)
+        else:
+            result = yield self.doSplit(resid, calendarObj, ical)
+
+        returnValue(result)
+
+
+    def doSummary(self, ical):
+        """
+        Print a summary of the recurrence instances of the specified event.
+
+        @param ical: calendar to process
+        @type ical: L{Component}
+        """
+        self.output.write("\n---- Calendar resource instances ----\n")
+
+        # Find the instance RECURRENCE-ID where a split is going to happen
+        now = DateTime.getNowUTC()
+        now.offsetDay(1)
+        instances = ical.cacheExpandedTimeRanges(now)
+        instances = sorted(instances.instances.values(), key=lambda x: x.start)
+        for instance in instances:
+            self.output.write(instance.rid.getText() + (" *\n" if instance.overridden else "\n"))
+
+
+    @inlineCallbacks
+    def doSplit(self, resid, calendarObj, ical):
+        rid = self.options["rid"]
+        try:
+            if rid[-1] != "Z":
+                raise ValueError
+            rid = DateTime.parseText(rid)
+        except ValueError:
+            printusage("rid must be a valid UTC date-time value: 'YYYYMMDDTHHMMSSZ'")
+
+        self.output.write("\n---- Splitting calendar resource ----\n")
+
+        # Find actual RECURRENCE-ID of split
+        splitter = iCalSplitter(1024, 14)
+        rid = splitter.whereSplit(ical, break_point=rid, allow_past_the_end=False)
+        if rid is None:
+            printusage("rid is not a valid recurrence instance")
+
+        self.output.write("\n")
+        self.output.write("Actual RECURRENCE-ID: %s.\n" % (rid,))
+
+        oldUID = yield calendarObj.split(rid=rid)
+
+        self.output.write("\n")
+        self.output.write("Split Resource: %s at %s, old UID: %s.\n" % (resid, rid, oldUID,))
+
+        yield self.txn.commit()
+        self.txn = None
+
+        returnValue(oldUID)
+
+
+
 def main(argv=sys.argv, stderr=sys.stderr, reactor=None):
 
     if reactor is None:
@@ -2702,6 +2836,8 @@
             return DoubleBookingService(store, options, output, reactor, config)
         elif options["dark-purge"]:
             return DarkPurgeService(store, options, output, reactor, config)
+        elif options["split"]:
+            return EventSplitService(store, options, output, reactor, config)
         else:
             printusage("Invalid operation")
             sys.exit(1)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/calverify_diff.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/calverify_diff.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/calverify_diff.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- test-case-name: calendarserver.tools.test.test_calverify -*-
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/changeip_calendar.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/changeip_calendar.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/changeip_calendar.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 #
 # changeip script for calendar server
 #
-# Copyright (c) 2005-2013 Apple Inc.  All Rights Reserved.
+# Copyright (c) 2005-2014 Apple Inc.  All Rights Reserved.
 #
 # IMPORTANT NOTE:  This file is licensed only for use on Apple-labeled
 # computers and is subject to the terms and conditions of the Apple

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/cmdline.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/cmdline.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/cmdline.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/config.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/config.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/config.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/dbinspect.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/dbinspect.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/dbinspect.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- test-case-name: calendarserver.tools.test.test_calverify -*-
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -37,8 +37,8 @@
 from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
 from twistedcaldav.directory import calendaruserproxy
 from twistedcaldav.directory.directory import DirectoryService
-from twistedcaldav.query import calendarqueryfilter
 from twistedcaldav.stdconfig import DEFAULT_CONFIG_FILE
+from txdav.caldav.datastore.query.filter import Filter
 from txdav.common.datastore.sql_tables import schema, _BIND_MODE_OWN
 from uuid import UUID
 import os
@@ -757,10 +757,10 @@
                           name="VCALENDAR",
                        )
                   )
-        filter = calendarqueryfilter.Filter(filter)
+        filter = Filter(filter)
         filter.settimezone(None)
 
-        matches = yield calendar._index.indexedSearch(filter, useruid=uid, fbtype=False)
+        matches = yield calendar.search(filter, useruid=uid, fbtype=False)
         if matches is None:
             returnValue(None)
         for name, _ignore_uid, _ignore_type in matches:

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/dkimtool.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/dkimtool.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/dkimtool.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/export.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/export.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/export.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- test-case-name: calendarserver.tools.test.test_export -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/gateway.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/gateway.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/gateway.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/icalsplit.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/icalsplit.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/icalsplit.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/loadaugmentdb.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/loadaugmentdb.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/loadaugmentdb.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/managepostgres.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/managepostgres.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/managepostgres.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/managetimezones.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/managetimezones.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/managetimezones.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/migrate.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/migrate.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/migrate.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/migrate_verify.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/migrate_verify.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/migrate_verify.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- test-case-name: calendarserver.tools.test.test_calverify -*-
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/notifications.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/notifications.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/notifications.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/obliterate.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/obliterate.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/obliterate.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- test-case-name: calendarserver.tools.test.test_calverify -*-
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/principals.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/principals.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/purge.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/purge.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/purge.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- test-case-name: calendarserver.tools.test.test_purge -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -30,10 +30,9 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 
 from twistedcaldav import caldavxml
-from twistedcaldav.caldavxml import TimeRange
 from twistedcaldav.directory.directory import DirectoryRecord
-from twistedcaldav.query import calendarqueryfilter
 
+from txdav.caldav.datastore.query.filter import Filter
 from txdav.xml import element as davxml
 
 
@@ -817,13 +816,13 @@
         query_filter = caldavxml.Filter(
               caldavxml.ComponentFilter(
                   caldavxml.ComponentFilter(
-                      TimeRange(start=whenString,),
+                      caldavxml.TimeRange(start=whenString,),
                       name=("VEVENT",),
                   ),
                   name="VCALENDAR",
                )
           )
-        query_filter = calendarqueryfilter.Filter(query_filter)
+        query_filter = Filter(query_filter)
 
         count = 0
         txn = self.store.newTransaction()
@@ -844,7 +843,7 @@
                     childNames.append(childName)
             else:
                 # events matching filter
-                for childName, _ignore_childUid, _ignore_childType in (yield calendar._index.indexedSearch(query_filter)):
+                for childName, _ignore_childUid, _ignore_childType in (yield calendar.search(query_filter)):
                     childNames.append(childName)
             yield txn.commit()
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/push.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/push.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/push.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/resources.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/resources.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/resources.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/cmd.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/cmd.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/cmd.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/directory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/directory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/directory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/terminal.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/terminal.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/terminal.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/test_cmd.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/test_cmd.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/test_cmd.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/test_vfs.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/test_vfs.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/test/test_vfs.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -28,45 +28,55 @@
 
 class TestListEntry(TestCase):
     def test_toString(self):
-        self.assertEquals(ListEntry(None, File  , "thingo"           ).toString(), "thingo" )
-        self.assertEquals(ListEntry(None, File  , "thingo", Foo="foo").toString(), "thingo" )
-        self.assertEquals(ListEntry(None, Folder, "thingo"           ).toString(), "thingo/")
+        self.assertEquals(ListEntry(None, File  , "thingo").toString(), "thingo")
+        self.assertEquals(ListEntry(None, File  , "thingo", Foo="foo").toString(), "thingo")
+        self.assertEquals(ListEntry(None, Folder, "thingo").toString(), "thingo/")
         self.assertEquals(ListEntry(None, Folder, "thingo", Foo="foo").toString(), "thingo/")
 
+
     def test_fieldNamesImplicit(self):
         # This test assumes File doesn't set list.fieldNames.
         assert not hasattr(File.list, "fieldNames")
 
         self.assertEquals(set(ListEntry(File(None, ()), File, "thingo").fieldNames), set(("Name",)))
 
+
     def test_fieldNamesExplicit(self):
         def fieldNames(fileClass):
             return ListEntry(fileClass(None, ()), fileClass, "thingo", Flavor="Coconut", Style="Hard")
 
         # Full list
-        class MyFile(File):
-            def list(self): return succeed(())
+        class MyFile1(File):
+            def list(self):
+                return succeed(())
             list.fieldNames = ("Name", "Flavor")
-        self.assertEquals(fieldNames(MyFile).fieldNames, ("Name", "Flavor"))
+        self.assertEquals(fieldNames(MyFile1).fieldNames, ("Name", "Flavor"))
 
+
         # Full list, different order
-        class MyFile(File):
-            def list(self): return succeed(())
+        class MyFile2(File):
+            def list(self):
+                return succeed(())
             list.fieldNames = ("Flavor", "Name")
-        self.assertEquals(fieldNames(MyFile).fieldNames, ("Flavor", "Name"))
+        self.assertEquals(fieldNames(MyFile2).fieldNames, ("Flavor", "Name"))
 
+
         # Omits Name, which is implicitly added
-        class MyFile(File):
-            def list(self): return succeed(())
+        class MyFile3(File):
+            def list(self):
+                return succeed(())
             list.fieldNames = ("Flavor",)
-        self.assertEquals(fieldNames(MyFile).fieldNames, ("Name", "Flavor"))
+        self.assertEquals(fieldNames(MyFile3).fieldNames, ("Name", "Flavor"))
 
+
         # Emtpy
-        class MyFile(File):
-            def list(self): return succeed(())
+        class MyFile4(File):
+            def list(self):
+                return succeed(())
             list.fieldNames = ()
-        self.assertEquals(fieldNames(MyFile).fieldNames, ("Name",))
+        self.assertEquals(fieldNames(MyFile4).fieldNames, ("Name",))
 
+
     def test_toFieldsImplicit(self):
         # This test assumes File doesn't set list.fieldNames.
         assert not hasattr(File.list, "fieldNames")
@@ -77,33 +87,41 @@
             ("thingo", "Coconut", "Hard")
         )
 
+
     def test_toFieldsExplicit(self):
         def fields(fileClass):
             return tuple(ListEntry(fileClass(None, ()), fileClass, "thingo", Flavor="Coconut", Style="Hard").toFields())
 
         # Full list
-        class MyFile(File):
-            def list(self): return succeed(())
+        class MyFile1(File):
+            def list(self):
+                return succeed(())
             list.fieldNames = ("Name", "Flavor")
-        self.assertEquals(fields(MyFile), ("thingo", "Coconut"))
+        self.assertEquals(fields(MyFile1), ("thingo", "Coconut"))
 
+
         # Full list, different order
-        class MyFile(File):
-            def list(self): return succeed(())
+        class MyFile2(File):
+            def list(self):
+                return succeed(())
             list.fieldNames = ("Flavor", "Name")
-        self.assertEquals(fields(MyFile), ("Coconut", "thingo"))
+        self.assertEquals(fields(MyFile2), ("Coconut", "thingo"))
 
+
         # Omits Name, which is implicitly added
-        class MyFile(File):
-            def list(self): return succeed(())
+        class MyFile3(File):
+            def list(self):
+                return succeed(())
             list.fieldNames = ("Flavor",)
-        self.assertEquals(fields(MyFile), ("thingo", "Coconut"))
+        self.assertEquals(fields(MyFile3), ("thingo", "Coconut"))
 
+
         # Emtpy
-        class MyFile(File):
-            def list(self): return succeed(())
+        class MyFile4(File):
+            def list(self):
+                return succeed(())
             list.fieldNames = ()
-        self.assertEquals(fields(MyFile), ("thingo",))
+        self.assertEquals(fields(MyFile4), ("thingo",))
 
 
 
@@ -114,6 +132,7 @@
     def __init__(self, testCase):
         self.testCase = testCase
 
+
     def mktemp(self):
         return self.testCase.mktemp()
 
@@ -129,8 +148,9 @@
         """
         Create a L{UIDsFolder}.
         """
-        self.svc = ShellService(store=(yield buildStore(self, None)),
-                                directory=DirectoryStubber(self).service(),
+        directory = DirectoryStubber(self).service()
+        self.svc = ShellService(store=(yield buildStore(self, None, directoryService=directory)),
+                                directory=directory,
                                 options=None, reactor=None, config=None)
         self.folder = UIDsFolder(self.svc, ())
 
@@ -156,6 +176,3 @@
               {"Record Type": "users", "Short Name": "dreid",
               "Full Name": "David Reid", "Name": dreid}]
         )
-
-
-

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/vfs.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/vfs.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/shell/vfs.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: calendarserver.tools.shell.test.test_vfs -*-
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/tables.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/tables.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/tables.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/calverify/accounts.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/calverify/accounts.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/calverify/accounts.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -47,4 +47,11 @@
     <name>Example User4</name>
     <email-address>example4 at example.com</email-address>
   </user>
+  <user>
+    <uid>home1</uid>
+    <guid>home1</guid>
+    <password>home1</password>
+    <name>Home 1</name>
+    <email-address>home1 at example.com</email-address>
+  </user>
 </accounts>

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/calverify/augments.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/calverify/augments.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/calverify/augments.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/augments.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/augments.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/augments.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/caldavd.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/caldavd.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/caldavd.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/resources-locations.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/resources-locations.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/resources-locations.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/users-groups.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/users-groups.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/deprovision/users-groups.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/augments.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/augments.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/augments.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/caldavd.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/caldavd.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/caldavd.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/resources-locations.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/resources-locations.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/resources-locations.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/users-groups.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/users-groups.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/gateway/users-groups.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/augments.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/augments.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/augments.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/caldavd.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/caldavd.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/caldavd.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/resources-locations.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/resources-locations.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/resources-locations.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/users-groups.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/users-groups.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/principals/users-groups.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/purge/accounts.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/purge/accounts.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/purge/accounts.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -26,4 +26,25 @@
     <name>Example User</name>
     <email-address>example at example.com</email-address>
   </user>
+  <user>
+    <uid>example2</uid>
+    <guid>37DB0C90-4DB1-4932-BC69-3DAB66F374F5</guid>
+    <password>example2</password>
+    <name>Example User 2</name>
+    <email-address>example2 at example.com</email-address>
+  </user>
+  <user>
+    <uid>home1</uid>
+    <guid>home1</guid>
+    <password>home1</password>
+    <name>Home 1</name>
+    <email-address>home1 at example.com</email-address>
+  </user>
+  <user>
+    <uid>home2</uid>
+    <guid>home2</guid>
+    <password>home2</password>
+    <name>Home 2</name>
+    <email-address>home2 at example.com</email-address>
+  </user>
 </accounts>

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_agent.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_agent.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_agent.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_calverify.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_calverify.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_calverify.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -20,7 +20,8 @@
 """
 
 from calendarserver.tools.calverify import BadDataService, \
-    SchedulingMismatchService, DoubleBookingService, DarkPurgeService
+    SchedulingMismatchService, DoubleBookingService, DarkPurgeService, \
+    EventSplitService
 
 from pycalendar.datetime import DateTime
 
@@ -28,6 +29,7 @@
 from twisted.internet.defer import inlineCallbacks
 
 from twistedcaldav.config import config
+from twistedcaldav.ical import normalize_iCalStr
 from twistedcaldav.test.util import StoreTestCase
 
 from txdav.common.datastore.test.util import populateCalendarsFrom
@@ -2806,3 +2808,323 @@
         self.assertEqual(len(calverify.results["Dark Events"]), 0)
         self.assertTrue("Fix dark events" not in calverify.results)
         self.assertTrue("Fix remove" not in calverify.results)
+
+
+
+class CalVerifyEventPurge(CalVerifyMismatchTestsBase):
+    """
+    Tests calverify for events.
+    """
+
+    # No organizer
+    NO_ORGANIZER_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_ORGANIZER_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_ORGANIZER_ICS
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+    # Valid organizer
+    VALID_ORGANIZER_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+BEGIN:VEVENT
+UID:INVITE_VALID_ORGANIZER_ICS
+DTSTART:%(now)s
+DURATION:PT1H
+ATTENDEE:urn:uuid:%(uuid1)s
+ATTENDEE:urn:uuid:%(uuid2)s
+ORGANIZER:urn:uuid:%(uuid1)s
+RRULE:FREQ=DAILY
+SUMMARY:INVITE_VALID_ORGANIZER_ICS
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+    # Valid attendee
+    VALID_ATTENDEE_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+BEGIN:VEVENT
+UID:INVITE_VALID_ORGANIZER_ICS
+DTSTART:%(now)s
+DURATION:PT1H
+ATTENDEE:urn:uuid:%(uuid1)s
+ATTENDEE:urn:uuid:%(uuid2)s
+ORGANIZER:urn:uuid:%(uuid1)s
+RRULE:FREQ=DAILY
+SUMMARY:INVITE_VALID_ORGANIZER_ICS
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+    # Valid organizer
+    VALID_ORGANIZER_FUTURE_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+BEGIN:VEVENT
+UID:INVITE_VALID_ORGANIZER_ICS
+DTSTART:%(now_fwd11)s
+DURATION:PT1H
+ATTENDEE:urn:uuid:%(uuid1)s
+ATTENDEE:urn:uuid:%(uuid2)s
+ORGANIZER:urn:uuid:%(uuid1)s
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY
+SEQUENCE:1
+SUMMARY:INVITE_VALID_ORGANIZER_ICS
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+    # Valid attendee
+    VALID_ATTENDEE_FUTURE_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+BEGIN:VEVENT
+UID:INVITE_VALID_ORGANIZER_ICS
+DTSTART:%(now_fwd11)s
+DURATION:PT1H
+ATTENDEE:urn:uuid:%(uuid1)s
+ATTENDEE:urn:uuid:%(uuid2)s
+ORGANIZER:urn:uuid:%(uuid1)s
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY
+SEQUENCE:1
+SUMMARY:INVITE_VALID_ORGANIZER_ICS
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+    # Valid organizer
+    VALID_ORGANIZER_PAST_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+BEGIN:VEVENT
+UID:%(relID)s
+DTSTART:%(now)s
+DURATION:PT1H
+ATTENDEE:urn:uuid:%(uuid1)s
+ATTENDEE:urn:uuid:%(uuid2)s
+ORGANIZER:urn:uuid:%(uuid1)s
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;UNTIL=%(now_fwd11_1)s
+SEQUENCE:1
+SUMMARY:INVITE_VALID_ORGANIZER_ICS
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+    # Valid attendee
+    VALID_ATTENDEE_PAST_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+BEGIN:VEVENT
+UID:%(relID)s
+DTSTART:%(now)s
+DURATION:PT1H
+ATTENDEE:urn:uuid:%(uuid1)s
+ATTENDEE:urn:uuid:%(uuid2)s
+ORGANIZER:urn:uuid:%(uuid1)s
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;UNTIL=%(now_fwd11_1)s
+SEQUENCE:1
+SUMMARY:INVITE_VALID_ORGANIZER_ICS
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+    # Valid organizer
+    VALID_ORGANIZER_OVERRIDE_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+BEGIN:VEVENT
+UID:VALID_ORGANIZER_OVERRIDE_ICS
+DTSTART:%(now)s
+DURATION:PT1H
+ATTENDEE:urn:uuid:%(uuid1)s
+ATTENDEE:urn:uuid:%(uuid2)s
+ORGANIZER:urn:uuid:%(uuid1)s
+RRULE:FREQ=DAILY
+SUMMARY:INVITE_VALID_ORGANIZER_ICS
+END:VEVENT
+BEGIN:VEVENT
+UID:VALID_ORGANIZER_OVERRIDE_ICS
+RECURRENCE-ID:%(now_fwd11)s
+DTSTART:%(now_fwd11)s
+DURATION:PT2H
+ATTENDEE:urn:uuid:%(uuid1)s
+ATTENDEE:urn:uuid:%(uuid2)s
+ORGANIZER:urn:uuid:%(uuid1)s
+RRULE:FREQ=DAILY
+SUMMARY:INVITE_VALID_ORGANIZER_ICS
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+    @inlineCallbacks
+    def setUp(self):
+
+        self.subs = {
+            "uuid1" : CalVerifyMismatchTestsBase.uuid1,
+            "uuid2" : CalVerifyMismatchTestsBase.uuid2,
+        }
+
+        self.now = DateTime.getNowUTC()
+        self.now.setHHMMSS(0, 0, 0)
+
+        self.subs["now"] = self.now
+
+        for i in range(30):
+            attrname = "now_back%s" % (i + 1,)
+            setattr(self, attrname, self.now.duplicate())
+            getattr(self, attrname).offsetDay(-(i + 1))
+            self.subs[attrname] = getattr(self, attrname)
+
+            attrname_12h = "now_back%s_12h" % (i + 1,)
+            setattr(self, attrname_12h, getattr(self, attrname).duplicate())
+            getattr(self, attrname_12h).offsetHours(12)
+            self.subs[attrname_12h] = getattr(self, attrname_12h)
+
+            attrname_1 = "now_back%s_1" % (i + 1,)
+            setattr(self, attrname_1, getattr(self, attrname).duplicate())
+            getattr(self, attrname_1).offsetSeconds(-1)
+            self.subs[attrname_1] = getattr(self, attrname_1)
+
+        for i in range(30):
+            attrname = "now_fwd%s" % (i + 1,)
+            setattr(self, attrname, self.now.duplicate())
+            getattr(self, attrname).offsetDay(i + 1)
+            self.subs[attrname] = getattr(self, attrname)
+
+            attrname_12h = "now_fwd%s_12h" % (i + 1,)
+            setattr(self, attrname_12h, getattr(self, attrname).duplicate())
+            getattr(self, attrname_12h).offsetHours(12)
+            self.subs[attrname_12h] = getattr(self, attrname_12h)
+
+            attrname_1 = "now_fwd%s_1" % (i + 1,)
+            setattr(self, attrname_1, getattr(self, attrname).duplicate())
+            getattr(self, attrname_1).offsetSeconds(-1)
+            self.subs[attrname_1] = getattr(self, attrname_1)
+
+        self.requirements = {
+            CalVerifyMismatchTestsBase.uuid1 : {
+                "calendar" : {
+                    "invite1.ics" : (self.NO_ORGANIZER_ICS % self.subs, CalVerifyMismatchTestsBase.metadata,),
+                    "invite2.ics" : (self.VALID_ORGANIZER_ICS % self.subs, CalVerifyMismatchTestsBase.metadata,),
+                    "invite3.ics" : (self.VALID_ORGANIZER_OVERRIDE_ICS % self.subs, CalVerifyMismatchTestsBase.metadata,),
+                },
+                "inbox" : {},
+            },
+            CalVerifyMismatchTestsBase.uuid2 : {
+                "calendar" : {
+                    "invite2a.ics" : (self.VALID_ATTENDEE_ICS % self.subs, CalVerifyMismatchTestsBase.metadata,),
+                },
+                "inbox" : {},
+            },
+            CalVerifyMismatchTestsBase.uuid3 : {
+                "calendar" : {},
+                "inbox" : {},
+            },
+            CalVerifyMismatchTestsBase.uuidl1 : {
+                "calendar" : {},
+                "inbox" : {},
+            },
+        }
+
+        yield super(CalVerifyEventPurge, self).setUp()
+
+
+    @inlineCallbacks
+    def test_validSplit(self):
+        """
+        CalVerifyService.doScan without fix for dark events. Make sure it detects
+        as much as it can. Make sure sync-token is not changed.
+        """
+
+        options = {
+            "nuke": False,
+            "missing": False,
+            "ical": False,
+            "mismatch": False,
+            "double": True,
+            "dark-purge": False,
+            "split": True,
+            "path": "/calendars/__uids__/%(uuid1)s/calendar/invite2.ics" % self.subs,
+            "rid": "%(now_fwd11)s" % self.subs,
+            "summary": False,
+        }
+        output = StringIO()
+        calverify = EventSplitService(self._sqlCalendarStore, options, output, reactor, config)
+        oldObj = yield calverify.doAction()
+        oldUID = oldObj.uid()
+
+        relsubs = dict(self.subs)
+        relsubs["relID"] = oldUID
+
+        calendar = yield self.calendarUnderTest(home=CalVerifyMismatchTestsBase.uuid1, name="calendar")
+        objs = yield calendar.listObjectResources()
+        self.assertEqual(len(objs), 4)
+        self.assertTrue("invite2.ics" in objs)
+        oldName = filter(lambda x: not x.startswith("invite"), objs)[0]
+
+        obj1 = yield calendar.objectResourceWithName("invite2.ics")
+        ical1 = yield obj1.component()
+        self.assertEqual(normalize_iCalStr(ical1), self.VALID_ORGANIZER_FUTURE_ICS % relsubs)
+
+        obj2 = yield calendar.objectResourceWithName(oldName)
+        ical2 = yield obj2.component()
+        self.assertEqual(normalize_iCalStr(ical2), self.VALID_ORGANIZER_PAST_ICS % relsubs)
+
+        calendar = yield self.calendarUnderTest(home=CalVerifyMismatchTestsBase.uuid2, name="calendar")
+        objs = yield calendar.listObjectResources()
+        self.assertEqual(len(objs), 2)
+        self.assertTrue("invite2a.ics" in objs)
+        oldName = filter(lambda x: not x.startswith("invite"), objs)[0]
+
+        obj1 = yield calendar.objectResourceWithName("invite2a.ics")
+        ical1 = yield obj1.component()
+        self.assertEqual(normalize_iCalStr(ical1), self.VALID_ATTENDEE_FUTURE_ICS % relsubs)
+
+        obj2 = yield calendar.objectResourceWithName(oldName)
+        ical2 = yield obj2.component()
+        self.assertEqual(normalize_iCalStr(ical2), self.VALID_ATTENDEE_PAST_ICS % relsubs)
+
+
+    @inlineCallbacks
+    def test_summary(self):
+        """
+        CalVerifyService.doScan without fix for dark events. Make sure it detects
+        as much as it can. Make sure sync-token is not changed.
+        """
+
+        options = {
+            "nuke": False,
+            "missing": False,
+            "ical": False,
+            "mismatch": False,
+            "double": True,
+            "dark-purge": False,
+            "split": True,
+            "path": "/calendars/__uids__/%(uuid1)s/calendar/invite3.ics" % self.subs,
+            "rid": "%(now_fwd11)s" % self.subs,
+            "summary": True,
+        }
+        output = StringIO()
+        calverify = EventSplitService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
+        result = output.getvalue().splitlines()
+        self.assertTrue("%(now)s" % self.subs in result)
+        self.assertTrue("%(now_fwd10)s" % self.subs in result)
+        self.assertTrue("%(now_fwd11)s *" % self.subs in result)
+        self.assertTrue("%(now_fwd12)s" % self.subs in result)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_changeip.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_changeip.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_changeip.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_config.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_config.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_config.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_export.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_export.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_export.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -277,7 +277,7 @@
         """
         yield populateCalendarsFrom(
             {
-                "home1": {
+                "user01": {
                     "calendar1": {
                         "valentines-day.ics": (valentines, {})
                     }
@@ -291,7 +291,7 @@
 
         io = StringIO()
         yield exportToFile(
-            [(yield self.txn().calendarHomeWithUID("home1"))
+            [(yield self.txn().calendarHomeWithUID("user01"))
               .calendarWithName("calendar1")], io
         )
         self.assertEquals(Component.fromString(io.getvalue()),
@@ -306,7 +306,7 @@
         """
         yield populateCalendarsFrom(
             {
-                "home1": {
+                "user01": {
                     "calendar1": {
                         "valentines-day.ics": (valentines, {}),
                         "new-years-day.ics": (newYears, {})
@@ -324,7 +324,7 @@
 
         io = StringIO()
         yield exportToFile(
-            [(yield self.txn().calendarHomeWithUID("home1"))
+            [(yield self.txn().calendarHomeWithUID("user01"))
               .calendarWithName("calendar1")], io
         )
         self.assertEquals(Component.fromString(io.getvalue()),
@@ -342,7 +342,7 @@
         """
         yield populateCalendarsFrom(
             {
-                "home1": {
+                "user01": {
                     "calendar1": {
                         "1.ics": (one, {}), # EST
                         "2.ics": (another, {}), # EST
@@ -354,7 +354,7 @@
 
         io = StringIO()
         yield exportToFile(
-            [(yield self.txn().calendarHomeWithUID("home1"))
+            [(yield self.txn().calendarHomeWithUID("user01"))
               .calendarWithName("calendar1")], io
         )
         result = Component.fromString(io.getvalue())

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_gateway.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_gateway.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_gateway.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_principals.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_principals.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_principals.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_purge.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_purge.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_purge.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -806,16 +806,6 @@
 
     @inlineCallbacks
     def setUp(self):
-        self.patch(config.DirectoryService.params, "xmlFile",
-            os.path.join(
-                os.path.dirname(__file__), "purge", "accounts.xml"
-            )
-        )
-        self.patch(config.ResourceService.params, "xmlFile",
-            os.path.join(
-                os.path.dirname(__file__), "purge", "resources.xml"
-            )
-        )
         yield super(PurgePrincipalTests, self).setUp()
 
         txn = self._sqlCalendarStore.newTransaction()
@@ -850,6 +840,20 @@
         (yield txn.commit())
 
 
+    def configure(self):
+        super(PurgePrincipalTests, self).configure()
+        self.patch(config.DirectoryService.params, "xmlFile",
+            os.path.join(
+                os.path.dirname(__file__), "purge", "accounts.xml"
+            )
+        )
+        self.patch(config.ResourceService.params, "xmlFile",
+            os.path.join(
+                os.path.dirname(__file__), "purge", "resources.xml"
+            )
+        )
+
+
     @inlineCallbacks
     def populate(self):
         yield populateCalendarsFrom(self.requirements, self.storeUnderTest())

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_purge_old_events.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_purge_old_events.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_purge_old_events.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_resources.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_resources.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_resources.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/test/test_util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/upgrade.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/upgrade.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- test-case-name: calendarserver.tools.test.test_upgrade -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/validcalendardata.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/validcalendardata.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/validcalendardata.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/workitems.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/workitems.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/tools/workitems.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: calendarserver.webadmin.test.test_resource -*-
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/test/test_resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webadmin/test/test_resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/test/test_resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/calendarserver/webcal/test/test_resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts-test.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts-test.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts-test.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts.dtd
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts.dtd	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts.dtd	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/accounts.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/augments-default.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/augments-default.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/augments-default.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/augments.dtd
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/augments.dtd	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/augments.dtd	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies-test-pod.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies-test-pod.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies-test-pod.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies-test.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies-test.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies-test.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies.dtd
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies.dtd	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/auth/proxies.dtd	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-apple.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-apple.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-apple.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-test-podB.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-test-podB.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-test-podB.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -43,6 +43,13 @@
     <array>
     </array>
 
+	<!--  Work Queue -->
+	<key>WorkQueue</key>
+	<dict>
+		<key>ampPort</key>
+		<integer>7655</integer>
+	</dict>
+
     <!-- Server root -->
     <key>ServerRoot</key>
     <string>./data/podB</string>
@@ -94,6 +101,19 @@
       </dict>
     </dict>
 
+    <!-- Sqlite ProxyDB Service - must use the same one as Pod A-->
+    <key>ProxyDBService</key>
+    <dict>
+      <key>type</key>
+      <string>twistedcaldav.directory.calendaruserproxy.ProxySqliteDB</string>
+      
+      <key>params</key>
+      <dict>
+        <key>dbpath</key>
+        <string>./data/podA/Data/proxies.sqlite</string>
+      </dict>
+    </dict>
+
     <key>ProxyLoadFromFile</key>
     <string>./conf/auth/proxies-test-pod.xml</string>
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-test.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-test.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd-test.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/caldavd.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers-test.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers-test.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers-test.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers.dtd
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers.dtd	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers.dtd	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 <!--
-Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/localservers.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers-test.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers-test.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers-test.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers.dtd
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers.dtd	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers.dtd	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/remoteservers.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/caldavd-resources.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/caldavd-resources.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/caldavd-resources.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/locations-resources-orig.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/locations-resources-orig.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/locations-resources-orig.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/locations-resources.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/locations-resources.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/locations-resources.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/users-groups.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/users-groups.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/resources/users-groups.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/resources.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/resources.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/resources.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/conf/test/accounts.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/conf/test/accounts.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/conf/test/accounts.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/launchd/calendarserver.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/launchd/calendarserver.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/launchd/calendarserver.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/_event_change.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/_event_change.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/_event_change.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/_event_create.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/_event_create.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/_event_create.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchlib.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchlib.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchlib.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchlib.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchlib.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchlib.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmark
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmark	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmark	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmark.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmark.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmark.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/bounded_recurrence.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/bounded_recurrence.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/bounded_recurrence.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/bounded_recurrence_autoaccept.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/bounded_recurrence_autoaccept.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/bounded_recurrence_autoaccept.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_add_attendee.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_add_attendee.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_add_attendee.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_autoaccept.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_autoaccept.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_autoaccept.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_change_date.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_change_date.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_change_date.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_change_summary.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_change_summary.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_change_summary.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_delete.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_delete.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_delete.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_delete_attendee.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_delete_attendee.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_delete_attendee.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_move.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_move.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/event_move.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/find_calendars.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/find_calendars.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/find_calendars.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/find_events.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/find_events.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/find_events.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/unbounded_recurrence.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/unbounded_recurrence.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/unbounded_recurrence.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/unbounded_recurrence_autoaccept.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/unbounded_recurrence_autoaccept.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/unbounded_recurrence_autoaccept.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/vfreebusy.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/vfreebusy.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/vfreebusy.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/vfreebusy_vary_attendees.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/vfreebusy_vary_attendees.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/benchmarks/vfreebusy_vary_attendees.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/compare
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/compare	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/compare	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/compare.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/compare.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/compare.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/display-calendar-events.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/display-calendar-events.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/display-calendar-events.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/extractconf
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/extractconf	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/extractconf	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/fix-units.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/fix-units.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/fix-units.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 --
--- Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+-- Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 --
 -- Licensed under the Apache License, Version 2.0 (the "License");
 -- you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/graph
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/graph	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/graph	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/graph.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/graph.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/graph.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/httpauth.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/httpauth.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/httpauth.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/httpclient.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/httpclient.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/httpclient.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/io_measure.d
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/io_measure.d	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/io_measure.d	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2010-2014 Apple Inc. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/ampsim.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/ampsim.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/ampsim.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/clients.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/clients.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/clients.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/config.dist.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/config.dist.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/config.dist.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/config.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/config.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/config.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/ical.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/ical.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/logger.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/logger.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/logger.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/population.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/population.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/population.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: contrib.performance.loadtest.test_population -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/profiles.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/profiles.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/profiles.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/sim.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/sim.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/sim.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: contrib.performance.loadtest.test_sim -*-
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_ical.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_ical.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_ical.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_population.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_population.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_population.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_profiles.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_profiles.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_profiles.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_sim.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_sim.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_sim.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_trafficlogger.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_trafficlogger.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_trafficlogger.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_webadmin.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_webadmin.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/test_webadmin.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/trafficlogger.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/trafficlogger.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/trafficlogger.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/webadmin.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/webadmin.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/loadtest/webadmin.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/massupload
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/massupload	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/massupload	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/massupload.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/massupload.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/massupload.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/nightly.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/nightly.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/nightly.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/bin/bash -x
 
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/pgsql.d
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/pgsql.d	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/pgsql.d	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2010-2014 Apple Inc. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/profile.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/profile.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/profile.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/bin/bash -x
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report_principals.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report_principals.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/report_principals.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/reupload.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/reupload.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/reupload.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/bin/bash -x
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sample-many.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sample-many.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sample-many.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sample.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sample.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sample.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash   
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/setbackend
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/setbackend	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/setbackend	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/setbackend.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/setbackend.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/setbackend.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sim
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sim	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sim	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/some-more-data.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/some-more-data.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/some-more-data.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/bin/bash -x
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/speedcenter.tac
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/speedcenter.tac	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/speedcenter.tac	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sql_measure.d
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sql_measure.d	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sql_measure.d	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2010-2014 Apple Inc. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/httpTests.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/httpTests.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/httpTests.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/invite.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/invite.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/invite.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/multiget.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/multiget.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/multiget.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/propfind.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/propfind.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/propfind.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/propfind_invite.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/propfind_invite.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/propfind_invite.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/put.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/put.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/put.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/query.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/query.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/query.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/sync.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/sync.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/requests/sync.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/sqlusage.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/sqlusage.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlusage/sqlusage.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlwatch
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlwatch	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlwatch	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlwatch.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlwatch.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sqlwatch.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/stackedbar.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/stackedbar.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/stackedbar.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/stats.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/stats.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/stats.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sudo-run.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sudo-run.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/sudo-run.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/svn-committime
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/svn-committime	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/svn-committime	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/svn-revno
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/svn-revno	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/svn-revno	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_benchmark.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_benchmark.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_benchmark.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_event_change_date.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_event_change_date.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_event_change_date.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_httpauth.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_httpauth.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_httpauth.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_stats.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_stats.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/test_stats.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/upload
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/upload	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/upload	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/upload.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/upload.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/performance/upload.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/anonymous_log.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/anonymous_log.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/anonymous_log.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/dtraceanalyze.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/dtraceanalyze.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/dtraceanalyze.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 # coding=utf-8
 
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/fakecalendardata.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/fakecalendardata.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/fakecalendardata.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/fix_calendar
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/fix_calendar	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/fix_calendar	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/harpoon.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/harpoon.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/harpoon.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/ngs/app/ical/code/bin/python
 
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/monitoranalysis.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/monitoranalysis.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/monitoranalysis.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/monitorsplit.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/monitorsplit.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/monitorsplit.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/netstatus.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/netstatus.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/netstatus.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/pg_stats_analysis.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/pg_stats_analysis.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/pg_stats_analysis.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/pgtrace.d
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/pgtrace.d	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/pgtrace.d	2014-01-12 19:10:08 UTC (rev 12322)
@@ -7,7 +7,7 @@
  *   Count postgres operations over time 
  * 
 ## 
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved. 
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved. 
 # 
 # Licensed under the Apache License, Version 2.0 (the "License"); 
 # you may not use this file except in compliance with the License. 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/protocolanalysis.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/protocolanalysis.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/protocolanalysis.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/readStats.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/readStats.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/readStats.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/request_monitor.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/request_monitor.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/request_monitor.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/sortrecurrences.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/sortrecurrences.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/sortrecurrences.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/sqldata_from_path.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/sqldata_from_path.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/sqldata_from_path.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/tables.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/tables.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/tables.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/test_protocolanalysis.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/test_protocolanalysis.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/tools/test_protocolanalysis.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/Makefile
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/Makefile	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/Makefile	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/caldav.js
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/caldav.js	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/caldav.js	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 /**
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/jcal.js
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/jcal.js	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/jcal.js	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 /**
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/utils.js
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/utils.js	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/utils.js	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 /**
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/webpoll.js
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/webpoll.js	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/contrib/webpoll/webapp/js/webpoll.js	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 /**
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Copied: CalendarServer/branches/users/gaya/cleanrevisions/doc/Extensions/caldav-recursplit.txt (from rev 12321, CalendarServer/trunk/doc/Extensions/caldav-recursplit.txt)
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/Extensions/caldav-recursplit.txt	                        (rev 0)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/Extensions/caldav-recursplit.txt	2014-01-12 19:10:08 UTC (rev 12322)
@@ -0,0 +1,504 @@
+
+
+
+Calendar Server Extension                                       C. Daboo
+                                                                   Apple
+                                                        January 10, 2014
+
+
+             Smart Splitting of Recurring Events in CalDAV
+
+Abstract
+
+   This document defines an extension to CalDAV that allows calendar
+   clients to split recurring events on the server in such a way as to
+   preserve the original per-attendee data, such as alarms and
+   participation status.
+
+
+Table of Contents
+
+   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . . . 2
+   2.  Conventions Used in This Document . . . . . . . . . . . . . . . 3
+   3.  New behavior  . . . . . . . . . . . . . . . . . . . . . . . . . 3
+     3.1.  Example . . . . . . . . . . . . . . . . . . . . . . . . . . 6
+   4.  Security Considerations . . . . . . . . . . . . . . . . . . . . 8
+   5.  IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 8
+   6.  Normative References  . . . . . . . . . . . . . . . . . . . . . 8
+   Appendix A.  Acknowledgments  . . . . . . . . . . . . . . . . . . . 9
+   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . . . 9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daboo                                                           [Page 1]
+
+                       CalDAV Recurrence Splitting          January 2014
+
+
+1.  Introduction
+
+   Internet calendaring and scheduling standards are defined by
+   iCalendar [RFC5545] and iTIP [RFC5546].  The CalDAV Access [RFC4791]
+   standard defines a way to access calendar data stored on a server,
+   and the CalDAV Scheduling [RFC6638] draft defines how scheduling
+   occurs between users of a CalDAV server.
+
+   When dealing with recurring events defined in iCalendar, it is often
+   necessary for the organizer of the events to apply a change from one
+   of the recurrence instances on into the future (e.g., add a new
+   attendee part way through the series of meetings). iCalendar supports
+   a "RANGE" property parameter on the "RECURRENCE-ID" property that
+   allows for a "THIS-AND-FUTURE" change to an existing set of recurring
+   events.  However, the "RANGE" behavior is not always implemented.
+   Instead, clients split the recurring series into two separate events
+   (different UIDs and thus different calendar object resources stored
+   in a CalDAV calendar).  One series contains all the instances up to
+   the point where the change is made, and the other contains all the
+   instances from that point onwards.  Typically this is done by
+   truncating the recurrence rule in the existing resource and creating
+   a new resource for the ongoing recurrence.  However, when done that
+   way, it results in any per-attendee data in the original resource for
+   recurrence instances after the "split point" being lost - i.e.,
+   attendee loose all their status for the ongoing instances.  What is
+   more, due to the requirements of CalDAV scheduling, the "PARTSTAT"
+   parameter on the "ATTENDEE" properties in the new calendar object
+   resource will be forcibly reset to "NEEDS-ACTION", requiring
+   attendees to re-accept/decline the ongoing recurrence series in the
+   new calendar object resource.  This is obviously a poor user
+   experience that needs to be corrected.
+
+   This specification defines a new CalDAV POST request action that
+   causes the server to split an existing calendar object resource
+   containing a recurring event, into two pieces at a specified "split
+   point", such that per-attendee data and attendee participation status
+   is preserved in the new calendar object resource created by the
+   split.  Once that is done, clients can then modify the new resource
+   to make the actual "this-and-future" change that triggers the split.
+
+   This specification does not cover the case of splitting of scheduled
+   calendar data for attendees not hosted on the CalDAV server.
+   Instead, existing existing procedures for sending iTIP messages have
+   to be used to update the attendee data to account for the split,
+   likely resulting in loss of per-attendee data.  A future extension to
+   iTIP might be possible to address that, but is not covered here.
+
+
+
+
+
+Daboo                                                           [Page 2]
+
+                       CalDAV Recurrence Splitting          January 2014
+
+
+2.  Conventions Used in This Document
+
+   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+   document are to be interpreted as described in [RFC2119].
+
+   When XML element types in the namespaces "DAV:" and
+   "urn:ietf:params:xml:ns:caldav" are referenced in this document
+   outside of the context of an XML fragment, the string "DAV:" and
+   "CALDAV:" will be prefixed to the element type names respectively.
+
+   The namespace "http://calendarserver.org/ns/" is used for XML
+   elements defined in this specification.  When XML element types in
+   this namespace are referenced in this document outside of the context
+   of an XML fragment, the string "CS:" will be prefixed to the element
+   type names respectively.
+
+   The prefix X-CALENDARSERVER- is used for all iCalendar properties,
+   parameters and enumerated values defined in this extension.
+
+
+3.  New behavior
+
+   A server supporting the features described in this specification MUST
+   include "calendarserver-recurrence-split" as a field in the DAV
+   response header from an OPTIONS request on a calendar home
+   collection.
+
+   To split an existing calendar object resource containing a recurring
+   event, a client issues an HTTP POST resource with the request-uri set
+   to the URI of the calendar object resource.  The client also includes
+   the following two URI query parameters:
+
+   1.  "action" set to the value "split"
+
+   2.  "rid" set to an iCalendar format DATE-TIME value in UTC
+       ("YYYYMMDDTHHMMSSZ" style format).
+
+   The "action" parameter is used to distinguish this operation from
+   others that might be defined in the future for calendar object
+   resources.  The "rid" parameter specified the UTC date-time where the
+   split is to occur.  The actual split occurs at the next recurrence
+   instance on or after the "rid" parameter value - the "split point".
+
+   Client MUST include both parameters in the POST request and MUST
+   ensure a valid date-time value is used.  The date-time value MUST NOT
+   be earlier than the start time of the first instance of the
+   recurrence set, and it MUST NOT be later than the start time of the
+
+
+
+Daboo                                                           [Page 3]
+
+                       CalDAV Recurrence Splitting          January 2014
+
+
+   last instance of the recurrence set.  If the "rid" parameter value is
+   not of the correct format or missing, the server MUST return a DAV:
+   error response with the CALDAV:valid-rid-parameter pre-condition
+   code.  If the "rid" parameter is valid, but outside of the allowed
+   range, or the targeted calendar object resource is not recurring,
+   then the server MUST return a DAV:error response with the CS:invalid-
+   split pre-condition code.  The server MUST reject any attempt by an
+   attendee to split their copy of a scheduled calendar object resource
+   - only organizers are allowed to split events.
+
+   Clients MAY include an HTTP "Prefer" request header including the
+   value "return=representation" (see [I-D.snell-http-prefer]).  That
+   instructs the server to return a WebDAV multistatus response
+   containing two responses: one for the targeted resource and one for
+   the new resource created as a result of the split.  The multistatus
+   response MUST include the DAV:getetag and CALDAV:calendar-data
+   properties for each resource.  In the absence of the "Prefer:
+   return=representation" request header, the server MUST return an HTTP
+   "Split-Component-URL" response header whose value is the URI of the
+   new resource created as a result of the split.
+
+   When a server receives a valid split request as described above, it
+   does the equivalent of the following:
+
+   1.  The existing resource is duplicated, preserving any per-user data
+       such as alarms or transparency status.
+
+   2.  The calendar data in the existing resource is modified as
+       follows:
+
+       A.  Any overridden components with a "RECURRENCE-ID" property
+           value prior to the split point are removed.
+
+       B.  Any "RDATE" or "EXDATE" property values prior to the split
+           point are removed.
+
+       C.  Any "RRULE" property that only generates instances prior to
+           the split point is removed.
+
+       D.  Any remaining "RRULE" property has its "COUNT" value adjusted
+           by subtracting the number of instances prior to the split
+           point.
+
+       E.  The "DTSTART" property of the master instance is adjusted to
+           the value of the first instance of the "RRULE" on or after
+           the split point, or, in the absence of an "RRULE", to the
+           first "RDATE" property value on or after the split point.
+
+
+
+
+Daboo                                                           [Page 4]
+
+                       CalDAV Recurrence Splitting          January 2014
+
+
+   3.  The calendar data in the new resource is modified as follows:
+
+       A.  Any overridden components with a "RECURRENCE-ID" property
+           value on or after the split point are removed.
+
+       B.  Any "RDATE" or "EXDATE" property values on or after the split
+           point are removed.
+
+       C.  Any "RRULE" property that only generates instances on or
+           after the split point is removed.
+
+       D.  Any remaining "RRULE" property has an "UNTIL" value applied,
+           with the until value being one second less than the split
+           point.
+
+       E.  The "UID" property of all components is changed to (the same)
+           new value.
+
+       F.  Attendee participation status MUST NOT be changed.
+
+   4.  The server MUST add a "RELATED" property, with a "RELTYPE"
+       parameter set to "X-CALENDARSERVER-RECURRENCE-SET", and with its
+       value set to the "UID" property value of the new resource to all
+       components of the existing and new resources, if the existing
+       resource does not contain a "RELATED" property with a "RELTYPE"
+       parameter value set to "X-CALENDARSERVER-RECURRENCE-SET".
+
+   When an organizer splits a scheduled event, the server performs the
+   following actions:
+
+   1.  For each attendee hosted on the same server, the server MUST
+       split the attendee's copy of the event in accordance with the
+       split point used by the organizer.  In doing so, it MUST preserve
+       any per-attendee state (alarms, transparency, participation
+       status) in the new resource (which also MUST have the same "UID"
+       property value as the organizer's new resource).
+
+   2.  For each attendee not hosted on the same server, the server will
+       need to send a series of iTIP messages to correctly update the
+       attendee with both the modified (old) resource data and the new
+       resource.  This will likely result in loss of per-attendee data
+       such as alarms (though the participation status might be
+       preserved if the calendar user agent processing the new iTIP
+       message for the new resource allows it).
+
+   Note that, since attendees can be invited to specific instances of a
+   recurring meeting (not necessarily the entire set), it is possible
+   that either the old or new calendar data no longer contains any valid
+
+
+
+Daboo                                                           [Page 5]
+
+                       CalDAV Recurrence Splitting          January 2014
+
+
+   components since the attendee was not invited to the corresponding
+   portions of the original split recurrence.  In such cases, the server
+   MUST remove the original resource, or MUST NOT create the new
+   resource.
+
+3.1.  Example
+
+   Assume the following iCalendar data is stored in the resource with
+   URI "/event.ics":
+   BEGIN:VCALENDAR
+   PRODID:-//Example Inc.//Example Calendar//EN
+   VERSION:2.0
+   BEGIN:VEVENT
+   DTSTAMP:20140110T135358Z
+   DTSTART:20140101T120000Z
+   DURATION:PT1H
+   SUMMARY:Example
+   UID:DF400028-1223-4D26-92CA-B0ED3CC161F3
+   RRULE:FREQ=DAILY;COUNT=20
+   END:VEVENT
+   END:VCALENDAR
+
+   The client issues a POST split request to split the recurring event
+   at the instance with date-time "20140110T120000Z":
+
+   >> Request <<
+
+   POST /event.ics?action=split&rid=20140110T120000Z HTTP/1.1
+   Host: cal.example.com
+   Content-Length: 0
+   Prefer: return=representation
+
+
+   >> Response <<
+
+   HTTP/1.1 207 Multi-Status
+   ETag: "5bc9a2b55081eba0a9cd34f742aa1c11"
+   Date: Fri, 10 Jan 2014 14:02:20 GMT
+   Content-Type: text/xml
+   Content-Length: xxxx
+
+   <?xml version='1.0' encoding='UTF-8'?>
+   <multistatus xmlns='DAV:'>
+     <response>
+       <href>/event.ics</href>
+       <propstat>
+         <prop>
+           <getetag>"5bc9a2b55081eba0a9cd34f742aa1c11"</getetag>
+
+
+
+Daboo                                                           [Page 6]
+
+                       CalDAV Recurrence Splitting          January 2014
+
+
+           <calendar-data xmlns='urn:ietf:params:xml:ns:caldav'
+   >BEGIN:VCALENDAR
+   VERSION:2.0
+   PRODID:-//Example Inc.//Example Calendar//EN
+   BEGIN:VEVENT
+   UID:DF400028-1223-4D26-92CA-B0ED3CC161F3
+   DTSTART:20140110T120000Z
+   DURATION:PT1H
+   DTSTAMP:20140110T135358Z
+   RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:E3B9D6D4-E19F-
+    47AA-9088-1A29A9A7030F
+   RRULE:FREQ=DAILY;COUNT=11
+   SUMMARY:Example
+   END:VEVENT
+   END:VCALENDAR
+   </calendar-data>
+         </prop>
+         <status>HTTP/1.1 200 OK</status>
+       </propstat>
+     </response>
+     <response>
+       <href>/event-split.ics</href>
+       <propstat>
+         <prop>
+           <getetag>"8b352ad2e0ca26c99cb205373b3dc34c"</getetag>
+           <calendar-data xmlns='urn:ietf:params:xml:ns:caldav'
+   >BEGIN:VCALENDAR
+   VERSION:2.0
+   PRODID:-//Example Inc.//Example Calendar//EN
+   BEGIN:VEVENT
+   UID:E3B9D6D4-E19F-47AA-9088-1A29A9A7030F
+   DTSTART:20140110T120000Z
+   DURATION:PT1H
+   DTSTAMP:20140110T135358Z
+   RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:E3B9D6D4-E19F-
+    47AA-9088-1A29A9A7030F
+   RRULE:FREQ=DAILY;UNTIL=20140110T115959Z
+   SUMMARY:Example
+   END:VEVENT
+   END:VCALENDAR
+   </calendar-data>
+         </prop>
+         <status>HTTP/1.1 200 OK</status>
+       </propstat>
+     </response>
+   </multistatus>
+
+   The original resource is changed to have a start date-time value of
+
+
+
+Daboo                                                           [Page 7]
+
+                       CalDAV Recurrence Splitting          January 2014
+
+
+   "20140110T120000Z", and the "COUNT" component of the "RRULE" property
+   is adjusted to the value "11" (which represents the number of
+   remaining instances for that event, 9 early instances having been
+   removed).  The new resource has the original start date-time value,
+   and its "RRULE" property has an "UNTIL" value one second prior to the
+   split point.  Both resources have a "RELATED" property with a
+   "RELTYPE" parameter set to "X-CALENDARSERVER-RECURRENCE-SET" and a
+   value set to the "UID" property value of the new resource.
+
+
+4.  Security Considerations
+
+   This specification does not introduce any more security
+   considerations beyond those already listed in iCalendar [RFC5545],
+   iTIP [RFC5546] and CalDAV Access [RFC4791] and CalDAV Scheduling
+   [RFC6638].
+
+
+5.  IANA Considerations
+
+   TBD: new HTTP request header registration.
+
+
+6.  Normative References
+
+   [I-D.snell-http-prefer]
+              Snell, J., "Prefer Header for HTTP",
+              draft-snell-http-prefer-18 (work in progress),
+              January 2013.
+
+   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
+              Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+   [RFC4791]  Daboo, C., Desruisseaux, B., and L. Dusseault,
+              "Calendaring Extensions to WebDAV (CalDAV)", RFC 4791,
+              March 2007.
+
+   [RFC5545]  Desruisseaux, B., "Internet Calendaring and Scheduling
+              Core Object Specification (iCalendar)", RFC 5545,
+              September 2009.
+
+   [RFC5546]  Daboo, C., "iCalendar Transport-Independent
+              Interoperability Protocol (iTIP)", RFC 5546,
+              December 2009.
+
+   [RFC6638]  Daboo, C. and B. Desruisseaux, "Scheduling Extensions to
+              CalDAV", RFC 6638, June 2012.
+
+
+
+
+Daboo                                                           [Page 8]
+
+                       CalDAV Recurrence Splitting          January 2014
+
+
+Appendix A.  Acknowledgments
+
+   This specification is the result of discussions between the Apple
+   calendar server and client teams.
+
+
+Author's Address
+
+   Cyrus Daboo
+   Apple Inc.
+   1 Infinite Loop
+   Cupertino, CA  95014
+   USA
+
+   Email: cyrus at daboo.name
+   URI:   http://www.apple.com/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daboo                                                           [Page 9]
+

Copied: CalendarServer/branches/users/gaya/cleanrevisions/doc/Extensions/caldav-recursplit.xml (from rev 12321, CalendarServer/trunk/doc/Extensions/caldav-recursplit.xml)
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/Extensions/caldav-recursplit.xml	                        (rev 0)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/Extensions/caldav-recursplit.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="../rfc2629.xslt"?>
+<!DOCTYPE rfc SYSTEM 'rfc2629.dtd' [
+<!ENTITY rfc2119 PUBLIC '' 'bibxml/reference.RFC.2119.xml'>
+<!ENTITY rfc5545 PUBLIC '' 'bibxml/reference.RFC.5545.xml'>
+<!ENTITY rfc5546 PUBLIC '' 'bibxml/reference.RFC.5546.xml'>
+<!ENTITY rfc4791 PUBLIC '' 'bibxml/reference.RFC.4791.xml'>
+<!ENTITY rfc6638 PUBLIC '' 'bibxml/reference.RFC.6638.xml'>
+<!ENTITY idPreferHeader SYSTEM 'http://xml.resource.org/public/rfc/bibxml3/reference.I-D.snell-http-prefer.xml'>
+]> 
+<?rfc toc="yes"?>
+<?rfc tocdepth="4"?>
+<?rfc strict="yes"?>
+<?rfc comments="yes"?>
+<?rfc inline="yes"?>
+<?rfc symrefs="yes"?>
+<?rfc sortrefs="yes"?>
+<?rfc compact="yes"?>
+<?rfc subcompact="no"?>
+<?rfc private="Calendar Server Extension"?>
+<rfc ipr="none" docName='caldav-recursplit-00'>
+    <front>
+        <title abbrev="CalDAV Recurrence Splitting">Smart Splitting of Recurring Events in CalDAV</title> 
+        <author initials="C." surname="Daboo" fullname="Cyrus Daboo">
+            <organization abbrev="Apple">
+                Apple Inc.
+            </organization>
+            <address>
+                <postal>
+                    <street>1 Infinite Loop</street>
+                    <city>Cupertino</city>
+                    <region>CA</region>
+                    <code>95014</code> 
+                    <country>USA</country>
+                </postal>
+                <email>cyrus at daboo.name</email>
+                <uri>http://www.apple.com/</uri>
+            </address>
+        </author>
+        <date />
+        <abstract>
+            <t>
+                This document defines an extension to CalDAV that allows calendar clients to split recurring events on the server in such a way as to preserve the original per-attendee data, such as alarms and participation status.
+            </t>
+        </abstract>
+    </front>
+    <middle>
+        <section title='Introduction'>
+            <t>
+                Internet calendaring and scheduling standards are defined by <xref target="RFC5545">iCalendar</xref> and <xref target="RFC5546">iTIP</xref>. The <xref target="RFC4791">CalDAV Access</xref> standard defines a way to access calendar data stored on a server, and the <xref target="RFC6638">CalDAV Scheduling</xref> draft defines how scheduling occurs between users of a CalDAV server.
+            </t>
+            <t>
+                When dealing with recurring events defined in iCalendar, it is often necessary for the organizer of the events to apply a change from one of the recurrence instances on into the future (e.g., add a new attendee part way through the series of meetings). iCalendar supports a "RANGE" property parameter on the "RECURRENCE-ID" property that allows for a "THIS-AND-FUTURE" change to an existing set of recurring events. However, the "RANGE" behavior is not always implemented. Instead, clients split the recurring series into two separate events (different UIDs and thus different calendar object resources stored in a CalDAV calendar). One series contains all the instances up to the point where the change is made, and the other contains all the instances from that point onwards. Typically this is done by truncating the recurrence rule in the existing resource and creating a new resource for the ongoing recurrence. However, when done that way, it results in any per-attendee data in the original resource for recurrence instances after the "split point" being lost - i.e., attendee loose all their status for the ongoing instances. What is more, due to the requirements of CalDAV scheduling, the "PARTSTAT" parameter on the "ATTENDEE" properties in the new calendar object resource will be forcibly reset to "NEEDS-ACTION", requiring attendees to re-accept/decline the ongoing recurrence series in the new calendar object resource. This is obviously a poor user experience that needs to be corrected.
+            </t>
+            <t>
+                This specification defines a new CalDAV POST request action that causes the server to split an existing calendar object resource containing a recurring event, into two pieces at a specified "split point", such that per-attendee data and attendee participation status is preserved in the new calendar object resource created by the split. Once that is done, clients can then modify the new resource to make the actual "this-and-future" change that triggers the split.
+            </t>
+            <t>
+              This specification does not cover the case of splitting of scheduled calendar data for attendees not hosted on the CalDAV server. Instead, existing existing procedures for sending iTIP messages have to be used to update the attendee data to account for the split, likely resulting in loss of per-attendee data. A future extension to iTIP might be possible to address that, but is not covered here.
+            </t>
+        </section>
+        <section title='Conventions Used in This Document'>
+            <t>
+                The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in <xref target='RFC2119' />. 
+            </t>
+            <t>
+                When XML element types in the namespaces "DAV:" and "urn:ietf:params:xml:ns:caldav" are referenced in this document outside of the context of an XML fragment, the string "DAV:" and "CALDAV:" will be prefixed to the element type names respectively. 
+            </t>
+            <t>
+                The namespace "http://calendarserver.org/ns/" is used for XML elements defined in this specification.  When XML element types in this namespace are referenced in this document outside of the context of an XML fragment, the string "CS:" will be prefixed to the element type names respectively. 
+            </t>
+            <t>
+                The prefix X-CALENDARSERVER- is used for all iCalendar properties, parameters and enumerated values defined in this extension. 
+            </t>
+        </section>
+        
+        <section title="New behavior">
+          <t>A server supporting the features described in this specification MUST include "calendarserver-recurrence-split" as a field in the DAV response header from an OPTIONS request on a calendar home collection.</t>
+          <t>To split an existing calendar object resource containing a recurring event, a client issues an HTTP POST resource with the request-uri set to the URI of the calendar object resource. The client also includes the following two URI query parameters:
+            <list style='numbers'>
+              <t>"action" set to the value "split"</t>
+              <t>"rid" set to an iCalendar format DATE-TIME value in UTC ("YYYYMMDDTHHMMSSZ" style format).</t>
+            </list>
+            The "action" parameter is used to distinguish this operation from others that might be defined in the future for calendar object resources. The "rid" parameter specified the UTC date-time where the split is to occur. The actual split occurs at the next recurrence instance on or after the "rid" parameter value - the "split point".</t>
+            <t>
+            Client MUST include both parameters in the POST request and MUST ensure a valid date-time value is used. The date-time value MUST NOT be earlier than the start time of the first instance of the recurrence set, and it MUST NOT be later than the start time of the last instance of the recurrence set. If the "rid" parameter value is not of the correct format or missing, the server MUST return a DAV:error response with the CALDAV:valid-rid-parameter pre-condition code. If the "rid" parameter is valid, but outside of the allowed range, or the targeted calendar object resource is not recurring, then the server MUST return a DAV:error response with the CS:invalid-split pre-condition code. The server MUST reject any attempt by an attendee to split their copy of a scheduled calendar object resource - only organizers are allowed to split events.
+          </t>
+          <t>
+            Clients MAY include an HTTP "Prefer" request header including the value "return=representation" (see <xref target='I-D.snell-http-prefer'/>). That instructs the server to return a WebDAV multistatus response containing two responses: one for the targeted resource and one for the new resource created as a result of the split. The multistatus response MUST include the DAV:getetag and CALDAV:calendar-data properties for each resource. In the absence of the "Prefer:return=representation" request header, the server MUST return an HTTP "Split-Component-URL" response header whose value is the URI of the new resource created as a result of the split.
+          </t>
+          <t>
+            When a server receives a valid split request as described above, it does the equivalent of the following:
+            <list style='numbers'>
+              <t>The existing resource is duplicated, preserving any per-user data such as alarms or transparency status.</t>
+              <t>The calendar data in the existing resource is modified as follows:
+                <list style='letters'>
+                  <t>Any overridden components with a "RECURRENCE-ID" property value prior to the split point are removed.</t>
+                  <t>Any "RDATE" or "EXDATE" property values prior to the split point are removed.</t>
+                  <t>Any "RRULE" property that only generates instances prior to the split point is removed.</t>
+                  <t>Any remaining "RRULE" property has its "COUNT" value adjusted by subtracting the number of instances prior to the split point.</t>
+                  <t>The "DTSTART" property of the master instance is adjusted to the value of the first instance of the "RRULE" on or after the split point, or, in the absence of an "RRULE", to the first "RDATE" property value on or after the split point.</t>
+                </list>
+              </t>
+              <t>The calendar data in the new resource is modified as follows:
+                <list style='letters'>
+                  <t>Any overridden components with a "RECURRENCE-ID" property value on or after the split point are removed.</t>
+                  <t>Any "RDATE" or "EXDATE" property values on or after the split point are removed.</t>
+                  <t>Any "RRULE" property that only generates instances on or after the split point is removed.</t>
+                  <t>Any remaining "RRULE" property has an "UNTIL" value applied, with the until value being one second less than the split point.</t>
+                  <t>The "UID" property of all components is changed to (the same) new value.</t>
+                  <t>Attendee participation status MUST NOT be changed.</t>
+                </list>
+              </t>
+              <t>
+                The server MUST add a "RELATED" property, with a "RELTYPE" parameter set to "X-CALENDARSERVER-RECURRENCE-SET", and with its value set to the "UID" property value of the new resource to all components of the existing and new resources, if the existing resource does not contain a "RELATED" property with a "RELTYPE" parameter value set to "X-CALENDARSERVER-RECURRENCE-SET". 
+              </t>
+            </list>
+          </t>
+          <t>
+              When an organizer splits a scheduled event, the server performs the following actions:
+            <list style="numbers">
+              <t>For each attendee hosted on the same server, the server MUST split the attendee's copy of the event in accordance with the split point used by the organizer. In doing so, it MUST preserve any per-attendee state (alarms, transparency, participation status) in the new resource (which also MUST have the same "UID" property value as the organizer's new resource).</t>
+              <t>For each attendee not hosted on the same server, the server will need to send a series of iTIP messages to correctly update the attendee with both the modified (old) resource data and the new resource. This will likely result in loss of per-attendee data such as alarms (though the participation status might be preserved if the calendar user agent processing the new iTIP message for the new resource allows it).</t>
+            </list>
+          </t>
+          <t>
+            Note that, since attendees can be invited to specific instances of a recurring meeting (not necessarily the entire set), it is possible that either the old or new calendar data no longer contains any valid components since the attendee was not invited to the corresponding portions of the original split recurrence. In such cases, the server MUST remove the original resource, or MUST NOT create the new resource.
+          </t>
+          <section title='Example'>
+            <t>Assume the following iCalendar data is stored in the resource with URI "/event.ics":
+            <figure><artwork><![CDATA[BEGIN:VCALENDAR
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTAMP:20140110T135358Z
+DTSTART:20140101T120000Z
+DURATION:PT1H
+SUMMARY:Example
+UID:DF400028-1223-4D26-92CA-B0ED3CC161F3
+RRULE:FREQ=DAILY;COUNT=20
+END:VEVENT
+END:VCALENDAR
+]]></artwork></figure>
+            </t>
+            <t>
+              The client issues a POST split request to split the recurring event at the instance with date-time "20140110T120000Z":
+        <figure>
+          <preamble>
+            &gt;&gt; Request &lt;&lt;
+          </preamble>
+          <artwork>
+<![CDATA[POST /event.ics?action=split&rid=20140110T120000Z HTTP/1.1
+Host: cal.example.com
+Content-Length: 0
+Prefer: return=representation
+
+]]></artwork> </figure>
+        <figure>
+          <preamble>
+            &gt;&gt; Response &lt;&lt;
+          </preamble>
+          <artwork>
+<![CDATA[HTTP/1.1 207 Multi-Status
+ETag: "5bc9a2b55081eba0a9cd34f742aa1c11"
+Date: Fri, 10 Jan 2014 14:02:20 GMT
+Content-Type: text/xml
+Content-Length: xxxx
+
+<?xml version='1.0' encoding='UTF-8'?>
+<multistatus xmlns='DAV:'>
+  <response>
+    <href>/event.ics</href>
+    <propstat>
+      <prop>
+        <getetag>"5bc9a2b55081eba0a9cd34f742aa1c11"</getetag>
+        <calendar-data xmlns='urn:ietf:params:xml:ns:caldav'
+>BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:DF400028-1223-4D26-92CA-B0ED3CC161F3
+DTSTART:20140110T120000Z
+DURATION:PT1H
+DTSTAMP:20140110T135358Z
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:E3B9D6D4-E19F-
+ 47AA-9088-1A29A9A7030F
+RRULE:FREQ=DAILY;COUNT=11
+SUMMARY:Example
+END:VEVENT
+END:VCALENDAR
+</calendar-data>
+      </prop>
+      <status>HTTP/1.1 200 OK</status>
+    </propstat>
+  </response>
+  <response>
+    <href>/event-split.ics</href>
+    <propstat>
+      <prop>
+        <getetag>"8b352ad2e0ca26c99cb205373b3dc34c"</getetag>
+        <calendar-data xmlns='urn:ietf:params:xml:ns:caldav'
+>BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:E3B9D6D4-E19F-47AA-9088-1A29A9A7030F
+DTSTART:20140110T120000Z
+DURATION:PT1H
+DTSTAMP:20140110T135358Z
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:E3B9D6D4-E19F-
+ 47AA-9088-1A29A9A7030F
+RRULE:FREQ=DAILY;UNTIL=20140110T115959Z
+SUMMARY:Example
+END:VEVENT
+END:VCALENDAR
+</calendar-data>
+      </prop>
+      <status>HTTP/1.1 200 OK</status>
+    </propstat>
+  </response>
+</multistatus>
+]]></artwork></figure>
+            </t>
+            <t>
+              The original resource is changed to have a start date-time value of "20140110T120000Z", and the "COUNT" component of the "RRULE" property is adjusted to the value "11" (which represents the number of remaining instances for that event, 9 early instances having been removed). The new resource has the original start date-time value, and its "RRULE" property has an "UNTIL" value one second prior to the split point. Both resources have a "RELATED" property with a "RELTYPE" parameter set to "X-CALENDARSERVER-RECURRENCE-SET" and a value set to the "UID" property value of the new resource.
+            </t>
+          </section>
+        </section>
+
+        <section title='Security Considerations'>
+            <t>This specification does not introduce any more security considerations beyond those already listed in <xref target="RFC5545">iCalendar</xref>, <xref target="RFC5546">iTIP</xref> and <xref target="RFC4791">CalDAV Access</xref> and <xref target="RFC6638">CalDAV Scheduling</xref>.</t>
+        </section>
+        <section title='IANA Considerations'>
+            <t>
+                TBD: new HTTP request header registration.
+            </t>
+        </section>
+    </middle>
+    <back>
+        <references title='Normative References'>
+            &rfc2119;
+            &rfc5545;
+            &rfc5546;
+            &rfc4791;
+            &rfc6638;
+            &idPreferHeader;
+        </references>
+<!--
+<references title='Informative References'>
+</references>
+-->
+        <section title='Acknowledgments'>
+            <t>
+                This specification is the result of discussions between the Apple calendar server and client teams.
+            </t>
+        </section>
+        <!--
+        <section title='Change History'>
+          <t>Changes since -00
+            <list style='numbers'>
+              <t></t>
+            </list>
+          </t>
+        </section>
+        -->
+    </back>
+</rfc>

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/caldavd.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/caldavd.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/caldavd.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_bootstrap_database.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_bootstrap_database.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_bootstrap_database.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_command_gateway.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_command_gateway.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_command_gateway.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_config.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_config.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_config.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_export.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_export.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_export.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_principals.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_principals.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_principals.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_push.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_push.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_push.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_timezones.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_timezones.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_manage_timezones.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_migrate_resources.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_migrate_resources.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_migrate_resources.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_monitor_notifications.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_monitor_notifications.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_monitor_notifications.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_attachments.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_attachments.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_attachments.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_events.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_events.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_events.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_principals.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_principals.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_purge_principals.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_shell.8
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_shell.8	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/doc/calendarserver_shell.8	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+.\" Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 .\"
 .\" Licensed under the Apache License, Version 2.0 (the "License");
 .\" you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/locales/en_EN.ISO8859-1/LC_MESSAGES/calendarserver.po
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/locales/en_EN.ISO8859-1/LC_MESSAGES/calendarserver.po	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/locales/en_EN.ISO8859-1/LC_MESSAGES/calendarserver.po	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 # Calendar Server Localization
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 msgid ""
 msgstr ""

Modified: CalendarServer/branches/users/gaya/cleanrevisions/pydoctor
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/pydoctor	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/pydoctor	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/run
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/run	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/run	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 # -*- sh-basic-offset: 2 -*-
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/setup.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/setup.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/setup.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/sim
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/sim	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/sim	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/Apple.make
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/Apple.make	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/Apple.make	2014-01-12 19:10:08 UTC (rev 12322)
@@ -4,7 +4,7 @@
 #
 # This is only useful internally at Apple, probably.
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -55,8 +55,8 @@
 .phony: $(Project) pycalendar build setup prep install install-ossfiles buildit
 
 CALDAVTESTER = CalDAVTester
-PYKERBEROS   = PyKerberos
-PYCALENDAR   = pycalendar
+PYKERBEROS   = PyKerberos-9409
+PYCALENDAR   = PyCalendar-11947
 PYGRESQL     = PyGreSQL-4.1.1
 SQLPARSE     = sqlparse-0.1.2
 SETPROCTITLE = setproctitle-1.1.6

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/XCode.make
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/XCode.make	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/XCode.make	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 ##
 # XCode Makefile for CalendarServer
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/build.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/build.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/build.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- sh-basic-offset: 2 -*-
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -847,7 +847,7 @@
   local n="pycrypto";
   local p="${n}-${v}";
   py_dependency -v "${v}" -m "55a61a054aa66812daf5161a0d5d7eda" \
-    "PyCrypto" "${n}" "${p}" \
+    "PyCrypto" "Crypto" "${p}" \
     "http://ftp.dlitz.net/pub/dlitz/crypto/${n}/${p}.tar.gz";
 
   local v="0.1.7";
@@ -864,7 +864,7 @@
     "${n}" "twisted" "${p}" \
     "${pypi}/T/${n}/${p}.tar.bz2";
 
-  local v="12094";
+  local v="12213";
   local n="twext";
   local p="${n}-${v}";
   py_dependency -fe -r "${v}" \
@@ -951,7 +951,7 @@
   local n="Nevow";
   local p="${n}-${v}";
   py_dependency -o -m "66dda2ad88f42dea05911add15f4d1b2" \
-    "${n}" "${n}" "${p}" \
+    "${n}" "nevow" "${p}" \
     "${pypi}/N/${n}/${p}.tar.gz";
 
   local v="0.5b1";

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/gendocs
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/gendocs	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/gendocs	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/patchapply
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/patchapply	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/patchapply	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/patchmaker
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/patchmaker	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/patchmaker	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/py.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/py.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/py.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- sh-basic-offset: 2 -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -110,6 +110,9 @@
     done;
 
     if [ -z "${module_version}" ]; then
+      module_version=$("${python}" -c 'import pkg_resources; print pkg_resources.get_distribution("'"${module}"'").version;');
+    fi;
+    if [ -z "${module_version}" ]; then
       if ! "${print_path}"; then
         echo "Unable to determine version for ${module}.";
       fi;

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/shell.sh
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/shell.sh	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/shell.sh	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/submit
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/submit	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/submit	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
 set -e
 set -u
 
-version="20";
+version="22";
 
  wd="$(cd "$(dirname "$0")" && pwd)";
 src="$(cd "${wd}/.." && pwd)";

Modified: CalendarServer/branches/users/gaya/cleanrevisions/support/version.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/support/version.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/support/version.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/test
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/test	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/test	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/testserver
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/testserver	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/testserver	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twisted/plugins/caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twisted/plugins/caldav.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twisted/plugins/caldav.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
 from twisted.internet.protocol import Factory
 Factory.noisy = False
 
-
 def serviceMakerProperty(propname):
     def getProperty(self):
         return getattr(reflect.namedClass(self.serviceMakerClass), propname)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/accounting.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/accounting.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/accounting.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/authkerb.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/authkerb.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/authkerb.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/backup.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/backup.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/backup.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/bind.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/bind.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/bind.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/cache.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/cache.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/cache.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/caldavxml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/caldavxml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/caldavxml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 # #
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/carddavxml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/carddavxml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/carddavxml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/geturl.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/geturl.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/geturl.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/pool.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/pool.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/pool.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/reverseproxy.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/reverseproxy.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/reverseproxy.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/test/test_reverseproxy.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/test/test_reverseproxy.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/client/test/test_reverseproxy.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/config.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/config.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/config.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/customxml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/customxml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -76,7 +76,11 @@
     "calendarserver-home-sync",
 )
 
+calendarserver_recurrence_split = (
+    "calendarserver-recurrence-split",
+)
 
+
 @registerElement
 class TwistedCalendarSupportedComponents (WebDAVTextElement):
     """

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/database.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/database.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/database.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/addressdata.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/addressdata.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/addressdata.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/calendardata.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/calendardata.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/calendardata.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/filter.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/filter.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/filter.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/hiddeninstance.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/hiddeninstance.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/hiddeninstance.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/peruserdata.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/peruserdata.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/peruserdata.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/privateevents.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/privateevents.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/privateevents.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_calendardata.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_calendardata.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_calendardata.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_hiddeninstances.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_hiddeninstances.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_hiddeninstances.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_peruserdata.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_peruserdata.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_peruserdata.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_privateevents.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_privateevents.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/datafilters/test/test_privateevents.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/dateops.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/dateops.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/dateops.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/addressbook.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/addressbook.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/addressbook.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/aggregate.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/aggregate.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/aggregate.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/appleopendirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/appleopendirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test.test_opendirectory -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/augment.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/augment.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/augment.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/cachingdirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/cachingdirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/cachingdirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test.test_cachedirectory -*-
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendar.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendar.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test.test_calendar -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendaruserproxy.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendaruserproxy.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test.test_proxyprincipalmembers -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendaruserproxyloader.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendaruserproxyloader.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/calendaruserproxyloader.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/common.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/common.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/common.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_wrapping,twistedcaldav.directory.test.test_calendar -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/digest.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/digest.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/digest.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test.test_digest -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/directory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/directory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/idirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/idirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/idirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/internal.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/internal.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/internal.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/ldapdirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/ldapdirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/ldapdirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 ##
 # Copyright (c) 2008-2009 Aymeric Augustin. All rights reserved.
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -40,7 +40,8 @@
     "LdapDirectoryService",
 ]
 
-import ldap, ldap.async
+import ldap
+import ldap.async
 from ldap.filter import escape_filter_chars as ldapEsc
 
 try:
@@ -52,8 +53,9 @@
 
 import time
 from twisted.cred.credentials import UsernamePassword
-from twistedcaldav.directory.cachingdirectory import (CachingDirectoryService,
-    CachingDirectoryRecord)
+from twistedcaldav.directory.cachingdirectory import (
+    CachingDirectoryService, CachingDirectoryRecord
+)
 from twistedcaldav.directory.directory import DirectoryConfigurationError
 from twistedcaldav.directory.augment import AugmentRecord
 from twistedcaldav.directory.util import splitIntoBatches, normalizeUUID
@@ -63,6 +65,8 @@
 from txweb2.http import HTTPError, StatusResponse
 from txweb2 import responsecode
 
+
+
 class LdapDirectoryService(CachingDirectoryService):
     """
     LDAP based implementation of L{IDirectoryService}.
@@ -72,8 +76,9 @@
     baseGUID = "5A871574-0C86-44EE-B11B-B9440C3DC4DD"
 
     def __repr__(self):
-        return "<%s %r: %r>" % (self.__class__.__name__, self.realmName,
-            self.uri)
+        return "<%s %r: %r>" % (
+            self.__class__.__name__, self.realmName, self.uri
+        )
 
 
     def __init__(self, params):
@@ -85,15 +90,15 @@
         """
 
         defaults = {
-            "augmentService" : None,
-            "groupMembershipCache" : None,
-            "cacheTimeout": 1, # Minutes
+            "augmentService": None,
+            "groupMembershipCache": None,
+            "cacheTimeout": 1,  # Minutes
             "negativeCaching": False,
             "warningThresholdSeconds": 3,
-            "batchSize": 500, # for splitting up large queries
-            "requestTimeoutSeconds" : 10,
-            "requestResultsLimit" : 200,
-            "optimizeMultiName" : False,
+            "batchSize": 500,  # for splitting up large queries
+            "requestTimeoutSeconds": 10,
+            "requestResultsLimit": 200,
+            "optimizeMultiName": False,
             "queryLocationsImplicitly": True,
             "restrictEnabledRecords": False,
             "restrictToGroup": "",
@@ -102,7 +107,7 @@
             "tls": False,
             "tlsCACertFile": None,
             "tlsCACertDir": None,
-            "tlsRequireCert": None, # never, allow, try, demand, hard
+            "tlsRequireCert": None,  # never, allow, try, demand, hard
             "credentials": {
                 "dn": None,
                 "password": None,
@@ -113,68 +118,68 @@
                 "guidAttr": "entryUUID",
                 "users": {
                     "rdn": "ou=People",
-                    "filter": None, # additional filter for this type
-                    "loginEnabledAttr" : "", # attribute controlling login
-                    "loginEnabledValue" : "yes", # "True" value of above attribute
-                    "calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
-                    "calendarEnabledValue" : "yes", # "True" value of above attribute
-                    "mapping" : { # maps internal record names to LDAP
+                    "filter": None,  # additional filter for this type
+                    "loginEnabledAttr": "",  # attribute controlling login
+                    "loginEnabledValue": "yes",  # "True" value of above attribute
+                    "calendarEnabledAttr": "",  # attribute controlling enabledForCalendaring
+                    "calendarEnabledValue": "yes",  # "True" value of above attribute
+                    "mapping": {  # maps internal record names to LDAP
                         "recordName": "uid",
-                        "fullName" : "cn",
-                        "emailAddresses" : ["mail"], # multiple LDAP fields supported
-                        "firstName" : "givenName",
-                        "lastName" : "sn",
+                        "fullName": "cn",
+                        "emailAddresses": ["mail"],  # multiple LDAP fields supported
+                        "firstName": "givenName",
+                        "lastName": "sn",
                     },
                 },
                 "groups": {
                     "rdn": "ou=Group",
-                    "filter": None, # additional filter for this type
-                    "mapping" : { # maps internal record names to LDAP
+                    "filter": None,  # additional filter for this type
+                    "mapping": {  # maps internal record names to LDAP
                         "recordName": "cn",
-                        "fullName" : "cn",
-                        "emailAddresses" : ["mail"], # multiple LDAP fields supported
-                        "firstName" : "givenName",
-                        "lastName" : "sn",
+                        "fullName": "cn",
+                        "emailAddresses": ["mail"],  # multiple LDAP fields supported
+                        "firstName": "givenName",
+                        "lastName": "sn",
                     },
                 },
                 "locations": {
                     "rdn": "ou=Places",
-                    "filter": None, # additional filter for this type
-                    "calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
-                    "calendarEnabledValue" : "yes", # "True" value of above attribute
-                    "associatedAddressAttr" : "",
-                    "mapping" : { # maps internal record names to LDAP
+                    "filter": None,  # additional filter for this type
+                    "calendarEnabledAttr": "",  # attribute controlling enabledForCalendaring
+                    "calendarEnabledValue": "yes",  # "True" value of above attribute
+                    "associatedAddressAttr": "",
+                    "mapping": {  # maps internal record names to LDAP
                         "recordName": "cn",
-                        "fullName" : "cn",
-                        "emailAddresses" : ["mail"], # multiple LDAP fields supported
+                        "fullName": "cn",
+                        "emailAddresses": ["mail"],  # multiple LDAP fields supported
                     },
                 },
                 "resources": {
                     "rdn": "ou=Resources",
-                    "filter": None, # additional filter for this type
-                    "calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
-                    "calendarEnabledValue" : "yes", # "True" value of above attribute
-                    "mapping" : { # maps internal record names to LDAP
+                    "filter": None,  # additional filter for this type
+                    "calendarEnabledAttr": "",  # attribute controlling enabledForCalendaring
+                    "calendarEnabledValue": "yes",  # "True" value of above attribute
+                    "mapping": {  # maps internal record names to LDAP
                         "recordName": "cn",
-                        "fullName" : "cn",
-                        "emailAddresses" : ["mail"], # multiple LDAP fields supported
+                        "fullName": "cn",
+                        "emailAddresses": ["mail"],  # multiple LDAP fields supported
                     },
                 },
                 "addresses": {
                     "rdn": "ou=Buildings",
-                    "filter": None, # additional filter for this type
-                    "streetAddressAttr" : "",
-                    "geoAttr" : "",
-                    "mapping" : { # maps internal record names to LDAP
+                    "filter": None,  # additional filter for this type
+                    "streetAddressAttr": "",
+                    "geoAttr": "",
+                    "mapping": {  # maps internal record names to LDAP
                         "recordName": "cn",
-                        "fullName" : "cn",
+                        "fullName": "cn",
                     },
                 },
             },
             "groupSchema": {
-                "membersAttr": "member", # how members are specified
-                "nestedGroupsAttr": None, # how nested groups are specified
-                "memberIdAttr": None, # which attribute the above refer to (None means use DN)
+                "membersAttr": "member",  # how members are specified
+                "nestedGroupsAttr": None,  # how nested groups are specified
+                "memberIdAttr": None,  # which attribute the above refer to (None means use DN)
             },
             "resourceSchema": {
                 # Either set this attribute to retrieve the plist version
@@ -184,12 +189,12 @@
                 # individually:
                 "autoScheduleAttr": None,
                 "autoScheduleEnabledValue": "yes",
-                "proxyAttr": None, # list of GUIDs
-                "readOnlyProxyAttr": None, # list of GUIDs
-                "autoAcceptGroupAttr": None, # single group GUID
+                "proxyAttr": None,  # list of GUIDs
+                "readOnlyProxyAttr": None,  # list of GUIDs
+                "autoAcceptGroupAttr": None,  # single group GUID
             },
             "poddingSchema": {
-                "serverIdAttr": None, # maps to augments server-id
+                "serverIdAttr": None,  # maps to augments server-id
             },
         }
         ignored = None
@@ -238,7 +243,7 @@
             if self.rdnSchema[recordType]["attr"]:
                 attrSet.add(self.rdnSchema[recordType]["attr"])
             for n in ("calendarEnabledAttr", "associatedAddressAttr",
-                "streetAddressAttr", "geoAttr"):
+                      "streetAddressAttr", "geoAttr"):
                 if self.rdnSchema[recordType].get(n, False):
                     attrSet.add(self.rdnSchema[recordType][n])
             for attrList in self.rdnSchema[recordType]["mapping"].values():
@@ -311,15 +316,16 @@
 
         # Query the LDAP server
         self.log.debug("Querying ldap for records matching base {base} and "
-            "filter {filter} for attributes {attrs}.",
-            base=ldap.dn.dn2str(base), filter=filterstr, attrs=self.attrlist)
+                       "filter {filter} for attributes {attrs}.",
+                       base=ldap.dn.dn2str(base), filter=filterstr,
+                       attrs=self.attrlist)
 
         # This takes a while, so if you don't want to have a "long request"
         # warning logged, use this instead of timedSearch:
         # results = self.ldap.search_s(ldap.dn.dn2str(base),
         #     ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
-        results = self.timedSearch(ldap.dn.dn2str(base),
-            ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
+        results = self.timedSearch(ldap.dn.dn2str(base), ldap.SCOPE_SUBTREE,
+                                   filterstr=filterstr, attrlist=self.attrlist)
 
         records = []
         numMissingGuids = 0
@@ -337,7 +343,8 @@
                 continue
 
             if not unrestricted:
-                self.log.debug("{dn} is not enabled because it's not a member of group: {group}",
+                self.log.debug(
+                    "{dn} is not enabled because it's not a member of group: {group}",
                     dn=dn, group=self.restrictToGroup)
                 record.enabledForCalendaring = False
                 record.enabledForAddressBooks = False
@@ -346,7 +353,8 @@
 
         if numMissingGuids:
             self.log.info("{num} {recordType} records are missing {attr}",
-                num=numMissingGuids, recordType=recordType, attr=guidAttr)
+                          num=numMissingGuids, recordType=recordType,
+                          attr=guidAttr)
 
         return records
 
@@ -400,11 +408,13 @@
 
         # Query the LDAP server
         self.log.debug("Querying ldap for records matching base {base} and "
-            "filter {filter} for attributes {attrs}.",
-            base=ldap.dn.dn2str(self.base), filter=filterstr, attrs=attrlist)
+                       "filter {filter} for attributes {attrs}.",
+                       base=ldap.dn.dn2str(self.base), filter=filterstr,
+                       attrs=attrlist)
 
         results = self.timedSearch(ldap.dn.dn2str(self.base),
-            ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=attrlist)
+                                   ldap.SCOPE_SUBTREE, filterstr=filterstr,
+                                   attrlist=attrlist)
 
         for dn, attrs in results:
             dn = normalizeDNstr(dn)
@@ -415,12 +425,12 @@
                 if readDelegate:
                     readDelegate = normalizeUUID(readDelegate)
                     assignments.append(("%s#calendar-proxy-read" % (guid,),
-                        [readDelegate]))
+                                       [readDelegate]))
                 writeDelegate = self._getUniqueLdapAttribute(attrs, writeAttr)
                 if writeDelegate:
                     writeDelegate = normalizeUUID(writeDelegate)
                     assignments.append(("%s#calendar-proxy-write" % (guid,),
-                        [writeDelegate]))
+                                       [writeDelegate]))
 
         return assignments
 
@@ -433,11 +443,11 @@
             if self.credentials.get("dn", ""):
                 try:
                     self.log.info("Binding to LDAP {dn}",
-                        dn=repr(self.credentials.get("dn")))
+                                  dn=repr(self.credentials.get("dn")))
                     self.ldap.simple_bind_s(self.credentials.get("dn"),
-                        self.credentials.get("password"))
+                                            self.credentials.get("password"))
                     self.log.info("Successfully authenticated with LDAP as {dn}",
-                        dn=repr(self.credentials.get("dn")))
+                                  dn=repr(self.credentials.get("dn")))
                 except ldap.INVALID_CREDENTIALS:
                     self.log.error("Can't bind to LDAP {uri}: check credentials", uri=self.uri)
                     raise DirectoryConfigurationError()
@@ -498,7 +508,7 @@
 
             except ldap.NO_SUCH_OBJECT:
                 self.log.error("LDAP Authentication error for %s: NO_SUCH_OBJECT"
-                    % (dn,))
+                               % (dn,))
                 # fall through to try again; could be transient
 
             except ldap.INVALID_CREDENTIALS:
@@ -526,7 +536,7 @@
 
 
     def timedSearch(self, base, scope, filterstr="(objectClass=*)",
-        attrlist=None, timeoutSeconds=-1, resultLimit=0):
+                    attrlist=None, timeoutSeconds=-1, resultLimit=0):
         """
         Execute an LDAP query, retrying up to 3 times in case the LDAP server has
         gone down and we need to reconnect. If it takes longer than the configured
@@ -541,8 +551,7 @@
             try:
                 s = ldap.async.List(self.getLDAPConnection())
                 s.startSearch(base, scope, filterstr, attrList=attrlist,
-                    timeout=timeoutSeconds,
-                    sizelimit=resultLimit)
+                              timeout=timeoutSeconds, sizelimit=resultLimit)
                 startTime = time.time()
                 s.processResults()
             except ldap.NO_SUCH_OBJECT:
@@ -566,8 +575,10 @@
             if totalTime > self.warningThresholdSeconds:
                 if filterstr and len(filterstr) > 100:
                     filterstr = "%s..." % (filterstr[:100],)
-                self.log.error("LDAP query exceeded threshold: %.2f seconds for %s %s %s (#results=%d)" %
-                    (totalTime, base, filterstr, attrlist, len(result)))
+                self.log.error(
+                    "LDAP query exceeded threshold: %.2f seconds for %s %s %s (#results=%d)" %
+                    (totalTime, base, filterstr, attrlist, len(result))
+                )
             return result
 
         raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE, "LDAP server unavailable"))
@@ -589,7 +600,7 @@
             return True
         if self.groupSchema["memberIdAttr"]:
             value = self._getUniqueLdapAttribute(attrs, self.groupSchema["memberIdAttr"])
-        else: # No memberIdAttr implies DN
+        else:  # No memberIdAttr implies DN
             value = dn
         return value in self.restrictedPrincipals
 
@@ -610,9 +621,11 @@
                 # TODO: This shouldn't be hardcoded to cn
                 filterstr = "(cn=%s)" % (self.restrictToGroup,)
                 self.log.debug("Retrieving ldap record with base %s and filter %s." %
-                    (ldap.dn.dn2str(base), filterstr))
+                               (ldap.dn.dn2str(base), filterstr))
                 result = self.timedSearch(ldap.dn.dn2str(base),
-                    ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
+                                          ldap.SCOPE_SUBTREE,
+                                          filterstr=filterstr,
+                                          attrlist=self.attrlist)
 
                 members = []
                 nestedGroups = []
@@ -621,16 +634,20 @@
                     dn, attrs = result[0]
                     dn = normalizeDNstr(dn)
                     if self.groupSchema["membersAttr"]:
-                        members = self._getMultipleLdapAttributes(attrs,
-                            self.groupSchema["membersAttr"])
-                        if not self.groupSchema["memberIdAttr"]: # these are DNs
+                        members = self._getMultipleLdapAttributes(
+                            attrs,
+                            self.groupSchema["membersAttr"]
+                        )
+                        if not self.groupSchema["memberIdAttr"]:  # these are DNs
                             members = [normalizeDNstr(m) for m in members]
                         members = set(members)
 
                     if self.groupSchema["nestedGroupsAttr"]:
-                        nestedGroups = self._getMultipleLdapAttributes(attrs,
-                            self.groupSchema["nestedGroupsAttr"])
-                        if not self.groupSchema["memberIdAttr"]: # these are DNs
+                        nestedGroups = self._getMultipleLdapAttributes(
+                            attrs,
+                            self.groupSchema["nestedGroupsAttr"]
+                        )
+                        if not self.groupSchema["memberIdAttr"]:  # these are DNs
                             nestedGroups = [normalizeDNstr(g) for g in nestedGroups]
                         nestedGroups = set(nestedGroups)
                     else:
@@ -639,8 +656,9 @@
                         nestedGroups = members
                         members = set()
 
-                self._cachedRestrictedPrincipals = set(self._expandGroupMembership(members,
-                    nestedGroups))
+                self._cachedRestrictedPrincipals = set(
+                    self._expandGroupMembership(members, nestedGroups)
+                )
                 self.log.info("Got %d restricted group members" % (
                     len(self._cachedRestrictedPrincipals),))
                 self.restrictedTimestamp = time.time()
@@ -695,15 +713,17 @@
                 scope = ldap.SCOPE_SUBTREE
                 base = self.typeDNs[recordType]
                 filterstr = "(%s=%s)" % (self.groupSchema["memberIdAttr"], group)
-            else: # Use DN
+            else:  # Use DN
                 scope = ldap.SCOPE_BASE
                 base = ldap.dn.str2dn(group)
                 filterstr = "(objectClass=*)"
 
             self.log.debug("Retrieving ldap record with base %s and filter %s." %
-                (ldap.dn.dn2str(base), filterstr))
+                           (ldap.dn.dn2str(base), filterstr))
             result = self.timedSearch(ldap.dn.dn2str(base),
-                scope, filterstr=filterstr, attrlist=self.attrlist)
+                                      scope,
+                                      filterstr=filterstr,
+                                      attrlist=self.attrlist)
 
             if len(result) == 0:
                 continue
@@ -714,24 +734,29 @@
                 dn, attrs = result[0]
                 dn = normalizeDNstr(dn)
                 if self.groupSchema["membersAttr"]:
-                    subMembers = self._getMultipleLdapAttributes(attrs,
-                        self.groupSchema["membersAttr"])
-                    if not self.groupSchema["memberIdAttr"]: # these are DNs
+                    subMembers = self._getMultipleLdapAttributes(
+                        attrs,
+                        self.groupSchema["membersAttr"]
+                    )
+                    if not self.groupSchema["memberIdAttr"]:  # these are DNs
                         subMembers = [normalizeDNstr(m) for m in subMembers]
                     subMembers = set(subMembers)
 
                 if self.groupSchema["nestedGroupsAttr"]:
-                    subNestedGroups = self._getMultipleLdapAttributes(attrs,
-                        self.groupSchema["nestedGroupsAttr"])
-                    if not self.groupSchema["memberIdAttr"]: # these are DNs
+                    subNestedGroups = self._getMultipleLdapAttributes(
+                        attrs,
+                        self.groupSchema["nestedGroupsAttr"]
+                    )
+                    if not self.groupSchema["memberIdAttr"]:  # these are DNs
                         subNestedGroups = [normalizeDNstr(g) for g in subNestedGroups]
                     subNestedGroups = set(subNestedGroups)
 
             processedItems.add(group)
             yield group
 
-            for item in self._expandGroupMembership(subMembers, subNestedGroups,
-                processedItems):
+            for item in self._expandGroupMembership(subMembers,
+                                                    subNestedGroups,
+                                                    processedItems):
                 yield item
 
 
@@ -805,8 +830,10 @@
         emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
 
         if len(emailAddresses) == 0 and emailSuffix:
-            emailPrefix = self._getUniqueLdapAttribute(attrs,
-                self.rdnSchema[recordType].get("attr", "cn"))
+            emailPrefix = self._getUniqueLdapAttribute(
+                attrs,
+                self.rdnSchema[recordType].get("attr", "cn")
+            )
             emailAddresses.add(emailPrefix + emailSuffix)
 
         proxyGUIDs = ()
@@ -837,7 +864,7 @@
                 memberGUIDs.extend(members)
 
             # Normalize members if they're in DN form
-            if not self.groupSchema["memberIdAttr"]: # empty = dn
+            if not self.groupSchema["memberIdAttr"]:  # empty = dn
                 guids = list(memberGUIDs)
                 memberGUIDs = []
                 for dnStr in guids:
@@ -849,14 +876,16 @@
                         self.log.warn("Bad LDAP DN: %s" % (dnStr,))
 
         elif recordType in (self.recordType_resources,
-            self.recordType_locations):
+                            self.recordType_locations):
             fullName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["fullName"])
             enabledForCalendaring = True
             enabledForAddressBooks = False
             enabledForLogin = False
             if self.resourceSchema["resourceInfoAttr"]:
-                resourceInfo = self._getUniqueLdapAttribute(attrs,
-                    self.resourceSchema["resourceInfoAttr"])
+                resourceInfo = self._getUniqueLdapAttribute(
+                    attrs,
+                    self.resourceSchema["resourceInfoAttr"]
+                )
                 if resourceInfo:
                     try:
                         (
@@ -876,45 +905,66 @@
                             readOnlyProxyGUIDs = (readOnlyProxy,)
                     except ValueError, e:
                         self.log.error("Unable to parse resource info (%s)" % (e,))
-            else: # the individual resource attributes might be specified
+            else:  # the individual resource attributes might be specified
                 if self.resourceSchema["autoScheduleAttr"]:
-                    autoScheduleValue = self._getUniqueLdapAttribute(attrs,
-                        self.resourceSchema["autoScheduleAttr"])
-                    autoSchedule = (autoScheduleValue ==
-                        self.resourceSchema["autoScheduleEnabledValue"])
+                    autoScheduleValue = self._getUniqueLdapAttribute(
+                        attrs,
+                        self.resourceSchema["autoScheduleAttr"]
+                    )
+                    autoSchedule = (
+                        autoScheduleValue == self.resourceSchema["autoScheduleEnabledValue"]
+                    )
                 if self.resourceSchema["proxyAttr"]:
-                    proxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
-                        self.resourceSchema["proxyAttr"]))
+                    proxyGUIDs = set(
+                        self._getMultipleLdapAttributes(
+                            attrs,
+                            self.resourceSchema["proxyAttr"]
+                        )
+                    )
                 if self.resourceSchema["readOnlyProxyAttr"]:
-                    readOnlyProxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
-                        self.resourceSchema["readOnlyProxyAttr"]))
+                    readOnlyProxyGUIDs = set(
+                        self._getMultipleLdapAttributes(
+                            attrs,
+                            self.resourceSchema["readOnlyProxyAttr"]
+                        )
+                    )
                 if self.resourceSchema["autoAcceptGroupAttr"]:
-                    autoAcceptGroup = self._getUniqueLdapAttribute(attrs,
-                        self.resourceSchema["autoAcceptGroupAttr"])
+                    autoAcceptGroup = self._getUniqueLdapAttribute(
+                        attrs,
+                        self.resourceSchema["autoAcceptGroupAttr"]
+                    )
 
             if recordType == self.recordType_locations:
                 if self.rdnSchema[recordType]["associatedAddressAttr"]:
-                    associatedAddress = self._getUniqueLdapAttribute(attrs,
-                        self.rdnSchema[recordType]["associatedAddressAttr"])
+                    associatedAddress = self._getUniqueLdapAttribute(
+                        attrs,
+                        self.rdnSchema[recordType]["associatedAddressAttr"]
+                    )
                     if associatedAddress:
                         extras["associatedAddress"] = associatedAddress
 
         elif recordType == self.recordType_addresses:
             if self.rdnSchema[recordType].get("geoAttr", ""):
-                geo = self._getUniqueLdapAttribute(attrs,
-                    self.rdnSchema[recordType]["geoAttr"])
+                geo = self._getUniqueLdapAttribute(
+                    attrs,
+                    self.rdnSchema[recordType]["geoAttr"]
+                )
                 if geo:
                     extras["geo"] = geo
             if self.rdnSchema[recordType].get("streetAddressAttr", ""):
-                street = self._getUniqueLdapAttribute(attrs,
-                    self.rdnSchema[recordType]["streetAddressAttr"])
+                street = self._getUniqueLdapAttribute(
+                    attrs,
+                    self.rdnSchema[recordType]["streetAddressAttr"]
+                )
                 if street:
                     extras["streetAddress"] = street
 
         serverID = None
         if self.poddingSchema["serverIdAttr"]:
-            serverID = self._getUniqueLdapAttribute(attrs,
-                self.poddingSchema["serverIdAttr"])
+            serverID = self._getUniqueLdapAttribute(
+                attrs,
+                self.poddingSchema["serverIdAttr"]
+            )
 
         record = LdapDirectoryRecord(
             service=self,
@@ -940,8 +990,7 @@
             # TODO: this needs to be deferred but for now we hard code
             # the deferred result because we know it is completing
             # immediately.
-            d = self.augmentService.getAugmentRecord(record.guid,
-                recordType)
+            d = self.augmentService.getAugmentRecord(record.guid, recordType)
             d.addCallback(lambda x: record.addAugmentInformation(x))
 
         else:
@@ -953,7 +1002,7 @@
                 enabledForCalendaring=enabledForCalendaring,
                 autoSchedule=autoSchedule,
                 autoAcceptGroup=autoAcceptGroup,
-                enabledForAddressBooks=enabledForAddressBooks, # TODO: add to LDAP?
+                enabledForAddressBooks=enabledForAddressBooks,  # TODO: add to LDAP?
                 enabledForLogin=enabledForLogin,
             )
             record.addAugmentInformation(augmentRecord)
@@ -963,15 +1012,18 @@
             loginEnabledAttr = self.rdnSchema[recordType]["loginEnabledAttr"]
             if loginEnabledAttr:
                 loginEnabledValue = self.rdnSchema[recordType]["loginEnabledValue"]
-                record.enabledForLogin = self._getUniqueLdapAttribute(attrs,
-                    loginEnabledAttr) == loginEnabledValue
+                record.enabledForLogin = self._getUniqueLdapAttribute(
+                    attrs, loginEnabledAttr
+                ) == loginEnabledValue
 
         # Override with LDAP calendar-enabled control if attribute specified
         calendarEnabledAttr = self.rdnSchema[recordType].get("calendarEnabledAttr", "")
         if calendarEnabledAttr:
             calendarEnabledValue = self.rdnSchema[recordType]["calendarEnabledValue"]
-            record.enabledForCalendaring = self._getUniqueLdapAttribute(attrs,
-                calendarEnabledAttr) == calendarEnabledValue
+            record.enabledForCalendaring = self._getUniqueLdapAttribute(
+                attrs,
+                calendarEnabledAttr
+            ) == calendarEnabledValue
 
         return record
 
@@ -994,7 +1046,7 @@
             queryMethod = self.timedSearch
 
         self.log.debug("LDAP query for types %s, indexType %s and indexKey %s"
-            % (recordTypes, indexType, indexKey))
+                       % (recordTypes, indexType, indexKey))
 
         guidAttr = self.rdnSchema["guidAttr"]
         for recordType in recordTypes:
@@ -1024,7 +1076,7 @@
 
             elif indexType == self.INDEX_TYPE_CUA:
                 # indexKey is of the form "mailto:test at example.net"
-                email = indexKey[7:] # strip "mailto:"
+                email = indexKey[7:]  # strip "mailto:"
                 emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
                 if emailSuffix is not None and email.partition("@")[2] == emailSuffix:
                     filterstr = "(&%s(|(&(!(mail=*))(%s=%s))(mail=%s)))" % (
@@ -1040,7 +1092,7 @@
                         if ldapFields:
                             subfilter = "(%s=%s)" % (ldapFields, ldapEsc(email))
                         else:
-                            continue # No LDAP attribute assigned for emailAddresses
+                            continue  # No LDAP attribute assigned for emailAddresses
 
                     else:
                         subfilter = []
@@ -1048,7 +1100,7 @@
                             if ldapField:
                                 subfilter.append("(%s=%s)" % (ldapField, ldapEsc(email)))
                         if not subfilter:
-                            continue # No LDAP attribute assigned for emailAddresses
+                            continue  # No LDAP attribute assigned for emailAddresses
 
                         subfilter = "(|%s)" % ("".join(subfilter))
                     filterstr = "(&%s%s)" % (filterstr, subfilter)
@@ -1058,9 +1110,11 @@
 
             # Query the LDAP server
             self.log.debug("Retrieving ldap record with base %s and filter %s." %
-                (ldap.dn.dn2str(base), filterstr))
+                           (ldap.dn.dn2str(base), filterstr))
             result = queryMethod(ldap.dn.dn2str(base),
-                ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
+                                 ldap.SCOPE_SUBTREE,
+                                 filterstr=filterstr,
+                                 attrlist=self.attrlist)
 
             if result:
                 dn, attrs = result.pop()
@@ -1079,20 +1133,26 @@
 
                     record.applySACLs()
 
-                    self.recordCacheForType(recordType).addRecord(record,
-                        indexType, indexKey
+                    self.recordCacheForType(recordType).addRecord(
+                        record, indexType, indexKey
                     )
 
                     # We got a match, so don't bother checking other types
                     break
 
                 except MissingRecordNameException:
-                    self.log.warn("Ignoring record missing record name attribute: recordType %s, indexType %s and indexKey %s"
-                        % (recordTypes, indexType, indexKey))
+                    self.log.warn(
+                        "Ignoring record missing record name "
+                        "attribute: recordType %s, indexType %s and indexKey %s"
+                        % (recordTypes, indexType, indexKey)
+                    )
 
                 except MissingGuidException:
-                    self.log.warn("Ignoring record missing guid attribute: recordType %s, indexType %s and indexKey %s"
-                        % (recordTypes, indexType, indexKey))
+                    self.log.warn(
+                        "Ignoring record missing guid attribute: "
+                        "recordType %s, indexType %s and indexKey %s"
+                        % (recordTypes, indexType, indexKey)
+                    )
 
 
     def recordsMatchingTokens(self, tokens, context=None, limitResults=50, timeoutSeconds=10):
@@ -1131,17 +1191,27 @@
             base = self.typeDNs[recordType]
             scope = ldap.SCOPE_SUBTREE
             extraFilter = self.rdnSchema[recordType].get("filter", "")
-            filterstr = buildFilterFromTokens(recordType, self.rdnSchema[recordType]["mapping"],
-                tokens, extra=extraFilter)
+            filterstr = buildFilterFromTokens(
+                recordType,
+                self.rdnSchema[recordType]["mapping"],
+                tokens,
+                extra=extraFilter
+            )
 
             if filterstr is not None:
                 # Query the LDAP server
-                self.log.debug("LDAP search %s %s (limit=%d)" %
-                    (ldap.dn.dn2str(base), filterstr, limitResults))
-                results = self.timedSearch(ldap.dn.dn2str(base), scope,
-                    filterstr=filterstr, attrlist=self.attrlist,
+                self.log.debug(
+                    "LDAP search %s %s (limit=%d)" %
+                    (ldap.dn.dn2str(base), filterstr, limitResults)
+                )
+                results = self.timedSearch(
+                    ldap.dn.dn2str(base),
+                    scope,
+                    filterstr=filterstr,
+                    attrlist=self.attrlist,
                     timeoutSeconds=timeoutSeconds,
-                    resultLimit=limitResults)
+                    resultLimit=limitResults
+                )
                 numMissingGuids = 0
                 numMissingRecordNames = 0
                 numNotEnabled = 0
@@ -1149,8 +1219,10 @@
                     dn = normalizeDNstr(dn)
                     # Skip if group restriction is in place and guid is not
                     # a member
-                    if (recordType != self.recordType_groups and
-                        not self.isAllowedByRestrictToGroup(dn, attrs)):
+                    if (
+                            recordType != self.recordType_groups and
+                            not self.isAllowedByRestrictToGroup(dn, attrs)
+                    ):
                         continue
 
                     try:
@@ -1219,19 +1291,27 @@
 
             else:
                 scope = ldap.SCOPE_SUBTREE
-                filterstr = buildFilter(recordType,
+                filterstr = buildFilter(
+                    recordType,
                     self.rdnSchema[recordType]["mapping"],
-                    fields, operand=operand,
-                    optimizeMultiName=self.optimizeMultiName)
+                    fields,
+                    operand=operand,
+                    optimizeMultiName=self.optimizeMultiName
+                )
 
             if filterstr is not None:
                 # Query the LDAP server
                 self.log.debug("LDAP search %s %s %s" %
-                    (ldap.dn.dn2str(base), scope, filterstr))
-                results = (yield deferToThread(self.timedSearch, ldap.dn.dn2str(base), scope,
-                    filterstr=filterstr, attrlist=self.attrlist,
+                               (ldap.dn.dn2str(base), scope, filterstr))
+                results = (yield deferToThread(
+                    self.timedSearch,
+                    ldap.dn.dn2str(base),
+                    scope,
+                    filterstr=filterstr,
+                    attrlist=self.attrlist,
                     timeoutSeconds=self.requestTimeoutSeconds,
-                    resultLimit=self.requestResultsLimit))
+                    resultLimit=self.requestResultsLimit)
+                )
                 self.log.debug("LDAP search returned %d results" % (len(results),))
                 numMissingGuids = 0
                 numMissingRecordNames = 0
@@ -1239,8 +1319,10 @@
                     dn = normalizeDNstr(dn)
                     # Skip if group restriction is in place and guid is not
                     # a member
-                    if (recordType != self.recordType_groups and
-                        not self.isAllowedByRestrictToGroup(dn, attrs)):
+                    if (
+                        recordType != self.recordType_groups and
+                        not self.isAllowedByRestrictToGroup(dn, attrs)
+                    ):
                         continue
 
                     try:
@@ -1262,11 +1344,11 @@
 
                 if numMissingGuids:
                     self.log.warn("%d %s records are missing %s" %
-                        (numMissingGuids, recordType, guidAttr))
+                                  (numMissingGuids, recordType, guidAttr))
 
                 if numMissingRecordNames:
                     self.log.warn("%d %s records are missing record name" %
-                        (numMissingRecordNames, recordType))
+                                  (numMissingRecordNames, recordType))
 
         self.log.debug("Principal property search matched %d records" % (len(records),))
         returnValue(records)
@@ -1300,16 +1382,24 @@
                 # recordsMatchingFields for *each* DN.
                 for value in valuesToFetch:
                     fields = [["dn", value, False, "equals"]]
-                    result = (yield self.recordsMatchingFields(fields,
-                        recordType=self.recordType_groups))
+                    result = (
+                        yield self.recordsMatchingFields(
+                            fields,
+                            recordType=self.recordType_groups
+                        )
+                    )
                     results.extend(result)
             else:
                 for batch in splitIntoBatches(valuesToFetch, self.batchSize):
                     fields = []
                     for value in batch:
                         fields.append([attributeToSearch, value, False, "equals"])
-                    result = (yield self.recordsMatchingFields(fields,
-                        recordType=self.recordType_groups))
+                    result = (
+                        yield self.recordsMatchingFields(
+                            fields,
+                            recordType=self.recordType_groups
+                        )
+                    )
                     results.extend(result)
 
             # Reset values for next iteration
@@ -1329,7 +1419,7 @@
                         # cut:  we know we only need to examine groups, and
                         # those will be children of the groups DN
                         if not dnContainedIn(ldap.dn.str2dn(memberAlias),
-                            groupsDN):
+                                             groupsDN):
                             continue
                     if memberAlias not in recordsByAlias:
                         valuesToFetch.add(memberAlias)
@@ -1351,7 +1441,7 @@
         """
         dn = ldap.dn.str2dn(dnStr.lower())
         for recordType in self.recordTypes():
-            base = self.typeDNs[recordType] # already lowercase
+            base = self.typeDNs[recordType]  # already lowercase
             if dnContainedIn(dn, base):
                 return recordType
         return None
@@ -1431,7 +1521,8 @@
                             if firstName != lastName:
                                 firstValue = _convertValue(firstName, firstMatchType)
                                 lastValue = _convertValue(lastName, lastMatchType)
-                                converted.append("(&(%s=%s)(%s=%s))" %
+                                converted.append(
+                                    "(&(%s=%s)(%s=%s))" %
                                     (mapping["firstName"], firstValue,
                                      mapping["lastName"], lastValue)
                                 )
@@ -1477,9 +1568,25 @@
     """
 
     filterStr = None
-    tokens = [ldapEsc(t) for t in tokens if len(t) > 2]
+
+    # Eliminate any substring duplicates
+    tokenSet = set()
+    for token in tokens:
+        collision = False
+        for existing in tokenSet:
+            if token in existing:
+                collision = True
+                break
+            elif existing in token:
+                tokenSet.remove(existing)
+                break
+        if not collision:
+            tokenSet.add(token)
+
+    tokens = [ldapEsc(t) for t in tokenSet]
     if len(tokens) == 0:
         return None
+    tokens.sort()
 
     attributes = [
         ("fullName", "(%s=*%s*)"),
@@ -1559,8 +1666,10 @@
         # Identifier of this record as a group member
         memberIdAttr = self.service.groupSchema["memberIdAttr"]
         if memberIdAttr:
-            self._memberId = self.service._getUniqueLdapAttribute(attrs,
-                memberIdAttr)
+            self._memberId = self.service._getUniqueLdapAttribute(
+                attrs,
+                memberIdAttr
+            )
         else:
             self._memberId = normalizeDNstr(self.dn)
 
@@ -1588,18 +1697,23 @@
                 base = self.service.base
                 filterstr = "(%s=%s)" % (memberIdAttr, ldapEsc(memberId))
                 self.log.debug("Retrieving subtree of %s with filter %s" %
-                    (ldap.dn.dn2str(base), filterstr),
-                    system="LdapDirectoryService")
-                result = self.service.timedSearch(ldap.dn.dn2str(base),
-                    ldap.SCOPE_SUBTREE, filterstr=filterstr,
-                    attrlist=self.service.attrlist)
+                               (ldap.dn.dn2str(base), filterstr),
+                               system="LdapDirectoryService")
+                result = self.service.timedSearch(
+                    ldap.dn.dn2str(base),
+                    ldap.SCOPE_SUBTREE,
+                    filterstr=filterstr,
+                    attrlist=self.service.attrlist
+                )
 
-            else: # using DN
+            else:  # using DN
 
                 self.log.debug("Retrieving %s." % memberId,
-                    system="LdapDirectoryService")
-                result = self.service.timedSearch(memberId,
-                    ldap.SCOPE_BASE, attrlist=self.service.attrlist)
+                               system="LdapDirectoryService")
+                result = self.service.timedSearch(
+                    memberId,
+                    ldap.SCOPE_BASE, attrlist=self.service.attrlist
+                )
 
             if result:
 
@@ -1611,12 +1725,16 @@
                     self.log.error("Unable to map %s to a record type" % (dn,))
                     continue
 
-                shortName = self.service._getUniqueLdapAttribute(attrs,
-                    self.service.rdnSchema[recordType]["mapping"]["recordName"])
+                shortName = self.service._getUniqueLdapAttribute(
+                    attrs,
+                    self.service.rdnSchema[recordType]["mapping"]["recordName"]
+                )
 
                 if shortName:
-                    record = self.service.recordWithShortName(recordType,
-                        shortName)
+                    record = self.service.recordWithShortName(
+                        recordType,
+                        shortName
+                    )
                     if record:
                         results.append(record)
 
@@ -1647,7 +1765,8 @@
         if len(membersAttrs) == 1:
             filterstr = "(%s=%s)" % (membersAttrs[0], self._memberId)
         else:
-            filterstr = "(|%s)" % ("".join(
+            filterstr = "(|%s)" % (
+                "".join(
                     ["(%s=%s)" % (a, self._memberId) for a in membersAttrs]
                 ),
             )
@@ -1655,8 +1774,12 @@
         groups = []
 
         try:
-            results = self.service.timedSearch(ldap.dn.dn2str(base),
-                ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.service.attrlist)
+            results = self.service.timedSearch(
+                ldap.dn.dn2str(base),
+                ldap.SCOPE_SUBTREE,
+                filterstr=filterstr,
+                attrlist=self.service.attrlist
+            )
 
             for dn, attrs in results:
                 dn = normalizeDNstr(dn)
@@ -1737,12 +1860,13 @@
 
                 except ldap.INVALID_CREDENTIALS:
                     self.log.info("Invalid credentials for {dn}",
-                        dn=repr(self.dn), system="LdapDirectoryService")
+                                  dn=repr(self.dn),
+                                  system="LdapDirectoryService")
                     return False
 
             else:
                 self.log.error("Unknown Authentication Method '{method}'",
-                    method=self.service.authMethod.upper())
+                               method=self.service.authMethod.upper())
                 raise DirectoryConfigurationError()
 
         return super(LdapDirectoryRecord, self).verifyCredentials(credentials)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/opendirectorybacker.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/opendirectorybacker.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -23,46 +23,46 @@
     "OpenDirectoryBackingService", "VCardRecord",
 ]
 
-import traceback
-import hashlib
+from calendarserver.platform.darwin.od import opendirectory, dsattributes, dsquery
 
-import os
-import sys
-import time
-
-from os import listdir
-from os.path import join, abspath
-from tempfile import mkstemp, gettempdir
-from random import random
-
+from pycalendar.datetime import DateTime
+from pycalendar.vcard.adr import Adr
 from pycalendar.vcard.n import N
-from pycalendar.vcard.adr import Adr
-from pycalendar.datetime import DateTime
 
-from socket import getfqdn
 
-from twisted.internet import reactor
-from twisted.internet.defer import inlineCallbacks, returnValue, deferredGenerator, succeed
 from twext.python.filepath import CachingFilePath as FilePath
-from txdav.xml import element as davxml
-from txdav.xml.base import twisted_dav_namespace, dav_namespace, parse_date, twisted_private_namespace
+
 from txweb2.dav.resource import DAVPropertyMixIn
 from txweb2.dav.util import joinURL
 from txweb2.http_headers import MimeType, generateContentType, ETag
 
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, returnValue, deferredGenerator, succeed
 
 from twistedcaldav import customxml, carddavxml
+from twistedcaldav.config import config
 from twistedcaldav.customxml import calendarserver_namespace
-from twistedcaldav.config import config
 from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
 from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
-from twistedcaldav.query import addressbookqueryfilter
 from twistedcaldav.vcard import Component, Property, vCardProductID
 
+from txdav.carddav.datastore.query.filter import IsNotDefined, ParameterFilter, \
+    TextMatch
+from txdav.xml import element as davxml
+from txdav.xml.base import twisted_dav_namespace, dav_namespace, parse_date, twisted_private_namespace
+
+from os import listdir
+from os.path import join, abspath
+from random import random
+from socket import getfqdn
+from tempfile import mkstemp, gettempdir
 from xmlrpclib import datetime
+import hashlib
+import os
+import sys
+import time
+import traceback
 
-from calendarserver.platform.darwin.od import opendirectory, dsattributes, dsquery
-
 class OpenDirectoryBackingService(DirectoryService):
     """
     Open Directory implementation of L{IDirectoryService}.
@@ -830,11 +830,11 @@
                 if not constant and not allAttrStrings:
                     return (False, [], [])
 
-                if propFilter.qualifier and isinstance(propFilter.qualifier, addressbookqueryfilter.IsNotDefined):
+                if propFilter.qualifier and isinstance(propFilter.qualifier, IsNotDefined):
                     return definedExpression(False, filterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrStrings)
 
-                paramFilterElements = [paramFilterElement for paramFilterElement in propFilter.filters if isinstance(paramFilterElement, addressbookqueryfilter.ParameterFilter)]
-                textMatchElements = [textMatchElement for textMatchElement in propFilter.filters if isinstance(textMatchElement, addressbookqueryfilter.TextMatch)]
+                paramFilterElements = [paramFilterElement for paramFilterElement in propFilter.filters if isinstance(paramFilterElement, ParameterFilter)]
+                textMatchElements = [textMatchElement for textMatchElement in propFilter.filters if isinstance(textMatchElement, TextMatch)]
                 propFilterAllOf = propFilter.propfilter_test == "allof"
 
                 # handle parameter filter elements

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/principal.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/principal.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test.test_principal -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -922,6 +922,23 @@
 
 
     @inlineCallbacks
+    def proxyMode(self, principal):
+        """
+        Determine whether what proxy mode this principal has in relation to the one specified.
+        """
+
+        read_uids = (yield self.proxyFor(False))
+        if principal in read_uids:
+            returnValue("read")
+
+        write_uids = (yield self.proxyFor(True))
+        if principal in write_uids:
+            returnValue("write")
+
+        returnValue("none")
+
+
+    @inlineCallbacks
     def proxyFor(self, read_write, resolve_memberships=True):
 
         proxyFors = set()

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
 
 from twistedcaldav.client.reverseproxy import ReverseProxyResource
 
+from twisted.internet.defer import succeed
+
 __all__ = ["DirectoryReverseProxyResource"]
 
 class DirectoryReverseProxyResource(ReverseProxyResource):
@@ -35,3 +37,32 @@
 
     def url(self):
         return joinURL(self.parent.url(), self.record.uid)
+
+
+    def hasQuota(self, request):
+        return succeed(False)
+
+
+    def hasQuotaRoot(self, request):
+        return succeed(False)
+
+
+    def quotaRootResource(self, request):
+        """
+        Return the quota root for this resource.
+
+        @return: L{DAVResource} or C{None}
+        """
+
+        return succeed(None)
+
+
+    def checkPrivileges(
+        self, request, privileges, recurse=False,
+        principal=None, inherited_aces=None
+    ):
+        return succeed(None)
+
+
+    def hasProperty(self, property, request):
+        return succeed(False)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/resourceinfo.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/resourceinfo.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/resourceinfo.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/accounts-modified.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/accounts-modified.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/accounts-modified.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/accounts.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/accounts.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/accounts.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -139,7 +139,7 @@
       <member type="users">delegateviagroup</member>
     </members>
   </group>
-  <user repeat="2">
+  <user repeat="100">
     <uid>user%02d</uid>
     <guid>user%02d</guid>
     <password>%02duser</password>

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-normalization.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-normalization.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-normalization.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-test-default.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-test-default.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-test-default.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-test.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-test.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments-test.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/augments.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -57,7 +57,7 @@
     <enable-calendar>false</enable-calendar>
     <enable-addressbook>false</enable-addressbook>
   </record>
-  <record repeat="2">
+  <record repeat="100">
     <uid>user%02d</uid>
     <enable>true</enable>
     <enable-calendar>true</enable-calendar>

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/augments.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/augments.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/augments.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/resources-locations.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/resources-locations.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/resources-locations.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/users-groups.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/users-groups.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/modify/users-groups.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/proxies.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/proxies.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/proxies.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/augments.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/augments.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/augments.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/caldavd.plist
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/caldavd.plist	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/caldavd.plist	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/resources-locations.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/resources-locations.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/resources-locations.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/users-groups.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/users-groups.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources/users-groups.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/resources.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_aggregate.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_aggregate.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_aggregate.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_augment.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_augment.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_augment.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_buildquery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_buildquery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_buildquery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_cachedirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_cachedirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_cachedirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_calendar.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_calendar.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_calendar.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_digest.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_digest.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_digest.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_directory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_directory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_directory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -999,8 +999,9 @@
         Exercise the default recordsMatchingTokens implementation
         """
         records = list((yield self.directoryService.recordsMatchingTokens(["Use", "01"])))
-        self.assertEquals(len(records), 1)
-        self.assertEquals(records[0].shortNames[0], "user01")
+        self.assertNotEquals(len(records), 0)
+        shorts = [record.shortNames[0] for record in records]
+        self.assertTrue("user01" in shorts)
 
         records = list((yield self.directoryService.recordsMatchingTokens(['"quotey"'],
             context=self.directoryService.searchContext_attendee)))

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_guidchange.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_guidchange.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_guidchange.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_ldapdirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_ldapdirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_ldapdirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -23,9 +23,13 @@
     )
     from twistedcaldav.directory.util import splitIntoBatches
     from twistedcaldav.test.util import proxiesFile
-    from twistedcaldav.directory.calendaruserproxyloader import XMLCalendarUserProxyLoader
+    from twistedcaldav.directory.calendaruserproxyloader import (
+        XMLCalendarUserProxyLoader
+    )
     from twistedcaldav.directory import calendaruserproxy
-    from twistedcaldav.directory.directory import GroupMembershipCache, GroupMembershipCacheUpdater
+    from twistedcaldav.directory.directory import (
+        GroupMembershipCache, GroupMembershipCacheUpdater
+    )
     from twisted.internet.defer import inlineCallbacks
     from string import maketrans
     import ldap
@@ -38,79 +42,79 @@
 
         def test_buildFilter(self):
             mapping = {
-                "recordName" : "uid",
-                "fullName" : "cn",
-                "emailAddresses" : "mail",
-                "firstName" : "givenName",
-                "lastName" : "sn",
-                "guid" : "generateduid",
-                "memberIDAttr" : "generateduid",
+                "recordName": "uid",
+                "fullName": "cn",
+                "emailAddresses": "mail",
+                "firstName": "givenName",
+                "lastName": "sn",
+                "guid": "generateduid",
+                "memberIDAttr": "generateduid",
             }
 
             entries = [
                 {
-                    "fields" : [
+                    "fields": [
                         ("fullName", "mor", True, u"starts-with"),
                         ("emailAddresses", "mor", True, u"starts-with"),
                         ("firstName", "mor", True, u"starts-with"),
                         ("lastName", "mor", True, u"starts-with")
                     ],
-                    "operand" : "or",
-                    "recordType" : "users",
-                    "expected" : "(&(uid=*)(generateduid=*)(|(cn=mor*)(mail=mor*)(givenName=mor*)(sn=mor*)))",
-                    "optimize" : False,
+                    "operand": "or",
+                    "recordType": "users",
+                    "expected": "(&(uid=*)(generateduid=*)(|(cn=mor*)(mail=mor*)(givenName=mor*)(sn=mor*)))",
+                    "optimize": False,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("fullName", "mor(", True, u"starts-with"),
                         ("emailAddresses", "mor)", True, u"contains"),
                         ("firstName", "mor*", True, u"exact"),
                         ("lastName", "mor\\", True, u"starts-with")
                     ],
-                    "operand" : "or",
-                    "recordType" : "users",
-                    "expected" : "(&(uid=*)(generateduid=*)(|(cn=mor\\28*)(mail=*mor\\29*)(givenName=mor\\2a)(sn=mor\\5c*)))",
-                    "optimize" : False,
+                    "operand": "or",
+                    "recordType": "users",
+                    "expected": "(&(uid=*)(generateduid=*)(|(cn=mor\\28*)(mail=*mor\\29*)(givenName=mor\\2a)(sn=mor\\5c*)))",
+                    "optimize": False,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("fullName", "mor", True, u"starts-with"),
                     ],
-                    "operand" : "or",
-                    "recordType" : "users",
-                    "expected" : "(&(uid=*)(generateduid=*)(cn=mor*))",
-                    "optimize" : False,
+                    "operand": "or",
+                    "recordType": "users",
+                    "expected": "(&(uid=*)(generateduid=*)(cn=mor*))",
+                    "optimize": False,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("fullName", "mor", True, u"contains"),
                         ("emailAddresses", "mor", True, u"equals"),
                         ("invalid", "mor", True, u"starts-with"),
                     ],
-                    "operand" : "and",
-                    "recordType" : "users",
-                    "expected" : "(&(uid=*)(generateduid=*)(&(cn=*mor*)(mail=mor)))",
-                    "optimize" : False,
+                    "operand": "and",
+                    "recordType": "users",
+                    "expected": "(&(uid=*)(generateduid=*)(&(cn=*mor*)(mail=mor)))",
+                    "optimize": False,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("invalid", "mor", True, u"contains"),
                         ("invalid", "mor", True, u"starts-with"),
                     ],
-                    "operand" : "and",
-                    "recordType" : "users",
-                    "expected" : None,
-                    "optimize" : False,
+                    "operand": "and",
+                    "recordType": "users",
+                    "expected": None,
+                    "optimize": False,
                 },
                 {
-                    "fields" : [ ],
-                    "operand" : "and",
-                    "recordType" : "users",
-                    "expected" : None,
-                    "optimize" : False,
+                    "fields": [],
+                    "operand": "and",
+                    "recordType": "users",
+                    "expected": None,
+                    "optimize": False,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("fullName", "mor", True, u"starts-with"),
                         ("fullName", "sag", True, u"starts-with"),
                         ("emailAddresses", "mor", True, u"starts-with"),
@@ -120,13 +124,13 @@
                         ("lastName", "mor", True, u"starts-with"),
                         ("lastName", "sag", True, u"starts-with"),
                     ],
-                    "operand" : "or",
-                    "recordType" : "users",
-                    "expected" : "(&(uid=*)(generateduid=*)(|(&(givenName=mor*)(sn=sag*))(&(givenName=sag*)(sn=mor*))))",
-                    "optimize" : True,
+                    "operand": "or",
+                    "recordType": "users",
+                    "expected": "(&(uid=*)(generateduid=*)(|(&(givenName=mor*)(sn=sag*))(&(givenName=sag*)(sn=mor*))))",
+                    "optimize": True,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("fullName", "mor", True, u"starts-with"),
                         ("fullName", "sag", True, u"starts-with"),
                         ("emailAddresses", "mor", True, u"starts-with"),
@@ -136,13 +140,13 @@
                         ("lastName", "mor", True, u"starts-with"),
                         ("lastName", "sag", True, u"starts-with"),
                     ],
-                    "operand" : "or",
-                    "recordType" : "groups",
-                    "expected" : None,
-                    "optimize" : True,
+                    "operand": "or",
+                    "recordType": "groups",
+                    "expected": None,
+                    "optimize": True,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("fullName", "mor", True, u"starts-with"),
                         ("fullName", "sag", True, u"starts-with"),
                         ("emailAddresses", "mor", True, u"starts-with"),
@@ -152,123 +156,142 @@
                         ("lastName", "mor", True, u"starts-with"),
                         ("lastName", "sag", True, u"starts-with"),
                     ],
-                    "operand" : "or",
-                    "recordType" : "groups",
-                    "expected" : None,
-                    "optimize" : True,
+                    "operand": "or",
+                    "recordType": "groups",
+                    "expected": None,
+                    "optimize": True,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("guid", "xyzzy", True, u"equals"),
                         ("guid", "plugh", True, u"equals"),
                     ],
-                    "operand" : "or",
-                    "recordType" : "groups",
-                    "expected" : "(&(uid=*)(generateduid=*)(|(generateduid=xyzzy)(generateduid=plugh)))",
-                    "optimize" : True,
+                    "operand": "or",
+                    "recordType": "groups",
+                    "expected": "(&(uid=*)(generateduid=*)(|(generateduid=xyzzy)(generateduid=plugh)))",
+                    "optimize": True,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("fullName", "mor", True, u"contains"),
                         ("fullName", "sag", True, u"contains"),
                     ],
-                    "operand" : "or",
-                    "recordType" : "locations",
-                    "expected" : "(&(uid=*)(generateduid=*)(|(cn=*mor*)(cn=*sag*)))",
-                    "optimize" : True,
+                    "operand": "or",
+                    "recordType": "locations",
+                    "expected": "(&(uid=*)(generateduid=*)(|(cn=*mor*)(cn=*sag*)))",
+                    "optimize": True,
                 },
                 {
-                    "fields" : [
+                    "fields": [
                         ("fullName", "mor", True, u"contains"),
                         ("fullName", "sag", True, u"contains"),
                     ],
-                    "operand" : "or",
-                    "recordType" : "resources",
-                    "expected" : "(&(uid=*)(generateduid=*)(|(cn=*mor*)(cn=*sag*)))",
-                    "optimize" : True,
+                    "operand": "or",
+                    "recordType": "resources",
+                    "expected": "(&(uid=*)(generateduid=*)(|(cn=*mor*)(cn=*sag*)))",
+                    "optimize": True,
                 },
             ]
             for entry in entries:
                 self.assertEquals(
                     buildFilter(entry["recordType"], mapping, entry["fields"],
-                        operand=entry["operand"], optimizeMultiName=entry["optimize"]),
+                                operand=entry["operand"], optimizeMultiName=entry["optimize"]),
                     entry["expected"]
                 )
 
 
+
     class BuildFilterFromTokensTestCase(TestCase):
 
         def test_buildFilterFromTokens(self):
 
             entries = [
                 {
-                    "tokens" : ["foo"],
-                    "mapping" : {
-                        "fullName" : "cn",
-                        "emailAddresses" : "mail",
+                    "tokens": ["foo"],
+                    "mapping": {
+                        "fullName": "cn",
+                        "emailAddresses": "mail",
                     },
-                    "expected" : "(&(a=b)(|(cn=*foo*)(mail=foo*)))",
-                    "extra" : "(a=b)",
+                    "expected": "(&(a=b)(|(cn=*foo*)(mail=foo*)))",
+                    "extra": "(a=b)",
                 },
                 {
-                    "tokens" : ["foo"],
-                    "mapping" : {
-                        "fullName" : "cn",
-                        "emailAddresses" : ["mail", "mailAliases"],
+                    "tokens": ["foo", "foo", "oo", "fo", "bar"],
+                    "mapping": {
+                        "fullName": "cn",
+                        "emailAddresses": "mail",
                     },
-                    "expected" : "(&(a=b)(|(cn=*foo*)(mail=foo*)(mailAliases=foo*)))",
-                    "extra" : "(a=b)",
+                    "expected": "(&(a=b)(|(cn=*bar*)(mail=bar*))(|(cn=*foo*)(mail=foo*)))",
+                    "extra": "(a=b)",
                 },
                 {
-                    "tokens" : [],
-                    "mapping" : {
-                        "fullName" : "cn",
-                        "emailAddresses" : "mail",
+                    "tokens": ["fo", "foo", "foooo", "ooo", "fooo"],
+                    "mapping": {
+                        "fullName": "cn",
+                        "emailAddresses": "mail",
                     },
-                    "expected" : None,
-                    "extra" : None,
+                    "expected": "(&(a=b)(|(cn=*foooo*)(mail=foooo*)))",
+                    "extra": "(a=b)",
                 },
                 {
-                    "tokens" : ["foo", "bar"],
-                    "mapping" : { },
-                    "expected" : None,
-                    "extra" : None,
+                    "tokens": ["foo"],
+                    "mapping": {
+                        "fullName": "cn",
+                        "emailAddresses": ["mail", "mailAliases"],
+                    },
+                    "expected": "(&(a=b)(|(cn=*foo*)(mail=foo*)(mailAliases=foo*)))",
+                    "extra": "(a=b)",
                 },
                 {
-                    "tokens" : ["foo", "bar"],
-                    "mapping" : {
-                        "emailAddresses" : "mail",
+                    "tokens": [],
+                    "mapping": {
+                        "fullName": "cn",
+                        "emailAddresses": "mail",
                     },
-                    "expected" : "(&(mail=foo*)(mail=bar*))",
-                    "extra" : None,
+                    "expected": None,
+                    "extra": None,
                 },
                 {
-                    "tokens" : ["foo", "bar"],
-                    "mapping" : {
-                        "fullName" : "cn",
-                        "emailAddresses" : "mail",
+                    "tokens": ["foo", "bar"],
+                    "mapping": {},
+                    "expected": None,
+                    "extra": None,
+                },
+                {
+                    "tokens": ["foo", "bar"],
+                    "mapping": {
+                        "emailAddresses": "mail",
                     },
-                    "expected" : "(&(|(cn=*foo*)(mail=foo*))(|(cn=*bar*)(mail=bar*)))",
-                    "extra" : None,
+                    "expected": "(&(mail=bar*)(mail=foo*))",
+                    "extra": None,
                 },
                 {
-                    "tokens" : ["foo", "bar"],
-                    "mapping" : {
-                        "fullName" : "cn",
-                        "emailAddresses" : ["mail", "mailAliases"],
+                    "tokens": ["foo", "bar"],
+                    "mapping": {
+                        "fullName": "cn",
+                        "emailAddresses": "mail",
                     },
-                    "expected" : "(&(|(cn=*foo*)(mail=foo*)(mailAliases=foo*))(|(cn=*bar*)(mail=bar*)(mailAliases=bar*)))",
-                    "extra" : None,
+                    "expected": "(&(|(cn=*bar*)(mail=bar*))(|(cn=*foo*)(mail=foo*)))",
+                    "extra": None,
                 },
                 {
-                    "tokens" : ["foo", "bar", "baz("],
-                    "mapping" : {
-                        "fullName" : "cn",
-                        "emailAddresses" : "mail",
+                    "tokens": ["foo", "bar"],
+                    "mapping": {
+                        "fullName": "cn",
+                        "emailAddresses": ["mail", "mailAliases"],
                     },
-                    "expected" : "(&(|(cn=*foo*)(mail=foo*))(|(cn=*bar*)(mail=bar*))(|(cn=*baz\\28*)(mail=baz\\28*)))",
-                    "extra" : None,
+                    "expected": "(&(|(cn=*bar*)(mail=bar*)(mailAliases=bar*))(|(cn=*foo*)(mail=foo*)(mailAliases=foo*)))",
+                    "extra": None,
                 },
+                {
+                    "tokens": ["foo", "bar", "baz("],
+                    "mapping": {
+                        "fullName": "cn",
+                        "emailAddresses": "mail",
+                    },
+                    "expected": "(&(|(cn=*bar*)(mail=bar*))(|(cn=*baz\\28*)(mail=baz\\28*))(|(cn=*foo*)(mail=foo*)))",
+                    "extra": None,
+                },
             ]
             for entry in entries:
                 self.assertEquals(
@@ -277,12 +300,13 @@
                 )
 
 
+
     class StubList(object):
         def __init__(self, wrapper):
             self.ldap = wrapper
 
         def startSearch(self, base, scope, filterstr, attrList=None,
-            timeout=-1, sizelimit=0):
+                        timeout=-1, sizelimit=0):
             self.base = base
             self.scope = scope
             self.filterstr = filterstr
@@ -292,14 +316,17 @@
 
         def processResults(self):
             self.allResults = self.ldap.search_s(self.base, self.scope,
-                self.filterstr, attrlist=self.attrList)
+                                                 self.filterstr,
+                                                 attrlist=self.attrList)
 
 
+
     class StubAsync(object):
         def List(self, wrapper):
             return StubList(wrapper)
 
 
+
     class LdapDirectoryTestWrapper(object):
         """
         A test stub which replaces search_s( ) with a version that will return
@@ -317,7 +344,7 @@
 
 
         def search_s(self, base, scope, filterstr="(objectClass=*)",
-            attrlist=None):
+                     attrlist=None):
             """ A simple implementation of LDAP search filter processing """
 
             base = normalizeDNstr(base)
@@ -475,8 +502,8 @@
                         'givenName': ['Test'],
                         'cn': ['Test Resource'],
                         # purposely throw in an un-normalized GUID
-                        'read-write-proxy' : ['6423f94a-6b76-4a3a-815b-d52cfd77935d'],
-                        'read-only-proxy' : ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
+                        'read-write-proxy': ['6423f94a-6b76-4a3a-815b-d52cfd77935d'],
+                        'read-only-proxy': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
                     }
                 ),
                 (
@@ -487,14 +514,14 @@
                         'sn': ['Resource2'],
                         'givenName': ['Test'],
                         'cn': ['Test Resource2'],
-                        'read-write-proxy' : ['6423F94A-6B76-4A3A-815B-D52CFD77935D'],
+                        'read-write-proxy': ['6423F94A-6B76-4A3A-815B-D52CFD77935D'],
                     }
                 ),
             ),
             {
-                "augmentService" : None,
-                "groupMembershipCache" : None,
-                "cacheTimeout": 1, # Minutes
+                "augmentService": None,
+                "groupMembershipCache": None,
+                "cacheTimeout": 1,  # Minutes
                 "negativeCaching": False,
                 "warningThresholdSeconds": 3,
                 "batchSize": 500,
@@ -506,7 +533,7 @@
                 "tls": False,
                 "tlsCACertFile": None,
                 "tlsCACertDir": None,
-                "tlsRequireCert": None, # never, allow, try, demand, hard
+                "tlsRequireCert": None,  # never, allow, try, demand, hard
                 "credentials": {
                     "dn": None,
                     "password": None,
@@ -517,83 +544,83 @@
                     "guidAttr": "apple-generateduid",
                     "users": {
                         "rdn": "cn=Users",
-                        "attr": "uid", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "", # additional filter for this type
-                        "loginEnabledAttr" : "", # attribute controlling login
-                        "loginEnabledValue" : "yes", # "True" value of above attribute
-                        "calendarEnabledAttr" : "enable-calendar", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "uid",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "",  # additional filter for this type
+                        "loginEnabledAttr": "",  # attribute controlling login
+                        "loginEnabledValue": "yes",  # "True" value of above attribute
+                        "calendarEnabledAttr": "enable-calendar",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "uid",
-                            "fullName" : "cn",
-                            "emailAddresses" : ["mail", "emailAliases"],
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": ["mail", "emailAliases"],
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "groups": {
                         "rdn": "cn=Groups",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "", # additional filter for this type
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "",  # additional filter for this type
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : ["mail", "emailAliases"],
+                            "fullName": "cn",
+                            "emailAddresses": ["mail", "emailAliases"],
                         },
                     },
                     "locations": {
                         "rdn": "cn=Places",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "calendarEnabledAttr" : "", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "associatedAddressAttr" : "assocAddr",
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "(objectClass=apple-resource)",  # additional filter for this type
+                        "calendarEnabledAttr": "",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "associatedAddressAttr": "assocAddr",
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : "", # old style, single string
+                            "fullName": "cn",
+                            "emailAddresses": "",  # old style, single string
                         },
                     },
                     "resources": {
                         "rdn": "cn=Resources",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "calendarEnabledAttr" : "", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "(objectClass=apple-resource)",  # additional filter for this type
+                        "calendarEnabledAttr": "",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : [], # new style, array
+                            "fullName": "cn",
+                            "emailAddresses": [],  # new style, array
                         },
                     },
                     "addresses": {
                         "rdn": "cn=Buildings",
-                        "geoAttr" : "coordinates",
-                        "streetAddressAttr" : "postal",
-                        "mapping": { # maps internal record names to LDAP
+                        "geoAttr": "coordinates",
+                        "streetAddressAttr": "postal",
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
+                            "fullName": "cn",
                         },
                     },
                 },
                 "groupSchema": {
-                    "membersAttr": "uniqueMember", # how members are specified
-                    "nestedGroupsAttr": "nestedGroups", # how nested groups are specified
-                    "memberIdAttr": "", # which attribute the above refer to
+                    "membersAttr": "uniqueMember",  # how members are specified
+                    "nestedGroupsAttr": "nestedGroups",  # how nested groups are specified
+                    "memberIdAttr": "",  # which attribute the above refer to
                 },
                 "resourceSchema": {
-                    "resourceInfoAttr": "apple-resource-info", # contains location/resource info
+                    "resourceInfoAttr": "apple-resource-info",  # contains location/resource info
                     "autoScheduleAttr": None,
                     "proxyAttr": "read-write-proxy",
                     "readOnlyProxyAttr": "read-only-proxy",
                     "autoAcceptGroupAttr": None,
                 },
                 "poddingSchema": {
-                    "serverIdAttr": "server-id", # maps to augments server-id
+                    "serverIdAttr": "server-id",  # maps to augments server-id
                 },
             }
         )
@@ -711,9 +738,9 @@
                 ),
             ),
             {
-                "augmentService" : None,
-                "groupMembershipCache" : None,
-                "cacheTimeout": 1, # Minutes
+                "augmentService": None,
+                "groupMembershipCache": None,
+                "cacheTimeout": 1,  # Minutes
                 "negativeCaching": False,
                 "warningThresholdSeconds": 3,
                 "batchSize": 500,
@@ -725,7 +752,7 @@
                 "tls": False,
                 "tlsCACertFile": None,
                 "tlsCACertDir": None,
-                "tlsRequireCert": None, # never, allow, try, demand, hard
+                "tlsRequireCert": None,  # never, allow, try, demand, hard
                 "credentials": {
                     "dn": None,
                     "password": None,
@@ -736,79 +763,79 @@
                     "guidAttr": "apple-generateduid",
                     "users": {
                         "rdn": "cn=Users",
-                        "attr": "uid", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "", # additional filter for this type
-                        "loginEnabledAttr" : "", # attribute controlling login
-                        "loginEnabledValue" : "yes", # "True" value of above attribute
-                        "calendarEnabledAttr" : "enable-calendar", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "uid",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "",  # additional filter for this type
+                        "loginEnabledAttr": "",  # attribute controlling login
+                        "loginEnabledValue": "yes",  # "True" value of above attribute
+                        "calendarEnabledAttr": "enable-calendar",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "uid",
-                            "fullName" : "cn",
-                            "emailAddresses" : ["mail", "emailAliases"],
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": ["mail", "emailAliases"],
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "groups": {
                         "rdn": "cn=Groups",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "", # additional filter for this type
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "",  # additional filter for this type
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : ["mail", "emailAliases"],
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": ["mail", "emailAliases"],
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "locations": {
                         "rdn": "cn=Places",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "calendarEnabledAttr" : "", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "(objectClass=apple-resource)",  # additional filter for this type
+                        "calendarEnabledAttr": "",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : "", # old style, single string
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": "",  # old style, single string
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "resources": {
                         "rdn": "cn=Resources",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "calendarEnabledAttr" : "", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "(objectClass=apple-resource)",  # additional filter for this type
+                        "calendarEnabledAttr": "",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : [], # new style, array
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": [],  # new style, array
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                 },
                 "groupSchema": {
-                    "membersAttr": "uniqueMember", # how members are specified
-                    "nestedGroupsAttr": "", # how nested groups are specified
-                    "memberIdAttr": "", # which attribute the above refer to
+                    "membersAttr": "uniqueMember",  # how members are specified
+                    "nestedGroupsAttr": "",  # how nested groups are specified
+                    "memberIdAttr": "",  # which attribute the above refer to
                 },
                 "resourceSchema": {
-                    "resourceInfoAttr": "apple-resource-info", # contains location/resource info
+                    "resourceInfoAttr": "apple-resource-info",  # contains location/resource info
                     "autoScheduleAttr": None,
                     "proxyAttr": None,
                     "readOnlyProxyAttr": None,
                     "autoAcceptGroupAttr": None,
                 },
                 "poddingSchema": {
-                    "serverIdAttr": "server-id", # maps to augments server-id
+                    "serverIdAttr": "server-id",  # maps to augments server-id
                 },
             }
         )
@@ -928,9 +955,9 @@
                 ),
             ),
             {
-                "augmentService" : None,
-                "groupMembershipCache" : None,
-                "cacheTimeout": 1, # Minutes
+                "augmentService": None,
+                "groupMembershipCache": None,
+                "cacheTimeout": 1,  # Minutes
                 "negativeCaching": False,
                 "warningThresholdSeconds": 3,
                 "batchSize": 500,
@@ -942,7 +969,7 @@
                 "tls": False,
                 "tlsCACertFile": None,
                 "tlsCACertDir": None,
-                "tlsRequireCert": None, # never, allow, try, demand, hard
+                "tlsRequireCert": None,  # never, allow, try, demand, hard
                 "credentials": {
                     "dn": None,
                     "password": None,
@@ -953,79 +980,79 @@
                     "guidAttr": "apple-generateduid",
                     "users": {
                         "rdn": "cn=Users",
-                        "attr": "uid", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "", # additional filter for this type
-                        "loginEnabledAttr" : "", # attribute controlling login
-                        "loginEnabledValue" : "yes", # "True" value of above attribute
-                        "calendarEnabledAttr" : "enable-calendar", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "uid",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "",  # additional filter for this type
+                        "loginEnabledAttr": "",  # attribute controlling login
+                        "loginEnabledValue": "yes",  # "True" value of above attribute
+                        "calendarEnabledAttr": "enable-calendar",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "uid",
-                            "fullName" : "cn",
-                            "emailAddresses" : ["mail", "emailAliases"],
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": ["mail", "emailAliases"],
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "groups": {
                         "rdn": "cn=Groups",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "", # additional filter for this type
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "",  # additional filter for this type
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : ["mail", "emailAliases"],
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": ["mail", "emailAliases"],
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "locations": {
                         "rdn": "cn=Places",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "calendarEnabledAttr" : "", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "(objectClass=apple-resource)",  # additional filter for this type
+                        "calendarEnabledAttr": "",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : "", # old style, single string
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": "",  # old style, single string
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "resources": {
                         "rdn": "cn=Resources",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "calendarEnabledAttr" : "", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "(objectClass=apple-resource)",  # additional filter for this type
+                        "calendarEnabledAttr": "",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : [], # new style, array
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": [],  # new style, array
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                 },
                 "groupSchema": {
-                    "membersAttr": "uniqueMember", # how members are specified
-                    "nestedGroupsAttr": "nestedGroups", # how nested groups are specified
-                    "memberIdAttr": "apple-generateduid", # which attribute the above refer to
+                    "membersAttr": "uniqueMember",  # how members are specified
+                    "nestedGroupsAttr": "nestedGroups",  # how nested groups are specified
+                    "memberIdAttr": "apple-generateduid",  # which attribute the above refer to
                 },
                 "resourceSchema": {
-                    "resourceInfoAttr": "apple-resource-info", # contains location/resource info
+                    "resourceInfoAttr": "apple-resource-info",  # contains location/resource info
                     "autoScheduleAttr": None,
                     "proxyAttr": None,
                     "readOnlyProxyAttr": None,
                     "autoAcceptGroupAttr": None,
                 },
                 "poddingSchema": {
-                    "serverIdAttr": "server-id", # maps to augments server-id
+                    "serverIdAttr": "server-id",  # maps to augments server-id
                 },
             }
         )
@@ -1141,9 +1168,9 @@
                 ),
             ),
             {
-                "augmentService" : None,
-                "groupMembershipCache" : None,
-                "cacheTimeout": 1, # Minutes
+                "augmentService": None,
+                "groupMembershipCache": None,
+                "cacheTimeout": 1,  # Minutes
                 "negativeCaching": False,
                 "warningThresholdSeconds": 3,
                 "batchSize": 500,
@@ -1155,7 +1182,7 @@
                 "tls": False,
                 "tlsCACertFile": None,
                 "tlsCACertDir": None,
-                "tlsRequireCert": None, # never, allow, try, demand, hard
+                "tlsRequireCert": None,  # never, allow, try, demand, hard
                 "credentials": {
                     "dn": None,
                     "password": None,
@@ -1166,83 +1193,84 @@
                     "guidAttr": "apple-generateduid",
                     "users": {
                         "rdn": "cn=Users",
-                        "attr": "uid", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "", # additional filter for this type
-                        "loginEnabledAttr" : "", # attribute controlling login
-                        "loginEnabledValue" : "yes", # "True" value of above attribute
-                        "calendarEnabledAttr" : "enable-calendar", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "uid",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "",  # additional filter for this type
+                        "loginEnabledAttr": "",  # attribute controlling login
+                        "loginEnabledValue": "yes",  # "True" value of above attribute
+                        "calendarEnabledAttr": "enable-calendar",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "uid",
-                            "fullName" : "cn",
-                            "emailAddresses" : ["mail", "emailAliases"],
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": ["mail", "emailAliases"],
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "groups": {
                         "rdn": "cn=Groups",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "", # additional filter for this type
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "",  # additional filter for this type
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : ["mail", "emailAliases"],
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": ["mail", "emailAliases"],
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "locations": {
                         "rdn": "cn=Places",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "calendarEnabledAttr" : "", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "(objectClass=apple-resource)",  # additional filter for this type
+                        "calendarEnabledAttr": "",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : "", # old style, single string
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": "",  # old style, single string
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                     "resources": {
                         "rdn": "cn=Resources",
-                        "attr": "cn", # used only to synthesize email address
-                        "emailSuffix": None, # used only to synthesize email address
-                        "filter": "(objectClass=apple-resource)", # additional filter for this type
-                        "calendarEnabledAttr" : "", # attribute controlling calendaring
-                        "calendarEnabledValue" : "yes", # "True" value of above attribute
-                        "mapping": { # maps internal record names to LDAP
+                        "attr": "cn",  # used only to synthesize email address
+                        "emailSuffix": None,  # used only to synthesize email address
+                        "filter": "(objectClass=apple-resource)",  # additional filter for this type
+                        "calendarEnabledAttr": "",  # attribute controlling calendaring
+                        "calendarEnabledValue": "yes",  # "True" value of above attribute
+                        "mapping": {  # maps internal record names to LDAP
                             "recordName": "cn",
-                            "fullName" : "cn",
-                            "emailAddresses" : [], # new style, array
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
+                            "fullName": "cn",
+                            "emailAddresses": [],  # new style, array
+                            "firstName": "givenName",
+                            "lastName": "sn",
                         },
                     },
                 },
                 "groupSchema": {
-                    "membersAttr": "uniqueMember", # how members are specified
-                    "nestedGroupsAttr": "", # how nested groups are specified
-                    "memberIdAttr": "apple-generateduid", # which attribute the above refer to
+                    "membersAttr": "uniqueMember",  # how members are specified
+                    "nestedGroupsAttr": "",  # how nested groups are specified
+                    "memberIdAttr": "apple-generateduid",  # which attribute the above refer to
                 },
                 "resourceSchema": {
-                    "resourceInfoAttr": "apple-resource-info", # contains location/resource info
+                    "resourceInfoAttr": "apple-resource-info",  # contains location/resource info
                     "autoScheduleAttr": None,
                     "proxyAttr": None,
                     "readOnlyProxyAttr": None,
                     "autoAcceptGroupAttr": None,
                 },
                 "poddingSchema": {
-                    "serverIdAttr": "server-id", # maps to augments server-id
+                    "serverIdAttr": "server-id",  # maps to augments server-id
                 },
             }
         )
 
+
         def setupService(self, scenario):
             self.service = LdapDirectoryService(scenario[1])
             self.service.ldap = LdapDirectoryTestWrapper(self.service.ldap, scenario[0])
@@ -1286,11 +1314,14 @@
                 'cn': ['Amanda Test']
             }
 
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_users)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_users
+            )
             self.assertEquals(record.guid, guid)
-            self.assertEquals(record.emailAddresses,
-                set(['alternate at example.com', 'odtestamanda at example.com']))
+            self.assertEquals(
+                record.emailAddresses,
+                set(['alternate at example.com', 'odtestamanda at example.com'])
+            )
             self.assertEquals(record.shortNames, ('odtestamanda',))
             self.assertEquals(record.fullName, 'Amanda Test')
             self.assertEquals(record.firstName, 'Amanda')
@@ -1312,8 +1343,9 @@
                 'cn': ['Amanda Test']
             }
 
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_users)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_users
+            )
             self.assertTrue(record.enabledForCalendaring)
 
             # User with "podding" info
@@ -1324,11 +1356,12 @@
                 'uid': ['odtestamanda'],
                 'apple-generateduid': [guid],
                 'cn': ['Amanda Test'],
-                'server-id' : ["test-server-id"],
+                'server-id': ["test-server-id"],
             }
 
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_users)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_users
+            )
             self.assertEquals(record.serverID, "test-server-id")
 
             # User missing guidAttr
@@ -1339,9 +1372,11 @@
                 'cn': ['Amanda Test'],
             }
 
-            self.assertRaises(MissingGuidException,
+            self.assertRaises(
+                MissingGuidException,
                 self.service._ldapResultToRecord, dn, attrs,
-                self.service.recordType_users)
+                self.service.recordType_users
+            )
 
             # User missing record name
 
@@ -1351,9 +1386,11 @@
                 'cn': ['Amanda Test'],
             }
 
-            self.assertRaises(MissingRecordNameException,
+            self.assertRaises(
+                MissingRecordNameException,
                 self.service._ldapResultToRecord, dn, attrs,
-                self.service.recordType_users)
+                self.service.recordType_users
+            )
 
             # Group with direct user members and nested group
 
@@ -1361,23 +1398,26 @@
             guid = '6C6CD280-E6E3-11DF-9492-0800200C9A66'
             attrs = {
                 'apple-generateduid': [guid],
-                'uniqueMember':
+                'uniqueMember': [
+                    'uid=odtestamanda,cn=users,dc=example,dc=com',
+                    'uid=odtestbetty,cn=users,dc=example,dc=com',
+                    'cn=odtestgroupb,cn=groups,dc=example,dc=com',
+                ],
+                'cn': ['odtestgrouptop']
+            }
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_groups
+            )
+            self.assertEquals(record.guid, guid)
+            self.assertEquals(
+                record.memberGUIDs(),
+                set(
                     [
+                        'cn=odtestgroupb,cn=groups,dc=example,dc=com',
                         'uid=odtestamanda,cn=users,dc=example,dc=com',
                         'uid=odtestbetty,cn=users,dc=example,dc=com',
-                        'cn=odtestgroupb,cn=groups,dc=example,dc=com',
-                    ],
-                'cn': ['odtestgrouptop']
-            }
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_groups)
-            self.assertEquals(record.guid, guid)
-            self.assertEquals(record.memberGUIDs(),
-                set([
-                     'cn=odtestgroupb,cn=groups,dc=example,dc=com',
-                     'uid=odtestamanda,cn=users,dc=example,dc=com',
-                     'uid=odtestbetty,cn=users,dc=example,dc=com',
-                     ])
+                    ]
+                )
             )
 
             # Group with illegal DN value in members
@@ -1386,22 +1426,25 @@
             guid = '6C6CD280-E6E3-11DF-9492-0800200C9A66'
             attrs = {
                 'apple-generateduid': [guid],
-                'uniqueMember':
-                    [
-                        'uid=odtestamanda,cn=users,dc=example,dc=com',
-                        'uid=odtestbetty ,cn=users,dc=example,dc=com',
-                        'cn=odtestgroupb+foo,cn=groups,dc=example,dc=com',
-                    ],
+                'uniqueMember': [
+                    'uid=odtestamanda,cn=users,dc=example,dc=com',
+                    'uid=odtestbetty ,cn=users,dc=example,dc=com',
+                    'cn=odtestgroupb+foo,cn=groups,dc=example,dc=com',
+                ],
                 'cn': ['odtestgrouptop']
             }
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_groups)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_groups
+            )
             self.assertEquals(record.guid, guid)
-            self.assertEquals(record.memberGUIDs(),
-                set([
-                     'uid=odtestamanda,cn=users,dc=example,dc=com',
-                     'uid=odtestbetty,cn=users,dc=example,dc=com',
-                     ])
+            self.assertEquals(
+                record.memberGUIDs(),
+                set(
+                    [
+                        'uid=odtestamanda,cn=users,dc=example,dc=com',
+                        'uid=odtestbetty,cn=users,dc=example,dc=com',
+                    ]
+                )
             )
 
             # Resource with delegates, autoSchedule = True, and autoAcceptGroup
@@ -1429,16 +1472,22 @@
 </dict>
 </plist>"""]
             }
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_resources)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_resources
+            )
             self.assertEquals(record.guid, guid)
-            self.assertEquals(record.externalProxies(),
-                set(['6C6CD280-E6E3-11DF-9492-0800200C9A66']))
-            self.assertEquals(record.externalReadOnlyProxies(),
-                set(['6AA1AE12-592F-4190-A069-547CD83C47C0']))
+            self.assertEquals(
+                record.externalProxies(),
+                set(['6C6CD280-E6E3-11DF-9492-0800200C9A66'])
+            )
+            self.assertEquals(
+                record.externalReadOnlyProxies(),
+                set(['6AA1AE12-592F-4190-A069-547CD83C47C0'])
+            )
             self.assertTrue(record.autoSchedule)
-            self.assertEquals(record.autoAcceptGroup,
-                '77A8EB52-AA2A-42ED-8843-B2BEE863AC70')
+            self.assertEquals(
+                record.autoAcceptGroup, '77A8EB52-AA2A-42ED-8843-B2BEE863AC70'
+            )
 
             # Resource with no delegates and autoSchedule = False
 
@@ -1459,25 +1508,24 @@
 </dict>
 </plist>"""]
             }
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_resources)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_resources
+            )
             self.assertEquals(record.guid, guid)
-            self.assertEquals(record.externalProxies(),
-                set())
-            self.assertEquals(record.externalReadOnlyProxies(),
-                set())
+            self.assertEquals(record.externalProxies(), set())
+            self.assertEquals(record.externalReadOnlyProxies(), set())
             self.assertFalse(record.autoSchedule)
             self.assertEquals(record.autoAcceptGroup, "")
 
             # Now switch off the resourceInfoAttr and switch to individual
             # attributes...
             self.service.resourceSchema = {
-                "resourceInfoAttr" : "",
-                "autoScheduleAttr" : "auto-schedule",
-                "autoScheduleEnabledValue" : "yes",
-                "proxyAttr" : "proxy",
-                "readOnlyProxyAttr" : "read-only-proxy",
-                "autoAcceptGroupAttr" : "auto-accept-group",
+                "resourceInfoAttr": "",
+                "autoScheduleAttr": "auto-schedule",
+                "autoScheduleEnabledValue": "yes",
+                "proxyAttr": "proxy",
+                "readOnlyProxyAttr": "read-only-proxy",
+                "autoAcceptGroupAttr": "auto-accept-group",
             }
 
             # Resource with delegates and autoSchedule = True
@@ -1487,21 +1535,28 @@
             attrs = {
                 'apple-generateduid': [guid],
                 'cn': ['odtestresource'],
-                'auto-schedule' : ['yes'],
-                'proxy' : ['6C6CD280-E6E3-11DF-9492-0800200C9A66'],
-                'read-only-proxy' : ['6AA1AE12-592F-4190-A069-547CD83C47C0'],
-                'auto-accept-group' : ['77A8EB52-AA2A-42ED-8843-B2BEE863AC70'],
+                'auto-schedule': ['yes'],
+                'proxy': ['6C6CD280-E6E3-11DF-9492-0800200C9A66'],
+                'read-only-proxy': ['6AA1AE12-592F-4190-A069-547CD83C47C0'],
+                'auto-accept-group': ['77A8EB52-AA2A-42ED-8843-B2BEE863AC70'],
             }
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_resources)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_resources
+            )
             self.assertEquals(record.guid, guid)
-            self.assertEquals(record.externalProxies(),
-                set(['6C6CD280-E6E3-11DF-9492-0800200C9A66']))
-            self.assertEquals(record.externalReadOnlyProxies(),
-                set(['6AA1AE12-592F-4190-A069-547CD83C47C0']))
+            self.assertEquals(
+                record.externalProxies(),
+                set(['6C6CD280-E6E3-11DF-9492-0800200C9A66'])
+            )
+            self.assertEquals(
+                record.externalReadOnlyProxies(),
+                set(['6AA1AE12-592F-4190-A069-547CD83C47C0'])
+            )
             self.assertTrue(record.autoSchedule)
-            self.assertEquals(record.autoAcceptGroup,
-                '77A8EB52-AA2A-42ED-8843-B2BEE863AC70')
+            self.assertEquals(
+                record.autoAcceptGroup,
+                '77A8EB52-AA2A-42ED-8843-B2BEE863AC70'
+            )
 
             # Record with lowercase guid
             dn = "uid=odtestamanda,cn=users,dc=example,dc=com"
@@ -1514,8 +1569,9 @@
                 'givenName': ['Amanda'],
                 'cn': ['Amanda Test']
             }
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_users)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_users
+            )
             self.assertEquals(record.guid, guid.upper())
 
             # Location with associated Address
@@ -1525,14 +1581,15 @@
             attrs = {
                 "apple-generateduid": [guid],
                 "cn": ["odtestlocation"],
-                "assocAddr" : ["6C6CD280-E6E3-11DF-9492-0800200C9A66"],
+                "assocAddr": ["6C6CD280-E6E3-11DF-9492-0800200C9A66"],
             }
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_locations)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_locations
+            )
             self.assertEquals(record.extras, {
                 "associatedAddress": "6C6CD280-E6E3-11DF-9492-0800200C9A66"
             })
-           
+
             # Address with street and geo
 
             dn = "cn=odtestaddress,cn=buildings,dc=example,dc=com"
@@ -1540,16 +1597,16 @@
             attrs = {
                 "apple-generateduid": [guid],
                 "cn": ["odtestaddress"],
-                "coordinates" : ["geo:1,2"],
-                "postal" : ["1 Infinite Loop, Cupertino, CA"],
+                "coordinates": ["geo:1,2"],
+                "postal": ["1 Infinite Loop, Cupertino, CA"],
             }
-            record = self.service._ldapResultToRecord(dn, attrs,
-                self.service.recordType_addresses)
+            record = self.service._ldapResultToRecord(
+                dn, attrs, self.service.recordType_addresses
+            )
             self.assertEquals(record.extras, {
                 "geo": "geo:1,2",
-                "streetAddress" : "1 Infinite Loop, Cupertino, CA",
+                "streetAddress": "1 Infinite Loop, Cupertino, CA",
             })
-           
 
         def test_listRecords(self):
             """
@@ -1562,7 +1619,7 @@
             self.assertEquals(len(records), 4)
             self.assertEquals(
                 set([r.firstName for r in records]),
-                set(["Amanda", "Betty", "Cyrus", "Wilfredo"]) # Carlene is skipped because no guid in LDAP
+                set(["Amanda", "Betty", "Cyrus", "Wilfredo"])  # Carlene is skipped because no guid in LDAP
             )
 
         def test_restrictedPrincipalsUsingDN(self):
@@ -1574,18 +1631,20 @@
             for scenario in (
                 self.nestedUsingSameAttributeUsingDN,
                 self.nestedUsingDifferentAttributeUsingDN,
-                ):
+            ):
                 self.setupService(scenario)
 
                 self.assertEquals(
-                    set([
-                        "cn=left_coast,cn=groups,dc=example,dc=com",
-                        "cn=right_coast,cn=groups,dc=example,dc=com",
-                        "uid=cdaboo,cn=users,dc=example,dc=com",
-                        "uid=dreid,cn=users,dc=example,dc=com",
-                        "uid=lecroy,cn=users,dc=example,dc=com",
-                        "uid=wsanchez,cn=users,dc=example,dc=com",
-                    ]),
+                    set(
+                        [
+                            "cn=left_coast,cn=groups,dc=example,dc=com",
+                            "cn=right_coast,cn=groups,dc=example,dc=com",
+                            "uid=cdaboo,cn=users,dc=example,dc=com",
+                            "uid=dreid,cn=users,dc=example,dc=com",
+                            "uid=lecroy,cn=users,dc=example,dc=com",
+                            "uid=wsanchez,cn=users,dc=example,dc=com",
+                        ]
+                    ),
                     self.service.restrictedPrincipals)
 
                 dn = "uid=cdaboo,cn=users,dc=example,dc=com"
@@ -1620,16 +1679,18 @@
             for scenario in (
                 self.nestedUsingDifferentAttributeUsingGUID,
                 self.nestedUsingSameAttributeUsingGUID,
-                ):
+            ):
                 self.setupService(scenario)
 
                 self.assertEquals(
-                    set([
-                        "left_coast",
-                        "right_coast",
-                        "5A985493-EE2C-4665-94CF-4DFEA3A89500",
-                        "6423F94A-6B76-4A3A-815B-D52CFD77935D",
-                    ]),
+                    set(
+                        [
+                            "left_coast",
+                            "right_coast",
+                            "5A985493-EE2C-4665-94CF-4DFEA3A89500",
+                            "6423F94A-6B76-4A3A-815B-D52CFD77935D",
+                        ]
+                    ),
                     self.service.restrictedPrincipals)
 
                 dn = "uid=cdaboo,cn=users,dc=example,dc=com"
@@ -1674,8 +1735,10 @@
             # Set up the GroupMembershipCache
             cache = GroupMembershipCache("ProxyDB", expireSeconds=60)
             self.service.groupMembershipCache = cache
-            updater = GroupMembershipCacheUpdater(calendaruserproxy.ProxyDBService,
-                self.service, 30, 15, 30, cache=cache, useExternalProxies=False)
+            updater = GroupMembershipCacheUpdater(
+                calendaruserproxy.ProxyDBService,
+                self.service, 30, 15, 30, cache=cache, useExternalProxies=False
+            )
 
             self.assertEquals((False, 8, 8), (yield updater.updateCache()))
 
@@ -1708,21 +1771,24 @@
                 ]
             )
 
-
         def test_splitIntoBatches(self):
             self.setupService(self.nestedUsingDifferentAttributeUsingDN)
             # Data is perfect multiple of size
             results = list(splitIntoBatches(set(range(12)), 4))
-            self.assertEquals(results,
-                [set([0, 1, 2, 3]), set([4, 5, 6, 7]), set([8, 9, 10, 11])])
+            self.assertEquals(
+                results,
+                [set([0, 1, 2, 3]), set([4, 5, 6, 7]), set([8, 9, 10, 11])]
+            )
 
             # Some left overs
             results = list(splitIntoBatches(set(range(12)), 5))
-            self.assertEquals(results,
-                [set([0, 1, 2, 3, 4]), set([8, 9, 5, 6, 7]), set([10, 11])])
+            self.assertEquals(
+                results,
+                [set([0, 1, 2, 3, 4]), set([8, 9, 5, 6, 7]), set([10, 11])]
+            )
 
             # Empty
-            results = list(splitIntoBatches(set([]), 5)) # empty data
+            results = list(splitIntoBatches(set([]), 5))  # empty data
             self.assertEquals(results, [set([])])
 
         def test_recordTypeForDN(self):
@@ -1772,7 +1838,8 @@
             self.history = []
 
             def stubSearchMethod(base, scope, filterstr="(objectClass=*)",
-                attrlist=None, timeoutSeconds=-1, resultLimit=0):
+                                 attrlist=None, timeoutSeconds=-1,
+                                 resultLimit=0):
                 self.history.append((base, scope, filterstr))
 
             recordTypes = [

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_livedirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_livedirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_livedirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_modify.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_modify.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_modify.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_opendirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_opendirectory.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_opendirectory.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_opendirectorybacker.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_opendirectorybacker.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_principal.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_principal.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_proxyprincipaldb.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_proxyprincipaldb.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_proxyprincipaldb.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_proxyprincipalmembers.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_proxyprincipalmembers.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_proxyprincipalmembers.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_resources.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_resources.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_resources.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_wiki.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_wiki.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_wiki.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_xmlfile.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_xmlfile.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/test_xmlfile.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/test/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test.test_util -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/wiki.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/wiki.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/wiki.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlaccountsparser.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlaccountsparser.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlaugmentsparser.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlaugmentsparser.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlaugmentsparser.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlfile.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directory/xmlfile.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directorybackedaddressbook.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directorybackedaddressbook.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/directorybackedaddressbook.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/dropbox.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/dropbox.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/dropbox.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/extensions.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/extensions.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_extensions -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/freebusyurl.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/freebusyurl.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/freebusyurl.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/ical.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/ical.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/ical.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_icalendar -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -1213,34 +1213,42 @@
         if master:
             # Check if cut-off matches an RDATE
             adjusted_rid = rid
+            adjust_rrule = None
+            adjust_count = 0
             continuing_rrule = True
-            rdates = set([v.getValue() for v in itertools.chain(*[rdate.value() for rdate in master.properties("RDATE")])])
-            if rid in rdates:
-                # Need to detect the first valid RRULE instance after the cut-off
-                rrules = master._pycalendar.getRecurrenceSet()
-                if rrules and len(rrules.getRules()) != 0:
-                    rrule = rrules.getRules()[0]
-                    upperlimit = rid.duplicate()
-                    upperlimit.offsetYear(1)
-                    rrule_expanded = []
-                    rrule.expand(
-                        master.propertyValue("DTSTART"),
-                        Period(DateTime(1900, 1, 1), upperlimit),
-                        rrule_expanded,
-                    )
-                    for i in sorted(rrule_expanded):
-                        if i > rid:
-                            adjusted_rid = i
-                            break
-                    else:
-                        # RRULE not needed in derived master
-                        continuing_rrule = False
 
+            # Need to detect the first valid RRULE instance after the cut-off as that needs to be the new DTSTART
+            rrules = master._pycalendar.getRecurrenceSet()
+            if rrules and len(rrules.getRules()) != 0:
+                rrule = rrules.getRules()[0]
+                upperlimit = rid.duplicate()
+                upperlimit.offsetYear(1)
+                rrule_expanded = []
+                rrule.expand(
+                    master.propertyValue("DTSTART"),
+                    Period(DateTime(1900, 1, 1), upperlimit),
+                    rrule_expanded,
+                )
+                for ctr, i in enumerate(sorted(rrule_expanded)):
+                    if i >= rid:
+                        adjusted_rid = i
+                        adjust_rrule = rrule
+                        adjust_count = ctr
+                        break
+                else:
+                    # RRULE not needed in derived master
+                    continuing_rrule = False
+
             # Adjust master to previously derived instance
             derived = self.deriveInstance(adjusted_rid, allowExcluded=True)
             if derived is None:
                 return
 
+            # Adjust any COUNT to exclude the earlier instances - note we do this after
+            # deriving the instance otherwise it might truncate the instance we care about
+            if adjust_rrule is not None and rrule.getUseCount():
+                adjust_rrule.setCount(adjust_rrule.getCount() - adjust_count)
+
             # Fix up recurrence properties so the derived one looks like the master
             derived.removeProperty(derived.getProperty("RECURRENCE-ID"))
             for property in list(itertools.chain(
@@ -3645,7 +3653,7 @@
     icalstr = str(icalstr).replace("\r\n ", "")
     icalstr = icalstr.replace("\n ", "")
     icalstr = "\r\n".join([line for line in icalstr.splitlines() if not line.startswith("DTSTAMP")])
-    return icalstr
+    return icalstr + "\r\n"
 
 
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/icaldav.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/icaldav.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/icaldav.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/instance.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/instance.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/instance.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/linkresource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/linkresource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/linkresource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/localization.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/localization.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/localization.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcachelock.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcachelock.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcachelock.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcachepool.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcachepool.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcachepool.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcacheprops.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcacheprops.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcacheprops.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Computer, Inc. All rights reserved.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcacher.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcacher.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/memcacher.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/acl.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/acl.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/acl.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/get.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/get.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/get.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/mkcalendar.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/mkcalendar.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/mkcalendar.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/mkcol.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/mkcol.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/mkcol.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_DAV.MKCOL -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/post.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/post.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/post.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 # #
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@
 __all__ = ["http_POST"]
 
 from txweb2 import responsecode
-from txweb2.http import StatusResponse
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 
@@ -45,13 +44,9 @@
         action = request.args.get("action", ("",))
         if len(action) == 1:
             action = action[0]
-            if action in ("attachment-add", "attachment-update", "attachment-remove") and \
-                hasattr(self, "POST_handler_attachment"):
-                if config.EnableManagedAttachments:
-                    result = (yield self.POST_handler_attachment(request, action))
-                    returnValue(result)
-                else:
-                    returnValue(StatusResponse(responsecode.FORBIDDEN, "Managed Attachments not supported."))
+            if hasattr(self, "POST_handler_action"):
+                result = (yield self.POST_handler_action(request, action))
+                returnValue(result)
 
     # Content-type handlers
     contentType = request.headers.getHeader("content-type")

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/propfind.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/propfind.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/propfind.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_prop.PROP.test_PROPFIND -*-
 ##
-# Copyright (c) 2005-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Computer, Inc. All rights reserved.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Computer, Inc. All rights reserved.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_addressbook_multiget.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_addressbook_multiget.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_addressbook_multiget.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_addressbook_query.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_addressbook_query.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_addressbook_query.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_addressbookquery -*-
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
 
 from twext.python.log import Logger
 from txweb2 import responsecode
-from txdav.xml import element as davxml
 from txweb2.dav.http import ErrorResponse, MultiStatusResponse
 from txweb2.dav.method.report import NumberOfMatchesWithinLimits
 from txweb2.dav.util import joinURL
@@ -37,9 +36,11 @@
 from twistedcaldav.config import config
 from twistedcaldav.carddavxml import carddav_namespace, NResults
 from twistedcaldav.method import report_common
-from twistedcaldav.query import addressbookqueryfilter
 
-from txdav.common.icommondatastore import ConcurrentModification
+from txdav.carddav.datastore.query.filter import Filter
+from txdav.common.icommondatastore import ConcurrentModification, \
+    IndexedSearchException
+from txdav.xml import element as davxml
 
 log = Logger()
 
@@ -62,7 +63,7 @@
     responses = []
 
     xmlfilter = addressbook_query.filter
-    filter = addressbookqueryfilter.Filter(xmlfilter)
+    filter = Filter(xmlfilter)
     query = addressbook_query.props
     limit = addressbook_query.limit
 
@@ -209,7 +210,7 @@
                                                         carddavxml.TextMatch.fromString(resource_name[:-4]),
                                                         name="UID", # attributes
                                                         ), ])
-                            vCardFilter = addressbookqueryfilter.Filter(vCardFilter)
+                            vCardFilter = Filter(vCardFilter)
 
                             directoryAddressBookLock, limited[0] = (yield  directory.cacheVCardsForAddressBookQuery(vCardFilter, query, max_number_of_results[0]))
 
@@ -230,11 +231,13 @@
 
                     # Check for disabled access
                     if filteredaces is not None:
-                        # See whether the filter is valid for an index only query
-                        index_query_ok = addrresource.index().searchValid(filter)
-
-                        # Get list of children that match the search and have read access
-                        names = [name for name, ignore_uid in (yield addrresource.index().search(filter))] #@UnusedVariable
+                        index_query_ok = True
+                        try:
+                            # Get list of children that match the search and have read access
+                            names = [name for name, ignore_uid in (yield addrresource.search(filter))] #@UnusedVariable
+                        except IndexedSearchException:
+                            names = yield addrresource.listChildren()
+                            index_query_ok = False
                         if not names:
                             return
 
@@ -277,7 +280,7 @@
                                                     carddavxml.TextMatch.fromString(resource_name[:-4]),
                                                     name="UID", # attributes
                                                     ), ])
-                        vCardFilter = addressbookqueryfilter.Filter(vCardFilter)
+                        vCardFilter = Filter(vCardFilter)
 
                         yield  maybeDeferred(queryDirectoryBackedAddressBook, parent, vCardFilter)
                         handled = True

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_calendar_multiget.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_calendar_multiget.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_calendar_multiget.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_calendar_query.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_calendar_query.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_calendar_query.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -20,8 +20,7 @@
 
 __all__ = ["report_urn_ietf_params_xml_ns_caldav_calendar_query"]
 
-from twisted.internet.defer import inlineCallbacks, returnValue, \
-    maybeDeferred
+from twisted.internet.defer import inlineCallbacks, returnValue
 
 from twext.python.log import Logger
 from txweb2 import responsecode
@@ -39,8 +38,8 @@
     ConcurrentModification
 from twistedcaldav.instance import TooManyInstancesError
 from twistedcaldav.method import report_common
-from twistedcaldav.query import calendarqueryfilter
 
+from txdav.caldav.datastore.query.filter import Filter
 from txdav.caldav.icalendarstore import TimeRangeLowerLimit, TimeRangeUpperLimit
 from txdav.xml import element as davxml
 
@@ -66,7 +65,7 @@
     responses = []
 
     xmlfilter = calendar_query.filter
-    filter = calendarqueryfilter.Filter(xmlfilter)
+    filter = Filter(xmlfilter)
     props = calendar_query.props
 
     assert props is not None
@@ -190,13 +189,11 @@
             if filteredaces is not None:
                 index_query_ok = True
                 try:
-                    # Get list of children that match the search and have read
-                    # access
-                    records = yield maybeDeferred(calresource.index().indexedSearch, filter)
+                    # Get list of children that match the search and have read access
+                    names = [name for name, ignore_uid, ignore_type in (yield calresource.search(filter))]
                 except IndexedSearchException:
-                    records = yield maybeDeferred(calresource.index().bruteForceSearch)
+                    names = yield calresource.listChildren()
                     index_query_ok = False
-                names = [name for name, ignore_uid, ignore_type in records]
 
                 if not names:
                     returnValue(True)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_common.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_common.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_common.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -36,17 +36,16 @@
 except ImportError:
     from md5 import new as md5
 
-from twisted.internet.defer import inlineCallbacks, returnValue, maybeDeferred
+from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python.failure import Failure
+
 from txweb2 import responsecode
-
-from txdav.xml import element
 from txweb2.dav.http import statusForFailure
 from txweb2.dav.method.propfind import propertyName
 from txweb2.dav.method.report import NumberOfMatchesWithinLimits
 from txweb2.dav.method.report import max_number_of_matches
 from txweb2.dav.resource import AccessDeniedError
-from txweb2.http import HTTPError
+from txweb2.http import HTTPError, StatusResponse
 
 from twext.python.log import Logger
 
@@ -65,9 +64,9 @@
 from twistedcaldav.instance import InstanceList
 from twistedcaldav.memcacher import Memcacher
 
-from twistedcaldav.query import calendarqueryfilter
-
+from txdav.caldav.datastore.query.filter import Filter
 from txdav.common.icommondatastore import IndexedSearchException
+from txdav.xml import element
 
 from pycalendar.duration import Duration
 from pycalendar.datetime import DateTime
@@ -583,17 +582,18 @@
                           name="VCALENDAR",
                        )
                   )
-        filter = calendarqueryfilter.Filter(filter)
+        filter = Filter(filter)
         tzinfo = filter.settimezone(tz)
 
         try:
-            resources = yield maybeDeferred(calresource.index().indexedSearch,
-                filter, useruid=useruid, fbtype=True
-            )
+            resources = yield calresource.search(filter, useruid=useruid, fbtype=True)
             if caching:
                 yield FBCacheEntry.makeCacheEntry(calresource, useruid, cache_timerange, resources)
         except IndexedSearchException:
-            resources = yield maybeDeferred(calresource.index().bruteForceSearch)
+            raise HTTPError(StatusResponse(
+                responsecode.INTERNAL_SERVER_ERROR,
+                "Failed freebusy query"
+            ))
 
     else:
         # Log extended item

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_freebusy.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_freebusy.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_freebusy.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_multiget_common.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_multiget_common.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_multiget_common.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -23,9 +23,8 @@
 from urllib import unquote
 
 from twext.python.log import Logger
+
 from txweb2 import responsecode
-from txdav.xml import element as davxml
-from txdav.xml.base import dav_namespace
 from txweb2.dav.http import ErrorResponse, MultiStatusResponse
 from txweb2.dav.resource import AccessDeniedError
 from txweb2.http import HTTPError, StatusResponse
@@ -37,11 +36,14 @@
 from twistedcaldav.carddavxml import carddav_namespace
 from twistedcaldav.config import config
 from twistedcaldav.method import report_common
-from txdav.common.icommondatastore import ConcurrentModification
 from twistedcaldav.method.report_common import COLLECTION_TYPE_CALENDAR, \
     COLLECTION_TYPE_ADDRESSBOOK
-from twistedcaldav.query import addressbookqueryfilter
 
+from txdav.carddav.datastore.query.filter import Filter
+from txdav.common.icommondatastore import ConcurrentModification
+from txdav.xml import element as davxml
+from txdav.xml.base import dav_namespace
+
 log = Logger()
 
 @inlineCallbacks
@@ -265,7 +267,7 @@
                     returnValue(None)
 
                 addressBookFilter = carddavxml.Filter(*vCardFilters)
-                addressBookFilter = addressbookqueryfilter.Filter(addressBookFilter)
+                addressBookFilter = Filter(addressBookFilter)
                 if self.directory.cacheQuery:
                     # add vcards to directory address book and run "normal case" below
                     limit = config.DirectoryAddressBook.MaxQueryResults
@@ -333,11 +335,11 @@
                     parent = (yield child.locateParent(request, resource_uri))
 
                     if collection_type == COLLECTION_TYPE_CALENDAR:
-                        if not parent.isCalendarCollection() or not (yield parent.index().resourceExists(name)):
+                        if not parent.isCalendarCollection() or not (yield parent.resourceExists(name)):
                             responses.append(davxml.StatusResponse(href, davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
                             continue
                     elif collection_type == COLLECTION_TYPE_ADDRESSBOOK:
-                        if not parent.isAddressBookCollection() or not (yield parent.index().resourceExists(name)):
+                        if not parent.isAddressBookCollection() or not (yield parent.resourceExists(name)):
                             responses.append(davxml.StatusResponse(href, davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
                             continue
 
@@ -367,11 +369,11 @@
                     parent = (yield self.locateParent(request, resource_uri))
 
                     if collection_type == COLLECTION_TYPE_CALENDAR:
-                        if not parent.isPseudoCalendarCollection() or not (yield parent.index().resourceExists(name)):
+                        if not parent.isPseudoCalendarCollection() or not (yield parent.resourceExists(name)):
                             responses.append(davxml.StatusResponse(href, davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
                             continue
                     elif collection_type == COLLECTION_TYPE_ADDRESSBOOK:
-                        if not parent.isAddressBookCollection() or not (yield parent.index().resourceExists(name)):
+                        if not parent.isAddressBookCollection() or not (yield parent.resourceExists(name)):
                             responses.append(davxml.StatusResponse(href, davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
                             continue
                     child = self

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_sync_collection.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_sync_collection.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/method/report_sync_collection.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/mkcolxml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/mkcolxml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/mkcolxml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/notifications.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/notifications.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/notifications.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_resource,twistedcaldav.test.test_wrapping -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -2667,10 +2667,9 @@
     @inlineCallbacks
     def _indexWhatChanged(self, revision, depth):
         # The newstore implementation supports this directly
-        changed, deleted = yield self._newStoreHome.resourceNamesSinceToken(
+        changed, deleted, notallowed = yield self._newStoreHome.resourceNamesSinceToken(
             revision, depth
         )
-        notallowed = []
 
         # Need to insert some addition items on first sync
         if revision == 0:
@@ -2894,10 +2893,9 @@
     @inlineCallbacks
     def _indexWhatChanged(self, revision, depth):
         # The newstore implementation supports this directly
-        changed, deleted = yield self._newStoreHome.resourceNamesSinceToken(
+        changed, deleted, notallowed = yield self._newStoreHome.resourceNamesSinceToken(
             revision, depth
         )
-        notallowed = []
 
         # Need to insert some addition items on first sync
         if revision == 0:

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test.test_calendar -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/test/test_resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/scheduling_store/caldav/test/test_resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/sharing.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/sharing.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_sharing -*-
 # #
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -267,10 +267,10 @@
         """
         if self._newStoreObject.direct():
             owner = self.principalForUID(self._newStoreObject.ownerHome().uid())
+            sharee = self.principalForUID(self._newStoreObject.viewerHome().uid())
             if owner.record.recordType == WikiDirectoryService.recordType_wikis:
                 # Access level comes from what the wiki has granted to the
                 # sharee
-                sharee = self.principalForUID(self._newStoreObject.viewerHome().uid())
                 userID = sharee.record.guid
                 wikiID = owner.record.shortNames[0]
                 access = (yield getWikiAccess(userID, wikiID))
@@ -281,7 +281,12 @@
                 else:
                     returnValue(None)
             else:
-                returnValue("original")
+                # Check proxy access
+                proxy_mode = yield sharee.proxyMode(owner)
+                if proxy_mode == "none":
+                    returnValue("original")
+                else:
+                    returnValue("read-write" if proxy_mode == "write" else "read-only")
         else:
             # Invited shares use access mode from the invite
             # Get the access for self
@@ -318,7 +323,7 @@
         sharee = self.principalForUID(self._newStoreObject.viewerHome().uid())
         access = yield self._checkAccessControl()
 
-        if access == "original":
+        if access == "original" and not self._newStoreObject.ownerHome().external():
             original = (yield request.locateResource(self._share_url))
             result = (yield original.accessControlList(request, *args, **kwargs))
             returnValue(result)
@@ -805,6 +810,12 @@
 
         # Accept the share
         shareeView = yield self._newStoreHome.acceptShare(inviteUID, summary)
+        if shareeView is None:
+            raise HTTPError(ErrorResponse(
+                responsecode.FORBIDDEN,
+                (calendarserver_namespace, "invalid-share"),
+                "Invite UID not valid",
+            ))
 
         # Return the URL of the shared collection
         sharedAsURL = joinURL(self.url(), shareeView.shareName())
@@ -820,7 +831,13 @@
     def declineShare(self, request, inviteUID):
 
         # Remove it if it is in the DB
-        yield self._newStoreHome.declineShare(inviteUID)
+        result = yield self._newStoreHome.declineShare(inviteUID)
+        if not result:
+            raise HTTPError(ErrorResponse(
+                responsecode.FORBIDDEN,
+                (calendarserver_namespace, "invalid-share"),
+                "Invite UID not valid",
+            ))
         returnValue(Response(code=responsecode.NO_CONTENT))
 
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/simpleresource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/simpleresource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/simpleresource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/sql.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/stdconfig.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/stdconfig.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_stdconfig -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -318,6 +318,13 @@
                                     # upgrade.
 
     #
+    # Work queue configuration information
+    #
+    "WorkQueue" : {
+        "ampPort": 7654,            # Port used for hosts in a cluster to take to each other
+    },
+
+    #
     # Types of service provided
     #
     "EnableCalDAV"  : True, # Enable CalDAV service
@@ -361,7 +368,7 @@
     #
     # Directory service
     #
-    #    A directory service provides information about principals (eg.
+    #    A directory service provides information about principals (e.g.
     #    users, groups, locations and resources) to the server.
     #
     "DirectoryService": {
@@ -829,8 +836,9 @@
     "Servers" : {
         "Enabled": False,                   # Multiple servers enabled or not
         "ConfigFile": "localservers.xml",   # File path for server information
-        "MaxClients": 5,                    # Pool size for connections to between servers
+        "MaxClients": 5,                    # Pool size for connections between servers
         "InboxName": "podding",             # Name for top-level inbox resource
+        "ConduitName": "conduit",           # Name for top-level cross-pod resource
     },
 
     #
@@ -1071,8 +1079,11 @@
         def _loadImport(childDict):
             # Look for an import and read that one as the main config and merge the current one into that
             if "ImportConfig" in childDict and childDict.ImportConfig:
-                configRoot = os.path.join(childDict.ServerRoot, childDict.ConfigRoot)
-                path = _expandPath(fullServerPath(configRoot, childDict.ImportConfig))
+                if childDict.ImportConfig[0] != ".":
+                    configRoot = os.path.join(childDict.ServerRoot, childDict.ConfigRoot)
+                    path = _expandPath(fullServerPath(configRoot, childDict.ImportConfig))
+                else:
+                    path = childDict.ImportConfig
                 if os.path.exists(path):
                     importDict = ConfigDict(self._parseConfigFromFile(path))
                     if importDict:
@@ -1568,6 +1579,7 @@
                         (direction,))
 
 
+
 def _updateSharing(configDict, reloading=False):
     #
     # Sharing
@@ -1578,6 +1590,7 @@
         PerUserDataFilter.IGNORE_X_PROPERTIES.append(propertyName)
 
 
+
 def _updateServers(configDict, reloading=False):
     from txdav.caldav.datastore.scheduling.ischedule.localservers import Servers
     if configDict.Servers.Enabled:
@@ -1617,6 +1630,7 @@
             compliance += customxml.calendarserver_partstat_changes_compliance
         if configDict.EnableTimezonesByReference:
             compliance += caldavxml.caldav_timezones_by_reference_compliance
+        compliance += customxml.calendarserver_recurrence_split
     else:
         compliance = ()
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/storebridge.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/storebridge.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_wrapping -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@
     TooManyAttendeesError, InvalidCalendarAccessError, ValidOrganizerError, \
     InvalidPerUserDataMerge, \
     AttendeeAllowedError, ResourceDeletedError, InvalidAttachmentOperation, \
-    ShareeAllowedError, DuplicatePrivateCommentsError
+    ShareeAllowedError, DuplicatePrivateCommentsError, InvalidSplit
 from txdav.carddav.iaddressbookstore import KindChangeNotAllowedError, \
     GroupWithUnsharedAddressNotAllowedError
 from txdav.common.datastore.sql_tables import _BIND_MODE_READ, _BIND_MODE_WRITE, \
@@ -286,13 +286,6 @@
         return self._parentResource
 
 
-    def index(self):
-        """
-        Retrieve the new-style index wrapper.
-        """
-        return self._newStoreObject.retrieveOldIndex()
-
-
     def exists(self):
         # FIXME: tests
         return self._newStoreObject is not None
@@ -303,7 +296,6 @@
         # The newstore implementation supports this directly
         returnValue(
             (yield self._newStoreObject.resourceNamesSinceToken(revision))
-            + ([],)
         )
 
 
@@ -347,6 +339,18 @@
         return self._newStoreObject.countObjectResources()
 
 
+    @inlineCallbacks
+    def resourceExists(self, name):
+        """
+        Indicate whether a resource with the specified name exists.
+
+        @return: C{True} if it exists
+        @rtype: C{bool}
+        """
+        allNames = yield self._newStoreObject.listObjectResources()
+        returnValue(name in allNames)
+
+
     def name(self):
         return self._name
 
@@ -462,6 +466,8 @@
         if self.isShareeResource():
             log.debug("Removing shared collection %s" % (self,))
             yield self.removeShareeResource(request)
+            # Re-initialize to get stuff setup again now we have no object
+            self._initializeWithHomeChild(None, self._parentResource)
             returnValue(NO_CONTENT)
 
         log.debug("Deleting collection %s" % (self,))
@@ -488,11 +494,6 @@
 
         # Now do normal delete
 
-        # Handle sharing
-        wasShared = self.isShared()
-        if wasShared:
-            yield self.downgradeFromShare(request)
-
         # Actually delete it.
         yield self._newStoreObject.remove()
 
@@ -968,6 +969,10 @@
                     )
 
 
+    def search(self, filter, **kwargs):
+        return self._newStoreObject.search(filter, **kwargs)
+
+
     def notifierID(self):
         return "%s/%s" % self._newStoreObject.notifierID()
 
@@ -1121,7 +1126,7 @@
         isowner = (yield self.isOwner(request))
         accessPrincipal = (yield self.resourceOwnerPrincipal(request))
 
-        for name, _ignore_uid, _ignore_type in (yield maybeDeferred(self.index().bruteForceSearch)):
+        for name in (yield self._newStoreObject.listObjectResources()):
             try:
                 child = yield request.locateChildResource(self, name)
             except TypeError:
@@ -2421,6 +2426,7 @@
 
         try:
             response = (yield self.storeMove(request, destinationparent, destination.name()))
+            self._newStoreObject = None
             returnValue(response)
 
         # Handle the various store errors
@@ -2915,8 +2921,130 @@
         returnValue(result)
 
 
+    @inlineCallbacks
+    def POST_handler_action(self, request, action):
+        """
+        Handle a POST request with an action= query parameter
+
+        @param request: the request to process
+        @type request: L{Request}
+        @param action: the action to execute
+        @type action: C{str}
+        """
+        if action.startswith("attachment-"):
+            result = (yield self.POST_handler_attachment(request, action))
+            returnValue(result)
+        else:
+            actioner = {
+                "split": self.POST_handler_split,
+            }
+            if action in actioner:
+                result = (yield actioner[action](request, action))
+                returnValue(result)
+            else:
+                raise HTTPError(ErrorResponse(
+                    FORBIDDEN,
+                    (caldav_namespace, "valid-action-parameter",),
+                    "The action parameter in the request-URI is not valid",
+                ))
+
+
     @requiresPermissions(davxml.WriteContent())
     @inlineCallbacks
+    def POST_handler_split(self, request, action):
+        """
+        Handle a split of a calendar object resource.
+
+        @param request: HTTP request object
+        @type request: L{Request}
+        @param action: The request-URI 'action' argument
+        @type action: C{str}
+
+        @return: an HTTP response
+        """
+
+        # Resource must exist
+        if not self.exists():
+            raise HTTPError(NOT_FOUND)
+
+        # Split point is in the rid query parameter
+        rid = request.args.get("rid")
+        if rid is None:
+            raise HTTPError(ErrorResponse(
+                FORBIDDEN,
+                (caldav_namespace, "valid-rid-parameter",),
+                "The rid parameter in the request-URI contains an invalid value",
+            ))
+
+        try:
+            rid = DateTime.parseText(rid[0])
+        except ValueError:
+            raise HTTPError(ErrorResponse(
+                FORBIDDEN,
+                (caldav_namespace, "valid-rid-parameter",),
+                "The rid parameter in the request-URI contains an invalid value",
+            ))
+        try:
+            otherStoreObject = yield self._newStoreObject.splitAt(rid)
+        except InvalidSplit:
+            raise HTTPError(ErrorResponse(
+                FORBIDDEN,
+                (calendarserver_namespace, "invalid-split",),
+                "The rid parameter in the request-URI contains an invalid value",
+            ))
+
+        other = yield request.locateChildResource(self._parentResource, otherStoreObject.name())
+        if other is None:
+            raise responsecode.INTERNAL_SERVER_ERROR
+
+        # Look for Prefer header
+        prefer = request.headers.getHeader("prefer", {})
+        returnRepresentation = any([key == "return" and value == "representation" for key, value, _ignore_args in prefer])
+
+        if returnRepresentation:
+            # Accept header handling
+            accepted_type = bestAcceptType(request.headers.getHeader("accept"), Component.allowedTypes())
+            if accepted_type is None:
+                raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, "Cannot generate requested data type"))
+            etag1 = yield self.etag()
+            etag2 = yield other.etag()
+            cal1 = yield self.component()
+            cal2 = yield other.component()
+
+            xml_responses = [
+                davxml.PropertyStatusResponse(
+                    davxml.HRef.fromString(self.url()),
+                    davxml.PropertyStatus(
+                        davxml.PropertyContainer(
+                            davxml.GETETag.fromString(etag1.generate()),
+                            caldavxml.CalendarData.fromComponent(cal1, accepted_type),
+                        ),
+                        davxml.Status.fromResponseCode(OK),
+                    )
+                ),
+                davxml.PropertyStatusResponse(
+                    davxml.HRef.fromString(other.url()),
+                    davxml.PropertyStatus(
+                        davxml.PropertyContainer(
+                            davxml.GETETag.fromString(etag2.generate()),
+                            caldavxml.CalendarData.fromComponent(cal2, accepted_type),
+                        ),
+                        davxml.Status.fromResponseCode(OK),
+                    )
+                ),
+            ]
+
+            # Return multistatus with calendar data for this resource and the new one
+            result = MultiStatusResponse(xml_responses)
+        else:
+            result = Response(responsecode.NO_CONTENT)
+            result.headers.addRawHeader("Split-Component-URL", other.url())
+
+        returnValue(result)
+
+
+    @requiresPermissions(davxml.WriteContent())
+    @inlineCallbacks
     def POST_handler_attachment(self, request, action):
         """
         Handle a managed attachments request on the calendar object resource.
@@ -2929,6 +3057,9 @@
         @return: an HTTP response
         """
 
+        if not config.EnableManagedAttachments:
+            returnValue(StatusResponse(responsecode.FORBIDDEN, "Managed Attachments not supported."))
+
         # Resource must exist to allow attachment operations
         if not self.exists():
             raise HTTPError(NOT_FOUND)
@@ -3371,6 +3502,8 @@
         if self.isShareeResource():
             log.debug("Removing shared resource %s" % (self,))
             yield self.removeShareeResource(request)
+            # Re-initialize to get stuff setup again now we have no object
+            self._initializeWithObject(None, self._newStoreParent)
             returnValue(NO_CONTENT)
         elif self._newStoreObject.isGroupForSharedAddressBook():
             abCollectionResource = (yield request.locateResource(parentForURL(request.uri)))
@@ -3673,7 +3806,6 @@
         # The newstore implementation supports this directly
         returnValue(
             (yield self._newStoreNotifications.resourceNamesSinceToken(revision))
-            + ([],)
         )
 
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_accounting.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_accounting.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_accounting.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_addressbookmultiget.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_addressbookmultiget.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_addressbookmultiget.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_addressbookquery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_addressbookquery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_addressbookquery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_cache.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_cache.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_cache.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_caldavxml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_caldavxml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_caldavxml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_calendarquery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_calendarquery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_calendarquery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
 from twistedcaldav import caldavxml
 from twistedcaldav import ical
 
-from twistedcaldav.query import calendarqueryfilter
 from twistedcaldav.config import config
 from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
 from twisted.internet.defer import inlineCallbacks, returnValue
@@ -36,6 +35,7 @@
 from twistedcaldav.ical import Component
 from txdav.caldav.icalendarstore import ComponentUpdateState
 from twistedcaldav.directory.directory import DirectoryService
+from txdav.caldav.datastore.query.filter import TimeRange
 
 
 @inlineCallbacks
@@ -167,7 +167,7 @@
                             cal = property.calendar()
                             instances = cal.expandTimeRanges(query_timerange.end)
                             vevents = [x for x in cal.subcomponents() if x.name() == "VEVENT"]
-                            if not calendarqueryfilter.TimeRange(query_timerange).matchinstance(vevents[0], instances):
+                            if not TimeRange(query_timerange).matchinstance(vevents[0], instances):
                                 self.fail("REPORT property %r returned calendar %s outside of request time range %r"
                                           % (property, property.calendar, query_timerange))
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_collectioncontents.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_collectioncontents.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_collectioncontents.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_config.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_config.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_config.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_customxml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_customxml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_customxml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_database.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_database.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_database.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_dateops.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_dateops.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_dateops.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_extensions.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_extensions.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_extensions.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_freebusyquery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_freebusyquery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_freebusyquery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_icalendar.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_icalendar.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_icalendar.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_kerberos.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_kerberos.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_kerberos.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_link.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_link.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_link.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_localization.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_localization.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_localization.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_memcachepool.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_memcachepool.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_memcachepool.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_memcacheprops.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_memcacheprops.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_memcacheprops.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Computer, Inc. All rights reserved.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_mkcalendar.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_mkcalendar.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_mkcalendar.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_multiget.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_multiget.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_multiget.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,4 +1,4 @@
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_options.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_options.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_options.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_props.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_props.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_props.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_sharing.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_sharing.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
 from twistedcaldav.test.test_cache import StubResponseCacheResource
 from twistedcaldav.test.util import norequest, StoreTestCase, SimpleStoreRequest
 
+from txdav.caldav.datastore.test.util import buildDirectory
 from txdav.common.datastore.sql_tables import _BIND_MODE_DIRECT
 from txdav.xml import element as davxml
 from txdav.xml.parser import WebDAVDocument
@@ -738,6 +739,8 @@
         home is at /.  Return the name of the newly shared calendar in the
         sharee's home.
         """
+
+        self._sqlCalendarStore._directoryService = buildDirectory(homes=("wiki-testing",))
         wcreate = self._sqlCalendarStore.newTransaction("create wiki")
         yield wcreate.calendarHomeWithUID("wiki-testing", create=True)
         yield wcreate.commit()

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_sql.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2007-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_stdconfig.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_stdconfig.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_timezones.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_timezones.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_timezones.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_timezonestdservice.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_timezonestdservice.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_timezonestdservice.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_upgrade.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_upgrade.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_wrapping.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_wrapping.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_wrapping.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_xml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_xml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_xml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -17,12 +17,15 @@
 import os
 
 from twisted.trial.unittest import SkipTest
+
 from twistedcaldav.ical import Component
-from twistedcaldav.query import calendarqueryfilter
 import twistedcaldav.test.util
 from twistedcaldav.caldavxml import ComponentFilter, PropertyFilter, TextMatch, \
     Filter, TimeRange
 
+from txdav.caldav.datastore.query.filter import Filter as storeFilter
+from txdav.caldav.datastore.query.filter import ComponentFilter as storeComponentFilter
+
 class XML (twistedcaldav.test.util.TestCase):
     """
     XML tests
@@ -46,7 +49,7 @@
             else:
                 no = ""
 
-            if has != calendarqueryfilter.ComponentFilter(
+            if has != storeComponentFilter(
                 ComponentFilter(
                     ComponentFilter(
                         name=component_name
@@ -70,7 +73,7 @@
             else:
                 no = ""
 
-            if has != calendarqueryfilter.ComponentFilter(
+            if has != storeComponentFilter(
                 ComponentFilter(
                     ComponentFilter(
                         PropertyFilter(
@@ -106,7 +109,7 @@
             else:
                 no = ""
 
-            if has != calendarqueryfilter.ComponentFilter(
+            if has != storeComponentFilter(
                 ComponentFilter(
                     ComponentFilter(
                         PropertyFilter(
@@ -148,7 +151,7 @@
             else:
                 no = ""
 
-            if has != calendarqueryfilter.Filter(
+            if has != storeFilter(
                 Filter(
                     ComponentFilter(
                         ComponentFilter(

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_xmlutil.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_xmlutil.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/test_xmlutil.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/test/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezones.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezones.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezones.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezoneservice.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezoneservice.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezoneservice.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezonestdservice.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezonestdservice.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezonestdservice.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezonexml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezonexml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/timezonexml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/upgrade.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/upgrade.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_upgrade -*-
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2007-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/vcard.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/vcard.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/vcard.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/xmlutil.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/xmlutil.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/twistedcaldav/xmlutil.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/dbapiclient.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/dbapiclient.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/dbapiclient.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/file.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/subpostgres.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/subpostgres.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/subpostgres.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.base.datastore.test.test_subpostgres -*-
 # #
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -228,7 +228,7 @@
                 # in /tmp and based on a hash of the data store directory
                 digest = md5(dataStoreDirectory.path).hexdigest()
                 socketDir = "/tmp/ccs_postgres_" + digest
-                
+
             self.socketDir = CachingFilePath(socketDir)
             self.host = self.socketDir.path
             self.port = None

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/test/test_subpostgres.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/test/test_subpostgres.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/test/test_subpostgres.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/datastore/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.caldav.datastore.test.test_file -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -98,6 +98,12 @@
         return "objectWithResourceID:%s:%s" % (homeResourceID, resourceID)
 
 
+    # Home child objects by external id
+
+    def keyForObjectWithExternalID(self, homeResourceID, externalID):
+        return "objectWithExternalID:%s:%s" % (homeResourceID, externalID)
+
+
     # Home metadata (Created/Modified)
 
     def keyForHomeMetaData(self, homeResourceID):

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/appledouble_xattr.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/appledouble_xattr.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/appledouble_xattr.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.base.propertystore.test.test_appledouble -*- ##
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/base.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/base.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/base.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/none.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/none.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/none.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.base.propertystore.test.test_none,txdav.caldav.datastore,txdav.carddav.datastore -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/sql.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.base.propertystore.test.test_sql -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/base.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/base.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/base.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_appledouble.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_appledouble.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_appledouble.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_base.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_base.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_base.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_none.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_none.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_none.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_sql.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_xattr.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_xattr.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/test/test_xattr.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/xattr.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/xattr.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/base/propertystore/xattr.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.base.propertystore.test.test_xattr -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/file.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.caldav.datastore.test.test_file -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/index_file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/index_file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/index_file.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_index -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
 # limitations under the License.
 ##
 
+
 """
 CalDAV Index.
 
@@ -43,12 +44,14 @@
 
 from twext.python.log import Logger
 
+from txdav.caldav.datastore.query.builder import buildExpression
+from txdav.caldav.datastore.query.filter import Filter
+from txdav.common.datastore.query.filegenerator import sqllitegenerator
 from txdav.common.icommondatastore import SyncTokenValidException, \
     ReservationError, IndexedSearchException
 
 from twistedcaldav.dateops import pyCalendarTodatetime
 from twistedcaldav.ical import Component
-from twistedcaldav.query import calendarquery, calendarqueryfilter
 from twistedcaldav.sql import AbstractSQLDatabase
 from twistedcaldav.sql import db_prefix
 from twistedcaldav.instance import InvalidOverriddenInstanceError
@@ -275,6 +278,7 @@
 
         changed = []
         deleted = []
+        invalid = []
         for name, wasdeleted in results:
             if name:
                 if wasdeleted == 'Y':
@@ -285,7 +289,7 @@
             else:
                 raise SyncTokenValidException
 
-        return changed, deleted,
+        return (changed, deleted, invalid)
 
 
     def lastRevision(self):
@@ -320,7 +324,7 @@
 
         # Make sure we have a proper Filter element and get the partial SQL
         # statement to use.
-        if isinstance(filter, calendarqueryfilter.Filter):
+        if isinstance(filter, Filter):
             if fbtype:
                 # Lookup the useruid - try the empty (default) one if needed
                 dbuseruid = self._db_value_for_sql(
@@ -330,7 +334,7 @@
             else:
                 dbuseruid = ""
 
-            qualifiers = calendarquery.sqlcalendarquery(filter, None, dbuseruid, fbtype)
+            qualifiers = sqlcalendarquery(filter, None, dbuseruid, fbtype)
             if qualifiers is not None:
                 # Determine how far we need to extend the current expansion of
                 # events. If we have an open-ended time-range we will expand one
@@ -437,6 +441,24 @@
 
 
 
+def sqlcalendarquery(filter, calendarid=None, userid=None, freebusy=False):
+    """
+    Convert the supplied calendar-query into a partial SQL statement.
+
+    @param filter: the L{Filter} for the calendar-query to convert.
+    @return: a C{tuple} of (C{str}, C{list}), where the C{str} is the partial SQL statement,
+            and the C{list} is the list of argument substitutions to use with the SQL API execute method.
+            Or return C{None} if it is not possible to create an SQL query to fully match the calendar-query.
+    """
+    try:
+        expression = buildExpression(filter, sqllitegenerator.FIELDS)
+        sql = sqllitegenerator(expression, calendarid, userid, freebusy)
+        return sql.generate()
+    except ValueError:
+        return None
+
+
+
 class CalendarIndex (AbstractCalendarIndex):
     """
     Calendar index - abstract class for indexer that indexes calendar objects in a collection.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/schedule.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/schedule.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/schedule.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.caldav.datastore.test.test_scheduling -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/addressmapping.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/addressmapping.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/addressmapping.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/delivery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/delivery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/scheduler.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/scheduler.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/test_delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/test_delivery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/test_delivery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/caldav/test/test_scheduler.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/cuaddress.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/cuaddress.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/cuaddress.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/delivery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/delivery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/freebusy.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/freebusy.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/freebusy.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -32,10 +32,11 @@
 from twistedcaldav.ical import Component, Property, iCalendarProductID
 from twistedcaldav.instance import InstanceList
 from twistedcaldav.memcacher import Memcacher
-from twistedcaldav.query import calendarqueryfilter
 
+from txdav.caldav.datastore.query.filter import Filter
 from txdav.caldav.icalendarstore import QueryMaxResources
-from txdav.common.icommondatastore import IndexedSearchException
+from txdav.common.icommondatastore import IndexedSearchException, \
+    InternalDataStoreError
 
 import uuid
 
@@ -92,7 +93,6 @@
 
 
 
- at inlineCallbacks
 def generateFreeBusyInfo(
     calresource,
     fbinfo,
@@ -107,6 +107,86 @@
     logItems=None,
 ):
     """
+    Get freebusy information for a calendar. Different behavior for internal vs external calendars.
+
+    See L{_internalGenerateFreeBusyInfo} for argument description.
+    """
+
+    # TODO: this method really should be moved to L{CalendarObject} so the internal/external pieces
+    # can be split across L{CalendarObject} and L{CalendarObjectExternal}
+    if calresource.external():
+        return _externalGenerateFreeBusyInfo(
+            calresource,
+            fbinfo,
+            timerange,
+            matchtotal,
+            excludeuid,
+            organizer,
+            organizerPrincipal,
+            same_calendar_user,
+            servertoserver,
+            event_details,
+            logItems
+        )
+    else:
+        return _internalGenerateFreeBusyInfo(
+            calresource,
+            fbinfo,
+            timerange,
+            matchtotal,
+            excludeuid,
+            organizer,
+            organizerPrincipal,
+            same_calendar_user,
+            servertoserver,
+            event_details,
+            logItems
+        )
+
+
+
+ at inlineCallbacks
+def _externalGenerateFreeBusyInfo(
+    calresource,
+    fbinfo,
+    timerange,
+    matchtotal,
+    excludeuid=None,
+    organizer=None,
+    organizerPrincipal=None,
+    same_calendar_user=False,
+    servertoserver=False,
+    event_details=None,
+    logItems=None,
+):
+    """
+    Generate a freebusy response for an external (cross-pod) calendar by making a cross-pod call. This will bypass
+    any type of smart caching on this pod in favor of using caching on the pod hosting the actual calendar data.
+
+    See L{_internalGenerateFreeBusyInfo} for argument description.
+    """
+    fbresults, matchtotal = yield calresource._txn.store().conduit.send_freebusy(calresource, timerange, matchtotal, excludeuid, organizer, organizerPrincipal, same_calendar_user, servertoserver, event_details)
+    for i in range(3):
+        fbinfo[i].extend([Period.parseText(p) for p in fbresults[i]])
+    returnValue(matchtotal)
+
+
+
+ at inlineCallbacks
+def _internalGenerateFreeBusyInfo(
+    calresource,
+    fbinfo,
+    timerange,
+    matchtotal,
+    excludeuid=None,
+    organizer=None,
+    organizerPrincipal=None,
+    same_calendar_user=False,
+    servertoserver=False,
+    event_details=None,
+    logItems=None,
+):
+    """
     Run a free busy report on the specified calendar collection
     accumulating the free busy info for later processing.
     @param calresource: the L{Calendar} for a calendar collection.
@@ -203,23 +283,23 @@
 
         # Create fake filter element to match time-range
         filter = caldavxml.Filter(
-                      caldavxml.ComponentFilter(
-                          caldavxml.ComponentFilter(
-                              cache_timerange if caching else timerange,
-                              name=("VEVENT", "VFREEBUSY", "VAVAILABILITY"),
-                          ),
-                          name="VCALENDAR",
-                       )
-                  )
-        filter = calendarqueryfilter.Filter(filter)
+            caldavxml.ComponentFilter(
+                caldavxml.ComponentFilter(
+                    cache_timerange if caching else timerange,
+                    name=("VEVENT", "VFREEBUSY", "VAVAILABILITY"),
+                ),
+                name="VCALENDAR",
+            )
+        )
+        filter = Filter(filter)
         tzinfo = filter.settimezone(tz)
 
         try:
-            resources = yield calresource._index.indexedSearch(filter, useruid=attendee_uid, fbtype=True)
+            resources = yield calresource.search(filter, useruid=attendee_uid, fbtype=True)
             if caching:
                 yield FBCacheEntry.makeCacheEntry(calresource, attendee_uid, cache_timerange, resources)
         except IndexedSearchException:
-            resources = yield calresource._index.bruteForceSearch()
+            raise InternalDataStoreError("Invalid indexedSearch query")
 
     else:
         # Log extended item

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/icaldiff.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/icaldiff.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/icaldiff.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/icalsplitter.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/icalsplitter.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/icalsplitter.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -83,17 +83,21 @@
         return len(str(ical)) > self.threshold
 
 
-    def whereSplit(self, ical):
+    def whereSplit(self, ical, break_point=None, allow_past_the_end=True):
         """
         Determine where a split is going to happen - i.e., the RECURRENCE-ID.
 
         @param ical: the iCalendar object to test
         @type ical: L{Component}
+        @param break_point: the date-time where the break should occur
+        @type break_point: L{DateTime}
 
         @return: recurrence-id of the split
         @rtype: L{DateTime}
         """
 
+        break_point = self.past if break_point is None else break_point
+
         # Find the instance RECURRENCE-ID where a split is going to happen
         now = self.now.duplicate()
         now.offsetDay(1)
@@ -101,14 +105,18 @@
         instances = sorted(instances.instances.values(), key=lambda x: x.start)
         rid = instances[0].rid
         for instance in instances:
-            rid = instance.rid
-            if instance.start >= self.past:
+            if instance.start >= break_point:
+                rid = instance.rid
+
+                # Do not allow a rid prior to the first instance
+                if break_point and rid == instances[0].rid:
+                    rid = None
                 break
         else:
-            # We can get here when splitting and event for overrides only in the past,
+            # We can get here when splitting an event for overrides only in the past,
             # which happens when splitting an Attendee's copy of an Organizer event
             # where the Organizer event has L{willSplit} == C{True}
-            rid = self.past
+            rid = break_point if allow_past_the_end else None
 
         return rid
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/delivery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/delivery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.caldav.datastore.scheduling.test.test_imip -*-
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/inbound.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/inbound.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/inbound.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/mailgateway.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/mailgateway.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/mailgateway.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -234,3 +234,6 @@
         yield txn.imipCreateToken(organizer, attendee, icaluid, token=token)
     yield txn.commit()
     os.remove(oldDB.dbpath)
+    journalPath = oldDB.dbpath + "-journal"
+    if os.path.exists(journalPath):
+        os.remove(journalPath)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/outbound.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/outbound.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/outbound.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/scheduler.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/scheduler.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/smtpsender.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/smtpsender.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/smtpsender.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_inbound.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_mailgateway.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_mailgateway.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_mailgateway.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/implicit.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/implicit.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/implicit.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/delivery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/delivery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/dkim.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/dkim.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/dkim.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/localservers.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/localservers.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/localservers.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -84,6 +84,12 @@
         self._thisServer = None
 
 
+    def addServer(self, server):
+        self._servers[server.id] = server
+        if server.thisServer:
+            self._thisServer = server
+
+
     def getServerById(self, id):
         return self._servers.get(id)
 
@@ -125,16 +131,22 @@
     Represents a server.
     """
 
-    def __init__(self):
-        self.id = None
-        self.uri = None
-        self.thisServer = False
+    def __init__(self, id=None, uri=None, sharedSecret=None, thisServer=False):
+        self.id = id
+        self.uri = uri
+        self.thisServer = thisServer
         self.ips = set()
         self.allowed_from_ips = set()
-        self.shared_secret = None
+        self.shared_secret = sharedSecret
         self.isImplicit = True
 
 
+    def details(self):
+        if not hasattr(self, "ssl"):
+            self._parseDetails()
+        return (self.ssl, self.host, self.port, self.path,)
+
+
     def check(self, ignoreIPLookupFailures=False):
         # Check whether this matches the current server
         parsed_uri = urlparse.urlparse(self.uri)
@@ -215,7 +227,28 @@
         return (SERVER_SECRET_HEADER, self.shared_secret,)
 
 
+    def _parseDetails(self):
+        # Extract scheme, host, port and path
+        if self.uri.startswith("http://"):
+            self.ssl = False
+            rest = self.uri[7:]
+        elif self.uri.startswith("https://"):
+            self.ssl = True
+            rest = self.uri[8:]
 
+        splits = rest.split("/", 1)
+        hostport = splits[0].split(":")
+        self.host = hostport[0]
+        if len(hostport) > 1:
+            self.port = int(hostport[1])
+        else:
+            self.port = {False: 80, True: 443}[self.ssl]
+        self.path = "/"
+        if len(splits) > 1:
+            self.path += splits[1]
+
+
+
 ELEMENT_SERVERS = "servers"
 ELEMENT_SERVER = "server"
 ELEMENT_ID = "id"

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/remoteservers.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/remoteservers.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/remoteservers.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/scheduler.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/scheduler.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_remoteservers.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_remoteservers.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_remoteservers.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_utils.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_utils.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/test/test_utils.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/utils.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/utils.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/utils.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2012-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/xml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/xml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/ischedule/xml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -259,14 +259,18 @@
 
 
     @classmethod
-    def fromCalendar(clazz, calendar):
+    def fromCalendar(clazz, calendar, format=None):
+        attrs = {}
+        if format is not None and format != "text/calendar":
+            attrs["content-type"] = format
+
         if isinstance(calendar, str):
             if not calendar:
                 raise ValueError("Missing calendar data")
             return clazz(PCDATAElement(calendar))
         elif isinstance(calendar, iComponent):
             assert calendar.name() == "VCALENDAR", "Not a calendar: %r" % (calendar,)
-            return clazz(PCDATAElement(calendar.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference)))
+            return clazz(PCDATAElement(calendar.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference, format=format)))
         else:
             raise ValueError("Not a calendar: %s" % (calendar,))
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/itip.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/itip.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/itip.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/processing.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/processing.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/processing.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/scheduler.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/scheduler.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_freebusy.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_freebusy.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_freebusy.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_icaldiff.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_icaldiff.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_icaldiff.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_icalsplitter.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -63,6 +63,11 @@
             getattr(self, attrname_12h).offsetHours(12)
             self.subs[attrname_12h] = getattr(self, attrname_12h)
 
+            attrname_1 = "now_fwd%s_1" % (i + 1,)
+            setattr(self, attrname_1, getattr(self, attrname).duplicate())
+            getattr(self, attrname_1).offsetSeconds(-1)
+            self.subs[attrname_1] = getattr(self, attrname_1)
+
         self.patch(config, "MaxAllowedInstances", 500)
 
 
@@ -1835,6 +1840,160 @@
 """,
             ),
             (
+                "1.8 - RRULE with COUNT",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back30)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ATTENDEE:mailto:user3 at example.com
+ATTENDEE:mailto:user4 at example.com
+ATTENDEE:mailto:user5 at example.com
+ATTENDEE:mailto:user6 at example.com
+ATTENDEE:mailto:user7 at example.com
+ATTENDEE:mailto:user8 at example.com
+ATTENDEE:mailto:user9 at example.com
+ATTENDEE:mailto:user10 at example.com
+ATTENDEE:mailto:user11 at example.com
+ATTENDEE:mailto:user12 at example.com
+ATTENDEE:mailto:user13 at example.com
+ATTENDEE:mailto:user14 at example.com
+ATTENDEE:mailto:user15 at example.com
+ATTENDEE:mailto:user16 at example.com
+ATTENDEE:mailto:user17 at example.com
+ATTENDEE:mailto:user18 at example.com
+ATTENDEE:mailto:user19 at example.com
+ATTENDEE:mailto:user20 at example.com
+ATTENDEE:mailto:user21 at example.com
+ATTENDEE:mailto:user22 at example.com
+ATTENDEE:mailto:user23 at example.com
+ATTENDEE:mailto:user24 at example.com
+ATTENDEE:mailto:user25 at example.com
+ORGANIZER:mailto:user1 at example.com
+RRULE:FREQ=DAILY;COUNT=40
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back14)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ATTENDEE:mailto:user3 at example.com
+ATTENDEE:mailto:user4 at example.com
+ATTENDEE:mailto:user5 at example.com
+ATTENDEE:mailto:user6 at example.com
+ATTENDEE:mailto:user7 at example.com
+ATTENDEE:mailto:user8 at example.com
+ATTENDEE:mailto:user9 at example.com
+ATTENDEE:mailto:user10 at example.com
+ATTENDEE:mailto:user11 at example.com
+ATTENDEE:mailto:user12 at example.com
+ATTENDEE:mailto:user13 at example.com
+ATTENDEE:mailto:user14 at example.com
+ATTENDEE:mailto:user15 at example.com
+ATTENDEE:mailto:user16 at example.com
+ATTENDEE:mailto:user17 at example.com
+ATTENDEE:mailto:user18 at example.com
+ATTENDEE:mailto:user19 at example.com
+ATTENDEE:mailto:user20 at example.com
+ATTENDEE:mailto:user21 at example.com
+ATTENDEE:mailto:user22 at example.com
+ATTENDEE:mailto:user23 at example.com
+ATTENDEE:mailto:user24 at example.com
+ATTENDEE:mailto:user25 at example.com
+ORGANIZER:mailto:user1 at example.com
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;COUNT=24
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:%(relID)s
+DTSTART:%(now_back30)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ATTENDEE:mailto:user3 at example.com
+ATTENDEE:mailto:user4 at example.com
+ATTENDEE:mailto:user5 at example.com
+ATTENDEE:mailto:user6 at example.com
+ATTENDEE:mailto:user7 at example.com
+ATTENDEE:mailto:user8 at example.com
+ATTENDEE:mailto:user9 at example.com
+ATTENDEE:mailto:user10 at example.com
+ATTENDEE:mailto:user11 at example.com
+ATTENDEE:mailto:user12 at example.com
+ATTENDEE:mailto:user13 at example.com
+ATTENDEE:mailto:user14 at example.com
+ATTENDEE:mailto:user15 at example.com
+ATTENDEE:mailto:user16 at example.com
+ATTENDEE:mailto:user17 at example.com
+ATTENDEE:mailto:user18 at example.com
+ATTENDEE:mailto:user19 at example.com
+ATTENDEE:mailto:user20 at example.com
+ATTENDEE:mailto:user21 at example.com
+ATTENDEE:mailto:user22 at example.com
+ATTENDEE:mailto:user23 at example.com
+ATTENDEE:mailto:user24 at example.com
+ATTENDEE:mailto:user25 at example.com
+ORGANIZER:mailto:user1 at example.com
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;UNTIL=%(now_back14_1)s
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+END:VEVENT
+END:VCALENDAR
+""",
+            ),
+            (
                 "2.1 - Overrides only - one future, one past",
                 """BEGIN:VCALENDAR
 VERSION:2.0
@@ -2018,3 +2177,188 @@
             # Make sure new items won't split again
             self.assertFalse(splitter.willSplit(icalNew), "Failed future will split: %s" % (title,))
             self.assertFalse(splitter.willSplit(icalOld), "Failed past will split: %s" % (title,))
+
+
+    def test_future_split(self):
+
+        data = (
+            (
+                "1.1 - RRULE with override",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ATTENDEE:mailto:user3 at example.com
+ATTENDEE:mailto:user4 at example.com
+ATTENDEE:mailto:user5 at example.com
+ATTENDEE:mailto:user6 at example.com
+ATTENDEE:mailto:user7 at example.com
+ATTENDEE:mailto:user8 at example.com
+ATTENDEE:mailto:user9 at example.com
+ATTENDEE:mailto:user10 at example.com
+ATTENDEE:mailto:user11 at example.com
+ATTENDEE:mailto:user12 at example.com
+ATTENDEE:mailto:user13 at example.com
+ATTENDEE:mailto:user14 at example.com
+ATTENDEE:mailto:user15 at example.com
+ATTENDEE:mailto:user16 at example.com
+ATTENDEE:mailto:user17 at example.com
+ATTENDEE:mailto:user18 at example.com
+ATTENDEE:mailto:user19 at example.com
+ATTENDEE:mailto:user20 at example.com
+ATTENDEE:mailto:user21 at example.com
+ATTENDEE:mailto:user22 at example.com
+ATTENDEE:mailto:user23 at example.com
+ATTENDEE:mailto:user24 at example.com
+ATTENDEE:mailto:user25 at example.com
+ORGANIZER:mailto:user1 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd11)s
+DTSTART:%(now_fwd11)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_fwd11)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ATTENDEE:mailto:user3 at example.com
+ATTENDEE:mailto:user4 at example.com
+ATTENDEE:mailto:user5 at example.com
+ATTENDEE:mailto:user6 at example.com
+ATTENDEE:mailto:user7 at example.com
+ATTENDEE:mailto:user8 at example.com
+ATTENDEE:mailto:user9 at example.com
+ATTENDEE:mailto:user10 at example.com
+ATTENDEE:mailto:user11 at example.com
+ATTENDEE:mailto:user12 at example.com
+ATTENDEE:mailto:user13 at example.com
+ATTENDEE:mailto:user14 at example.com
+ATTENDEE:mailto:user15 at example.com
+ATTENDEE:mailto:user16 at example.com
+ATTENDEE:mailto:user17 at example.com
+ATTENDEE:mailto:user18 at example.com
+ATTENDEE:mailto:user19 at example.com
+ATTENDEE:mailto:user20 at example.com
+ATTENDEE:mailto:user21 at example.com
+ATTENDEE:mailto:user22 at example.com
+ATTENDEE:mailto:user23 at example.com
+ATTENDEE:mailto:user24 at example.com
+ATTENDEE:mailto:user25 at example.com
+ORGANIZER:mailto:user1 at example.com
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd11)s
+DTSTART:%(now_fwd11)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:%(relID)s
+DTSTART:%(now)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ATTENDEE:mailto:user3 at example.com
+ATTENDEE:mailto:user4 at example.com
+ATTENDEE:mailto:user5 at example.com
+ATTENDEE:mailto:user6 at example.com
+ATTENDEE:mailto:user7 at example.com
+ATTENDEE:mailto:user8 at example.com
+ATTENDEE:mailto:user9 at example.com
+ATTENDEE:mailto:user10 at example.com
+ATTENDEE:mailto:user11 at example.com
+ATTENDEE:mailto:user12 at example.com
+ATTENDEE:mailto:user13 at example.com
+ATTENDEE:mailto:user14 at example.com
+ATTENDEE:mailto:user15 at example.com
+ATTENDEE:mailto:user16 at example.com
+ATTENDEE:mailto:user17 at example.com
+ATTENDEE:mailto:user18 at example.com
+ATTENDEE:mailto:user19 at example.com
+ATTENDEE:mailto:user20 at example.com
+ATTENDEE:mailto:user21 at example.com
+ATTENDEE:mailto:user22 at example.com
+ATTENDEE:mailto:user23 at example.com
+ATTENDEE:mailto:user24 at example.com
+ATTENDEE:mailto:user25 at example.com
+ORGANIZER:mailto:user1 at example.com
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;UNTIL=%(now_fwd11_1)s
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE:mailto:user2 at example.com
+ORGANIZER:mailto:user1 at example.com
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+END:VEVENT
+END:VCALENDAR
+""",
+            ),
+        )
+
+        for title, calendar, split_future, split_past in data:
+            ical = Component.fromString(calendar % self.subs)
+            splitter = iCalSplitter(1024, 14)
+            icalOld, icalNew = splitter.split(ical, rid=DateTime.parseText("%(now_fwd11)s" % self.subs))
+            relsubs = dict(self.subs)
+            relsubs["relID"] = icalOld.resourceUID()
+            self.assertEqual(str(icalNew).replace("\r\n ", ""), split_future.replace("\n", "\r\n") % relsubs, "Failed future: %s" % (title,))
+            self.assertEqual(str(icalOld).replace("\r\n ", ""), split_past.replace("\n", "\r\n") % relsubs, "Failed past: %s" % (title,))
+
+            # Make sure new items won't split again
+            self.assertFalse(splitter.willSplit(icalNew), "Failed future will split: %s" % (title,))
+            self.assertFalse(splitter.willSplit(icalOld), "Failed past will split: %s" % (title,))
+
+            ical = Component.fromString(calendar % self.subs)
+            splitter = iCalSplitter(1024, 14)
+            icalOld, icalNew = splitter.split(ical, rid=splitter.whereSplit(ical, break_point=DateTime.parseText("%(now_fwd10_12h)s" % self.subs)))
+            relsubs = dict(self.subs)
+            relsubs["relID"] = icalOld.resourceUID()
+            self.assertEqual(str(icalNew).replace("\r\n ", ""), split_future.replace("\n", "\r\n") % relsubs, "Failed future: %s" % (title,))
+            self.assertEqual(str(icalOld).replace("\r\n ", ""), split_past.replace("\n", "\r\n") % relsubs, "Failed past: %s" % (title,))
+
+            # Make sure new items won't split again
+            self.assertFalse(splitter.willSplit(icalNew), "Failed future will split: %s" % (title,))
+            self.assertFalse(splitter.willSplit(icalOld), "Failed past will split: %s" % (title,))

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_implicit.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_implicit.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_implicit.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_itip.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_itip.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_itip.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_pocessing.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_pocessing.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_pocessing.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_utils.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_utils.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/test/test_utils.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/utils.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/utils.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/scheduling/utils.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/sql.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.caldav.datastore.test.test_sql -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -46,6 +46,7 @@
 
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twisted.python import hashlib
+from twisted.python.failure import Failure
 
 from twistedcaldav import caldavxml, customxml, ical
 from twistedcaldav.config import config
@@ -57,6 +58,9 @@
 from twistedcaldav.memcacher import Memcacher
 
 from txdav.base.propertystore.base import PropertyName
+from txdav.caldav.datastore.query.builder import buildExpression
+from txdav.caldav.datastore.query.filter import Filter
+from txdav.caldav.datastore.query.generator import CalDAVSQLQueryGenerator
 from txdav.caldav.datastore.scheduling.icalsplitter import iCalSplitter
 from txdav.caldav.datastore.scheduling.implicit import ImplicitScheduler
 from txdav.caldav.datastore.util import AttachmentRetrievalTransport, \
@@ -72,12 +76,11 @@
     AttendeeAllowedError, InvalidPerUserDataMerge, ComponentUpdateState, \
     ValidOrganizerError, ShareeAllowedError, ComponentRemoveState, \
     InvalidDefaultCalendar, \
-    InvalidAttachmentOperation, DuplicatePrivateCommentsError
+    InvalidAttachmentOperation, DuplicatePrivateCommentsError, \
+    TimeRangeUpperLimit, TimeRangeLowerLimit, InvalidSplit
 from txdav.caldav.icalendarstore import QuotaExceeded
 from txdav.common.datastore.sql import CommonHome, CommonHomeChild, \
     CommonObjectResource, ECALENDARTYPE
-from txdav.common.datastore.sql_legacy import PostgresLegacyIndexEmulator, \
-    PostgresLegacyInboxIndexEmulator
 from txdav.common.datastore.sql_tables import _ATTACHMENTS_MODE_NONE, \
     _ATTACHMENTS_MODE_WRITE, schema, _BIND_MODE_OWN, \
     _ATTACHMENTS_MODE_READ, _TRANSP_OPAQUE, _TRANSP_TRANSPARENT
@@ -87,7 +90,8 @@
     InvalidObjectResourceError, ObjectResourceNameAlreadyExistsError, \
     ObjectResourceNameNotAllowedError, TooManyObjectResourcesError, \
     InvalidUIDError, UIDExistsError, UIDExistsElsewhereError, \
-    InvalidResourceMove, InvalidComponentForStoreError
+    InvalidResourceMove, InvalidComponentForStoreError, \
+    NoSuchObjectResourceError
 from txdav.xml import element
 
 from txdav.idav import ChangeCategory
@@ -363,7 +367,7 @@
     @inlineCallbacks
     def calendarObjectWithID(self, txn, rid):
         """
-        Return all child object resources with the specified UID. Only "owned" resources are returned,
+        Return all child object resources with the specified resource id. Only "owned" resources are returned,
         no shared resources.
 
         @param txn: transaction to use
@@ -375,7 +379,7 @@
         @rtype: L{CalendarObject} or C{None}
         """
 
-        # First find the resource-ids of the (home, parent, object) for each object matching the UID.
+        # First find the resource-ids of the (home, parent, object) for each object matching the resource id.
         obj = CalendarHome._objectSchema
         bind = CalendarHome._bindSchema
         rows = (yield Select(
@@ -433,12 +437,6 @@
         "VPOLL": "_default_polls",
     }
 
-    def __init__(self, transaction, ownerUID):
-
-        self._childClass = Calendar
-        super(CalendarHome, self).__init__(transaction, ownerUID)
-
-
     @classmethod
     def metadataColumns(cls):
         """
@@ -957,6 +955,12 @@
     _objectSchema = schema.CALENDAR_OBJECT
     _timeRangeSchema = schema.TIME_RANGE
 
+    # Mapping of iCalendar property name to DB column name
+    _queryFields = {
+        "UID": _objectSchema.UID,
+        "TYPE": _objectSchema.ICALENDAR_TYPE,
+    }
+
     _supportedComponents = None
 
     def __init__(self, *args, **kw):
@@ -964,10 +968,6 @@
         Initialize a calendar pointing at a record in a database.
         """
         super(Calendar, self).__init__(*args, **kw)
-        if self.isInbox():
-            self._index = PostgresLegacyInboxIndexEmulator(self)
-        else:
-            self._index = PostgresLegacyIndexEmulator(self)
         self._transp = _TRANSP_OPAQUE
 
 
@@ -1085,6 +1085,45 @@
         self.viewerHome().removedCalendarResource(child.uid())
 
 
+    @inlineCallbacks
+    def moveObjectResourceHere(self, name, component):
+        """
+        Create a new child in this collection as part of a move operation. This needs to be split out because
+        behavior differs for sub-classes and cross-pod operations.
+
+        @param name: new name to use in new parent
+        @type name: C{str} or C{None} for existing name
+        @param component: data for new resource
+        @type component: L{Component}
+        """
+
+        # Cross-pod calls come in with component as str or unicode
+        if isinstance(component, str) or isinstance(component, unicode):
+            try:
+                component = self._objectResourceClass._componentClass.fromString(component)
+            except InvalidICalendarDataError as e:
+                raise InvalidComponentForStoreError(str(e))
+
+        yield self._createCalendarObjectWithNameInternal(name, component, internal_state=ComponentUpdateState.RAW)
+
+
+    @inlineCallbacks
+    def moveObjectResourceAway(self, rid, child=None):
+        """
+        Remove the child as the result of a move operation. This needs to be split out because
+        behavior differs for sub-classes and cross-pod operations.
+
+        @param rid: the child resource-id to move
+        @type rid: C{int}
+        @param child: the child resource to move - might be C{None} for cross-pod
+        @type child: L{CommonObjectResource}
+        """
+
+        if child is None:
+            child = yield self.objectResourceWithID(rid)
+        yield child._removeInternal(internal_state=ComponentRemoveState.INTERNAL)
+
+
     def calendarObjectsInTimeRange(self, start, end, timeZone):
         raise NotImplementedError()
 
@@ -1302,6 +1341,37 @@
         yield self.setDefaultAlarm("empty", False, False)
 
 
+    def getInviteCopyProperties(self):
+        """
+        Get a dictionary of property name/values (as strings) for properties that are shadowable and
+        need to be copied to a sharee's collection when an external (cross-pod) share is created.
+        Sub-classes should override to expose the properties they care about.
+        """
+        props = {}
+        for elem in (element.DisplayName, caldavxml.CalendarDescription, caldavxml.CalendarTimeZone, customxml.CalendarColor,):
+            if PropertyName.fromElement(elem) in self.properties():
+                props[elem.sname()] = str(self.properties()[PropertyName.fromElement(elem)])
+        return props
+
+
+    def setInviteCopyProperties(self, props):
+        """
+        Copy a set of shadowable properties (as name/value strings) onto this shared resource when
+        a cross-pod invite is processed. Sub-classes should override to expose the properties they
+        care about.
+        """
+        # Initialize these for all shares
+        for elem in (caldavxml.CalendarDescription, caldavxml.CalendarTimeZone,):
+            if PropertyName.fromElement(elem) not in self.properties() and elem.sname() in props:
+                self.properties()[PropertyName.fromElement(elem)] = elem.fromString(props[elem.sname()])
+
+        # Only initialize these for direct shares
+        if self.direct():
+            for elem in (element.DisplayName, customxml.CalendarColor,):
+                if PropertyName.fromElement(elem) not in self.properties() and elem.sname() in props:
+                    self.properties()[PropertyName.fromElement(elem)] = elem.fromString(props[elem.sname()])
+
+
     # FIXME: this is DAV-ish.  Data store calendar objects don't have
     # mime types.  -wsv
     def contentType(self):
@@ -1312,6 +1382,196 @@
 
 
     @inlineCallbacks
+    def search(self, filter, useruid=None, fbtype=False):
+        """
+        Finds resources matching the given qualifiers.
+        @param filter: the L{Filter} for the calendar-query to execute.
+        @return: an iterable of tuples for each resource matching the
+            given C{qualifiers}. The tuples are C{(name, uid)}, where
+            C{name} is the resource name, C{uid} is the resource UID.
+        """
+
+        # We might be passed an L{Filter} or a serialization of one
+        if isinstance(filter, dict):
+            try:
+                filter = Filter.deserialize(filter)
+            except Exception:
+                filter = None
+
+        # Make sure we have a proper Filter element and get the partial SQL statement to use.
+        sql_stmt = self._sqlquery(filter, useruid, fbtype)
+
+        # No result means it is too complex for us
+        if sql_stmt is None:
+            raise IndexedSearchException()
+        sql_stmt, args, usedtimerange = sql_stmt
+
+        # Check for time-range re-expand
+        if usedtimerange is not None:
+
+            today = DateTime.getToday()
+
+            # Determine how far we need to extend the current expansion of
+            # events. If we have an open-ended time-range we will expand
+            # one year past the start. That should catch bounded
+            # recurrences - unbounded will have been indexed with an
+            # "infinite" value always included.
+            maxDate, isStartDate = filter.getmaxtimerange()
+            if maxDate:
+                maxDate = maxDate.duplicate()
+                maxDate.offsetDay(1)
+                maxDate.setDateOnly(True)
+                upperLimit = today + Duration(days=config.FreeBusyIndexExpandMaxDays)
+                if maxDate > upperLimit:
+                    raise TimeRangeUpperLimit(upperLimit)
+                if isStartDate:
+                    maxDate += Duration(days=365)
+
+            # Determine if the start date is too early for the restricted range we
+            # are applying. If it is today or later we don't need to worry about truncation
+            # in the past.
+            minDate, _ignore_isEndDate = filter.getmintimerange()
+            if minDate >= today:
+                minDate = None
+            if minDate is not None and config.FreeBusyIndexLowerLimitDays:
+                truncateLowerLimit = today - Duration(days=config.FreeBusyIndexLowerLimitDays)
+                if minDate < truncateLowerLimit:
+                    raise TimeRangeLowerLimit(truncateLowerLimit)
+
+            if maxDate is not None or minDate is not None:
+                yield self.testAndUpdateIndex(minDate, maxDate)
+
+        rowiter = yield sql_stmt.on(self._txn, **args)
+
+        # Check result for missing resources
+        results = []
+        for row in rowiter:
+            if fbtype:
+                row = list(row)
+                row[4] = 'Y' if row[4] else 'N'
+                row[7] = indexfbtype_to_icalfbtype[row[7]]
+                if row[9] is not None:
+                    row[8] = row[9]
+                row[8] = 'T' if row[8] else 'F'
+                del row[9]
+            results.append(row)
+
+        returnValue(results)
+
+
+    def _sqlquery(self, filter, useruid, fbtype):
+        """
+        Convert the supplied addressbook-query into a partial SQL statement.
+
+        @param filter: the L{Filter} for the addressbook-query to convert.
+        @return: a C{tuple} of (C{str}, C{list}), where the C{str} is the partial SQL statement,
+                and the C{list} is the list of argument substitutions to use with the SQL API execute method.
+                Or return C{None} if it is not possible to create an SQL query to fully match the addressbook-query.
+        """
+
+        if not isinstance(filter, Filter):
+            return None
+
+        try:
+            expression = buildExpression(filter, self._queryFields)
+            sql = CalDAVSQLQueryGenerator(expression, self, self.id(), useruid, fbtype)
+            return sql.generate()
+        except ValueError:
+            return None
+
+
+    @classproperty
+    def _notExpandedWithinQuery(cls): #@NoSelf
+        """
+        Query to find resources that need to be re-expanded
+        """
+        co = schema.CALENDAR_OBJECT
+        return Select(
+            [co.RESOURCE_NAME],
+            From=co,
+            Where=((co.RECURRANCE_MIN > Parameter("minDate"))
+                .Or(co.RECURRANCE_MAX < Parameter("maxDate")))
+                .And(co.CALENDAR_RESOURCE_ID == Parameter("resourceID"))
+        )
+
+
+    @inlineCallbacks
+    def notExpandedWithin(self, minDate, maxDate):
+        """
+        Gives all resources which have not been expanded beyond a given date
+        in the database.  (Unused; see above L{postgresqlgenerator}.
+        """
+        returnValue([row[0] for row in (
+            yield self._notExpandedWithinQuery.on(
+                self._txn,
+                minDate=pyCalendarTodatetime(normalizeForIndex(minDate)) if minDate is not None else None,
+                maxDate=pyCalendarTodatetime(normalizeForIndex(maxDate)),
+                resourceID=self._resourceID))]
+        )
+
+
+    @inlineCallbacks
+    def reExpandResource(self, name, expand_start, expand_end):
+        """
+        Given a resource name, remove it from the database and re-add it
+        with a longer expansion.
+        """
+        obj = yield self.calendarObjectWithName(name)
+
+        # Use a new transaction to do this update quickly without locking the row for too long. However, the original
+        # transaction may have the row locked, so use wait=False and if that fails, fall back to using the original txn.
+
+        newTxn = obj.transaction().store().newTransaction()
+        try:
+            yield obj.lock(wait=False, txn=newTxn)
+        except NoSuchObjectResourceError:
+            yield newTxn.commit()
+            returnValue(None)
+        except:
+            yield newTxn.abort()
+            newTxn = None
+
+        # Now do the re-expand using the appropriate transaction
+        try:
+            doExpand = False
+            if newTxn is None:
+                doExpand = True
+            else:
+                # We repeat this check because the resource may have been re-expanded by someone else
+                rmin, rmax = (yield obj.recurrenceMinMax(txn=newTxn))
+
+                # If the resource is not fully expanded, see if within the required range or not.
+                # Note that expand_start could be None if no lower limit is applied, but expand_end will
+                # never be None
+                if rmax is not None and rmax < expand_end:
+                    doExpand = True
+                if rmin is not None and expand_start is not None and rmin > expand_start:
+                    doExpand = True
+
+            if doExpand:
+                yield obj.updateDatabase(
+                    (yield obj.component()),
+                    expand_until=expand_end,
+                    reCreate=True,
+                    txn=newTxn,
+                )
+        finally:
+            if newTxn is not None:
+                yield newTxn.commit()
+
+
+    @inlineCallbacks
+    def testAndUpdateIndex(self, minDate, maxDate):
+        # Find out if the index is expanded far enough
+        names = yield self.notExpandedWithin(minDate, maxDate)
+
+        # Actually expand recurrence max
+        for name in names:
+            self.log.info("Search falls outside range of index for %s %s to %s" % (name, minDate, maxDate))
+            yield self.reExpandResource(name, minDate, maxDate)
+
+
+    @inlineCallbacks
     def splitCollectionByComponentTypes(self):
         """
         If the calendar contains iCalendar data with different component types, then split it into separate collections
@@ -1524,6 +1784,7 @@
     implements(ICalendarObject)
 
     _objectSchema = schema.CALENDAR_OBJECT
+    _componentClass = VComponent
 
     def __init__(self, calendar, name, uid, resourceID=None, options=None):
 
@@ -1542,36 +1803,20 @@
         self._cachedComponent = None
         self._cachedCommponentPerUser = {}
 
-    _allColumns = [
-        _objectSchema.RESOURCE_ID,
-        _objectSchema.RESOURCE_NAME,
-        _objectSchema.UID,
-        _objectSchema.MD5,
-        Len(_objectSchema.TEXT),
-        _objectSchema.ATTACHMENTS_MODE,
-        _objectSchema.DROPBOX_ID,
-        _objectSchema.ACCESS,
-        _objectSchema.SCHEDULE_OBJECT,
-        _objectSchema.SCHEDULE_TAG,
-        _objectSchema.SCHEDULE_ETAGS,
-        _objectSchema.PRIVATE_COMMENTS,
-        _objectSchema.CREATED,
-        _objectSchema.MODIFIED
-    ]
 
-
     @classmethod
     @inlineCallbacks
     def _createInternal(cls, parent, name, component, internal_state, options=None, split_details=None):
 
-        child = (yield cls.objectWithName(parent, name, None))
+        child = (yield cls.objectWithName(parent, name))
         if child:
             raise ObjectResourceNameAlreadyExistsError(name)
 
         if name.startswith("."):
             raise ObjectResourceNameNotAllowedError(name)
 
-        objectResource = cls(parent, name, None, None, options=options)
+        c = cls._externalClass if parent.external() else cls
+        objectResource = c(parent, name, None, None, options=options)
         yield objectResource._setComponentInternal(component, inserting=True, internal_state=internal_state, split_details=split_details)
         yield objectResource._loadPropertyStore(created=True)
 
@@ -1581,27 +1826,51 @@
         returnValue(objectResource)
 
 
-    def _initFromRow(self, row):
+    @classmethod
+    def _allColumns(cls): #@NoSelf
         """
-        Given a select result using the columns from L{_allColumns}, initialize
-        the calendar object resource state.
+        Full set of columns in the object table that need to be loaded to
+        initialize the object resource state.
         """
-        (self._resourceID,
-         self._name,
-         self._uid,
-         self._md5,
-         self._size,
-         self._attachment,
-         self._dropboxID,
-         self._access,
-         self._schedule_object,
-         self._schedule_tag,
-         self._schedule_etags,
-         self._private_comments,
-         self._created,
-         self._modified,) = tuple(row)
+        obj = cls._objectSchema
+        return [
+            obj.RESOURCE_ID,
+            obj.RESOURCE_NAME,
+            obj.UID,
+            obj.MD5,
+            Len(obj.TEXT),
+            obj.ATTACHMENTS_MODE,
+            obj.DROPBOX_ID,
+            obj.ACCESS,
+            obj.SCHEDULE_OBJECT,
+            obj.SCHEDULE_TAG,
+            obj.SCHEDULE_ETAGS,
+            obj.PRIVATE_COMMENTS,
+            obj.CREATED,
+            obj.MODIFIED
+        ]
 
 
+    @classmethod
+    def _rowAttributes(cls): #@NoSelf
+        return (
+            "_resourceID",
+            "_name",
+            "_uid",
+            "_md5",
+            "_size",
+            "_attachment",
+            "_dropboxID",
+            "_access",
+            "_schedule_object",
+            "_schedule_tag",
+            "_schedule_etags",
+            "_private_comments",
+            "_created",
+            "_modified",
+         )
+
+
     @property
     def _calendar(self):
         return self._parentCollection
@@ -2063,6 +2332,12 @@
                 internal_request=is_internal,
             ))
 
+            # Set an attribute on this object to indicate that it is valid to check for an event split. We need to do this here so that if a timeout
+            # occurs whilst doing implicit processing (most likely because the event is too big) we are able to subsequently detect that it is OK
+            # to split and then try that.
+            if internal_state not in (ComponentUpdateState.SPLIT_OWNER, ComponentUpdateState.SPLIT_ATTENDEE,) and scheduler.state == "organizer":
+                self.okToSplit = True
+
             if do_implicit_action and not is_internal:
 
                 # Cannot do implicit in sharee's shared calendar
@@ -2177,15 +2452,34 @@
                         raise UIDExistsElsewhereError("UID already exists in different calendar: %s." % (elsewhere.calendar().name(),))
 
 
+    @inlineCallbacks
     def setComponent(self, component, inserting=False, smart_merge=False):
         """
         Public api for storing a component. This will do full data validation checks on the specified component.
         Scheduling will be done automatically.
         """
 
-        return self._setComponentInternal(component, inserting, ComponentUpdateState.NORMAL, smart_merge)
+        # Cross-pod calls come in with component as str or unicode
+        if isinstance(component, str) or isinstance(component, unicode):
+            try:
+                component = self._componentClass.fromString(component)
+            except InvalidICalendarDataError as e:
+                raise InvalidComponentForStoreError(str(e))
+        try:
+            result = yield self._setComponentInternal(component, inserting, ComponentUpdateState.NORMAL, smart_merge)
+        except Exception:
+            ex = Failure()
 
+            # If the failure is due to a txn timeout and we have the special attribute indicating it is OK to
+            # attempt a split, then try splitting only when doing an update.
+            if self._txn.timedout and hasattr(self, "okToSplit") and not inserting:
+                yield self.timeoutSplit()
 
+            ex.raiseException()
+
+        returnValue(result)
+
+
     @inlineCallbacks
     def _setComponentInternal(self, component, inserting=False, internal_state=ComponentUpdateState.NORMAL, smart_merge=False, split_details=None):
         """
@@ -2734,9 +3028,10 @@
                 yield NamedLock.acquire(self._txn, "ImplicitUIDLock:%s" % (hashlib.md5(calendar.resourceUID()).hexdigest(),))
 
         # Need to also remove attachments
-        if self._dropboxID:
-            yield DropBoxAttachment.resourceRemoved(self._txn, self._resourceID, self._dropboxID)
-        yield ManagedAttachment.resourceRemoved(self._txn, self._resourceID)
+        if internal_state != ComponentRemoveState.INTERNAL:
+            if self._dropboxID:
+                yield DropBoxAttachment.resourceRemoved(self._txn, self._resourceID, self._dropboxID)
+            yield ManagedAttachment.resourceRemoved(self._txn, self._resourceID)
         yield super(CalendarObject, self).remove()
 
         # Do scheduling
@@ -3399,16 +3694,21 @@
 
 
     @inlineCallbacks
-    def checkSplit(self):
+    def checkSplit(self, txn=None):
         """
-        Determine if the calendar data needs to be split, and enqueue a split work item if needed.
+        Determine if the calendar data needs to be split, and enqueue a split work item if needed. Note we may
+        need to do this in some other transaction.
         """
 
         if config.Scheduling.Options.Splitting.Enabled:
             will = (yield self.willSplit())
             if will:
                 notBefore = datetime.datetime.utcnow() + datetime.timedelta(seconds=config.Scheduling.Options.Splitting.Delay)
-                work = (yield self._txn.enqueue(CalendarObject.CalendarObjectSplitterWork, resourceID=self._resourceID, notBefore=notBefore))
+                if txn is None:
+                    txn = self._txn
+                work = (yield txn.enqueue(CalendarObject.CalendarObjectSplitterWork, resourceID=self._resourceID, notBefore=notBefore))
+
+                # _workItems is used during unit testing only, to track the created work
                 if not hasattr(self, "_workItems"):
                     self._workItems = []
                 self._workItems.append(work)
@@ -3427,6 +3727,55 @@
 
 
     @inlineCallbacks
+    def timeoutSplit(self):
+        """
+        A txn timeout occurred. Check to see if it is possible to split this event and if so schedule that to occur
+        as the timeout might be the result of the resource being too large and doing a split here will allow a
+        subsequent operation to succeed since the split can reduce the size.
+        """
+
+        # Can only do if cached data exists
+        if self._cachedComponent:
+            txn = self.transaction().store().newTransaction("Timeout checkSplit")
+            yield self.checkSplit(txn=txn)
+            yield txn.commit()
+
+
+    @inlineCallbacks
+    def splitAt(self, rid):
+        """
+        User initiated split. We need to verify it is OK to do so first. We will allow any recurring item to
+        be split, but will not allow attendees to split invites.
+
+        @param rid: the date-time where the split should occur. This need not be a specific instance
+            date-time - this method will choose the next instance on or after this value.
+        @type rid: L{DateTime}
+        """
+
+        # Must be recurring
+        component = yield self.component()
+        if not component.isRecurring():
+            raise InvalidSplit()
+
+        # Cannot be attendee
+        ownerPrincipal = self.calendar().ownerHome().directoryRecord()
+        organizer = component.getOrganizer()
+        organizerPrincipal = self.directoryService().recordWithCalendarUserAddress(organizer) if organizer else None
+        if organizer is not None and organizerPrincipal.uid != ownerPrincipal.uid:
+            raise InvalidSplit()
+
+        # 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()
+
+        # Do split and return new resource
+        olderObject = yield self.split(rid=rid)
+        returnValue(olderObject)
+
+
+    @inlineCallbacks
     def split(self, onlyThis=False, rid=None, olderUID=None):
         """
         Split this and all matching UID calendar objects as per L{iCalSplitter}.
@@ -3469,8 +3818,9 @@
         # Now process this resource, but do implicit scheduling for attendees not hosted on this server.
         # We need to do this before processing attendee copies.
         calendar_old, calendar_new = splitter.split(calendar, rid=rid, olderUID=olderUID)
-        calendar_new.bumpiTIPInfo(oldcalendar=calendar, doSequence=True)
-        calendar_old.bumpiTIPInfo(oldcalendar=None, doSequence=True)
+        if calendar_new.getOrganizer() is not None:
+            calendar_new.bumpiTIPInfo(oldcalendar=calendar, doSequence=True)
+            calendar_old.bumpiTIPInfo(oldcalendar=None, doSequence=True)
 
         # If the split results in nothing either resource, then there is really nothing
         # to actually split
@@ -3479,7 +3829,7 @@
 
         # Store changed data
         yield self._setComponentInternal(calendar_new, internal_state=ComponentUpdateState.SPLIT_OWNER, split_details=(rid, olderUID, True,))
-        yield self.calendar()._createCalendarObjectWithNameInternal("%s.ics" % (olderUID,), calendar_old, ComponentUpdateState.SPLIT_OWNER, split_details=(rid, newerUID, False,))
+        olderObject = yield self.calendar()._createCalendarObjectWithNameInternal("%s.ics" % (olderUID,), calendar_old, ComponentUpdateState.SPLIT_OWNER, split_details=(rid, newerUID, False,))
 
         # Split each one - but not this resource
         for resource in resources:
@@ -3487,7 +3837,7 @@
                 continue
             yield resource.splitForAttendee(rid, olderUID)
 
-        returnValue(olderUID)
+        returnValue(olderObject)
 
 
     @inlineCallbacks
@@ -4419,4 +4769,10 @@
 
         returnValue(location)
 
+# Hook-up class relationships at the end after they have all been defined
+from txdav.caldav.datastore.sql_external import CalendarHomeExternal, CalendarExternal, CalendarObjectExternal
+CalendarHome._externalClass = CalendarHomeExternal
+CalendarHome._childClass = Calendar
+Calendar._externalClass = CalendarExternal
 Calendar._objectResourceClass = CalendarObject
+CalendarObject._externalClass = CalendarObjectExternal

Copied: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/sql_external.py (from rev 12321, CalendarServer/trunk/txdav/caldav/datastore/sql_external.py)
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/sql_external.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/sql_external.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -0,0 +1,217 @@
+# -*- test-case-name: txdav.caldav.datastore.test.test_sql -*-
+##
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+"""
+SQL backend for CalDAV storage when resources are external.
+"""
+
+from twisted.internet.defer import succeed, inlineCallbacks, returnValue
+
+from twext.python.log import Logger
+
+from txdav.caldav.datastore.sql import CalendarHome, Calendar, CalendarObject
+from txdav.caldav.icalendarstore import ComponentUpdateState, ComponentRemoveState
+from txdav.common.datastore.sql_external import CommonHomeExternal, CommonHomeChildExternal, \
+    CommonObjectResourceExternal
+
+log = Logger()
+
+class CalendarHomeExternal(CommonHomeExternal, CalendarHome):
+    """
+    Wrapper for a CalendarHome that is external and only supports a limited set of operations.
+    """
+
+    def __init__(self, transaction, ownerUID, resourceID):
+
+        CalendarHome.__init__(self, transaction, ownerUID)
+        CommonHomeExternal.__init__(self, transaction, ownerUID, resourceID)
+
+
+    def hasCalendarResourceUIDSomewhereElse(self, uid, ok_object, mode):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def getCalendarResourcesForUID(self, uid):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def calendarObjectWithDropboxID(self, dropboxID):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def getAllDropboxIDs(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def getAllAttachmentNames(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def getAllManagedIDs(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def createdHome(self):
+        """
+        No children - make this a no-op.
+        """
+        return succeed(None)
+
+
+    def splitCalendars(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def ensureDefaultCalendarsExist(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def setDefaultCalendar(self, calendar, componentType):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def defaultCalendar(self, componentType, create=True):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def isDefaultCalendar(self, calendar):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def getDefaultAlarm(self, vevent, timed):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def setDefaultAlarm(self, alarm, vevent, timed):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def getAvailability(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def setAvailability(self, availability):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+
+class CalendarExternal(CommonHomeChildExternal, Calendar):
+    """
+    SQL-based implementation of L{ICalendar}.
+    """
+    pass
+
+
+
+class CalendarObjectExternal(CommonObjectResourceExternal, CalendarObject):
+    """
+    SQL-based implementation of L{ICalendarObject}.
+    """
+
+    @classmethod
+    def _createInternal(cls, parent, name, component, internal_state, options=None, split_details=None):
+        raise AssertionError("CalendarObjectExternal: not supported")
+
+
+    def _setComponentInternal(self, component, inserting=False, internal_state=ComponentUpdateState.NORMAL, smart_merge=False, split_details=None):
+        raise AssertionError("CalendarObjectExternal: not supported")
+
+
+    def _removeInternal(self, internal_state=ComponentRemoveState.NORMAL):
+        raise AssertionError("CalendarObjectExternal: not supported")
+
+
+    @inlineCallbacks
+    def addAttachment(self, rids, content_type, filename, stream):
+        result = yield self._txn.store().conduit.send_add_attachment(self, rids, content_type, filename, stream)
+        managedID, location = result
+        returnValue((ManagedAttachmentExternal(str(managedID)), str(location),))
+
+
+    @inlineCallbacks
+    def updateAttachment(self, managed_id, content_type, filename, stream):
+        result = yield self._txn.store().conduit.send_update_attachment(self, managed_id, content_type, filename, stream)
+        managedID, location = result
+        returnValue((ManagedAttachmentExternal(str(managedID)), str(location),))
+
+
+    @inlineCallbacks
+    def removeAttachment(self, rids, managed_id):
+        yield self._txn.store().conduit.send_remove_attachment(self, rids, managed_id)
+        returnValue(None)
+
+
+
+class ManagedAttachmentExternal(object):
+    """
+    Fake managed attachment object returned from L{CalendarObjectExternal.addAttachment} and
+    L{CalendarObjectExternal.updateAttachment}.
+    """
+
+    def __init__(self, managedID):
+        self._managedID = managedID
+
+
+    def managedID(self):
+        return self._managedID
+
+
+CalendarExternal._objectResourceClass = CalendarObjectExternal

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.caldav.datastore.test -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/attachments/accounts.xml
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/attachments/accounts.xml	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/attachments/accounts.xml	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+Copyright (c) 2006-2014 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/common.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/common.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.caldav.datastore -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -416,12 +416,14 @@
         yield coll.removeNotificationObjectWithUID("1")
         st2 = yield coll.syncToken()
         rev2 = self.token2revision(st2)
-        changed, deleted = yield coll.resourceNamesSinceToken(rev)
+        changed, deleted, invalid = yield coll.resourceNamesSinceToken(rev)
         self.assertEquals(set(changed), set(["2.xml"]))
         self.assertEquals(set(deleted), set(["1.xml"]))
-        changed, deleted = yield coll.resourceNamesSinceToken(rev2)
+        self.assertEquals(len(invalid), 0)
+        changed, deleted, invalid = yield coll.resourceNamesSinceToken(rev2)
         self.assertEquals(set(changed), set([]))
         self.assertEquals(set(deleted), set([]))
+        self.assertEquals(len(invalid), 0)
 
 
     @inlineCallbacks
@@ -1602,7 +1604,7 @@
 
         home = yield self.homeUnderTest()
 
-        changed, deleted = yield home.resourceNamesSinceToken(
+        changed, deleted, invalid = yield home.resourceNamesSinceToken(
             self.token2revision(st), "infinity")
 
         self.assertEquals(set(changed), set(["calendar_1/",
@@ -1610,11 +1612,13 @@
                                              "calendar_1/2.ics",
                                              "other-calendar/"]))
         self.assertEquals(set(deleted), set(["calendar_1/2.ics"]))
+        self.assertEquals(invalid, [])
 
-        changed, deleted = yield home.resourceNamesSinceToken(
+        changed, deleted, invalid = yield home.resourceNamesSinceToken(
             self.token2revision(st2), "infinity")
         self.assertEquals(changed, [])
         self.assertEquals(deleted, [])
+        self.assertEquals(invalid, [])
 
 
     @inlineCallbacks
@@ -1634,12 +1638,14 @@
         yield obj1.remove()
         st2 = yield cal.syncToken()
         rev2 = self.token2revision(st2)
-        changed, deleted = yield cal.resourceNamesSinceToken(rev)
+        changed, deleted, invalid = yield cal.resourceNamesSinceToken(rev)
         self.assertEquals(set(changed), set(["new.ics"]))
         self.assertEquals(set(deleted), set(["2.ics"]))
-        changed, deleted = yield cal.resourceNamesSinceToken(rev2)
+        self.assertEquals(len(invalid), 0)
+        changed, deleted, invalid = yield cal.resourceNamesSinceToken(rev2)
         self.assertEquals(set(changed), set([]))
         self.assertEquals(set(deleted), set([]))
+        self.assertEquals(len(invalid), 0)
 
 
     @inlineCallbacks
@@ -1703,7 +1709,7 @@
         L{ICalendarStore.withEachCalendarHomeDo} executes its C{action}
         argument repeatedly with all homes that have been created.
         """
-        additionalUIDs = set('alpha-uid home2 home3 beta-uid'.split())
+        additionalUIDs = set('user01 home2 home3 uid1'.split())
         txn = self.transactionUnderTest()
         for name in additionalUIDs:
             yield txn.calendarHomeWithUID(name, create=True)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_attachments.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_attachments.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_attachments.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_file.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_implicit.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_implicit.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_implicit.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_index_file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_index_file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_index_file.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 from twisted.internet.task import deferLater
 
 from txdav.caldav.datastore.index_file import Index, MemcachedUIDReserver
+from txdav.caldav.datastore.query.filter import Filter
 from txdav.common.icommondatastore import ReservationError, \
     InternalDataStoreError
 
@@ -26,7 +27,6 @@
 from twistedcaldav.caldavxml import TimeRange
 from twistedcaldav.ical import Component, InvalidICalendarDataError
 from twistedcaldav.instance import InvalidOverriddenInstanceError
-from twistedcaldav.query import calendarqueryfilter
 from twistedcaldav.test.util import InMemoryMemcacheProtocol
 import twistedcaldav.test.util
 
@@ -480,7 +480,7 @@
                       name="VCALENDAR",
                    )
               )
-            filter = calendarqueryfilter.Filter(filter)
+            filter = Filter(filter)
 
             resources = yield self.db.indexedSearch(filter)
             index_results = set()
@@ -666,7 +666,7 @@
                       name="VCALENDAR",
                    )
               )
-            filter = calendarqueryfilter.Filter(filter)
+            filter = Filter(filter)
 
             resources = yield self.db.indexedSearch(filter, fbtype=True)
             index_results = set()
@@ -1073,7 +1073,7 @@
                       name="VCALENDAR",
                    )
               )
-            filter = calendarqueryfilter.Filter(filter)
+            filter = Filter(filter)
 
             for useruid, instances in peruserinstances:
                 resources = yield self.db.indexedSearch(filter, useruid=useruid, fbtype=True)
@@ -1142,12 +1142,12 @@
         self.db.deleteResource("data3.ics")
 
         tests = (
-            (0, (["data1.ics", "data2.ics", ], [],)),
-            (1, (["data2.ics", ], ["data3.ics", ],)),
-            (2, ([], ["data3.ics", ],)),
-            (3, ([], ["data3.ics", ],)),
-            (4, ([], [],)),
-            (5, ([], [],)),
+            (0, (["data1.ics", "data2.ics", ], [], [],)),
+            (1, (["data2.ics", ], ["data3.ics", ], [],)),
+            (2, ([], ["data3.ics", ], [],)),
+            (3, ([], ["data3.ics", ], [],)),
+            (4, ([], [], [],)),
+            (5, ([], [], [],)),
         )
 
         for revision, results in tests:

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_schedule.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_schedule.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_schedule.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,14 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-from txdav.caldav.datastore.scheduling.processing import ImplicitProcessor
-from txdav.caldav.datastore.scheduling.cuaddress import RemoteCalendarUser, \
-    LocalCalendarUser
-from txdav.caldav.datastore.scheduling.caldav.scheduler import CalDAVScheduler
-from txdav.caldav.datastore.scheduling.scheduler import ScheduleResponseQueue
-from txweb2 import responsecode
-from txdav.caldav.datastore.scheduling.itip import iTIPRequestStatus
-from twistedcaldav.instance import InvalidOverriddenInstanceError
 
 """
 Tests for txdav.caldav.datastore.postgres, mostly based on
@@ -32,14 +24,16 @@
 
 from twext.enterprise.dal.syntax import Select, Parameter, Insert, Delete, \
     Update
-from twistedcaldav.ical import Component as VComponent
+from twext.enterprise.ienterprise import AlreadyFinishedError
+
+from txweb2 import responsecode
 from txweb2.http_headers import MimeType
 from txweb2.stream import MemoryStream
 
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks, returnValue, DeferredList, \
     succeed
-from twisted.internet.task import deferLater
+from twisted.internet.task import deferLater, Clock
 from twisted.trial import unittest
 
 from twistedcaldav import caldavxml, ical
@@ -47,24 +41,33 @@
 from twistedcaldav.config import config
 from twistedcaldav.dateops import datetimeMktime
 from twistedcaldav.ical import Component, normalize_iCalStr, diff_iCalStrs
-from twistedcaldav.query import calendarqueryfilter
+from twistedcaldav.instance import InvalidOverriddenInstanceError
 
 from txdav.base.propertystore.base import PropertyName
+from txdav.caldav.datastore.query.filter import Filter
+from txdav.caldav.datastore.scheduling.caldav.scheduler import CalDAVScheduler
+from txdav.caldav.datastore.scheduling.cuaddress import RemoteCalendarUser, \
+    LocalCalendarUser
+from txdav.caldav.datastore.scheduling.implicit import ImplicitScheduler
+from txdav.caldav.datastore.scheduling.itip import iTIPRequestStatus
+from txdav.caldav.datastore.scheduling.processing import ImplicitProcessor
+from txdav.caldav.datastore.scheduling.scheduler import ScheduleResponseQueue
 from txdav.caldav.datastore.test.common import CommonTests as CalendarCommonTests, \
     test_event_text
 from txdav.caldav.datastore.test.test_file import setUpCalendarStore
 from txdav.caldav.datastore.test.util import buildCalendarStore
 from txdav.caldav.datastore.util import _migrateCalendar, migrateHome
-from txdav.caldav.icalendarstore import ComponentUpdateState, InvalidDefaultCalendar
-from txdav.common.datastore.sql import ECALENDARTYPE, CommonObjectResource
-from txdav.common.datastore.sql_legacy import PostgresLegacyIndexEmulator
+from txdav.caldav.icalendarstore import ComponentUpdateState, InvalidDefaultCalendar, \
+    InvalidSplit
+from txdav.common.datastore.sql import ECALENDARTYPE, CommonObjectResource, \
+    CommonStoreTransactionMonitor
 from txdav.common.datastore.sql_tables import schema, _BIND_MODE_DIRECT, \
     _BIND_STATUS_ACCEPTED
 from txdav.common.datastore.test.util import populateCalendarsFrom, \
     CommonCommonTests
 from txdav.common.icommondatastore import NoSuchObjectResourceError
+from txdav.idav import ChangeCategory
 from txdav.xml.rfc2518 import GETContentLanguage, ResourceType
-from txdav.idav import ChangeCategory
 
 import datetime
 
@@ -407,10 +410,10 @@
                           name="VCALENDAR",
                        )
                   )
-        filter = calendarqueryfilter.Filter(filter)
+        filter = Filter(filter)
         filter.settimezone(None)
 
-        results = yield toCalendar._index.indexedSearch(filter, 'user01', True)
+        results = yield toCalendar.search(filter, 'user01', True)
         self.assertEquals(len(results), 1)
         _ignore_name, uid, _ignore_type, _ignore_organizer, _ignore_float, _ignore_start, _ignore_end, _ignore_fbtype, transp = results[0]
         self.assertEquals(uid, "uid4")
@@ -618,7 +621,7 @@
 
         @inlineCallbacks
         def _defer1():
-            yield cal1.createObjectResourceWithName("1.ics", VComponent.fromString(
+            yield cal1.createObjectResourceWithName("1.ics", Component.fromString(
 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -664,7 +667,7 @@
 
         @inlineCallbacks
         def _defer2():
-            yield cal2.createObjectResourceWithName("2.ics", VComponent.fromString(
+            yield cal2.createObjectResourceWithName("2.ics", Component.fromString(
 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -825,7 +828,7 @@
         # Create calendar object
         calendar1 = yield self.calendarUnderTest()
         name = "test.ics"
-        component = VComponent.fromString(test_event_text)
+        component = Component.fromString(test_event_text)
         metadata = {
             "accessMode": "PUBLIC",
             "isScheduleObject": True,
@@ -873,7 +876,7 @@
         inbox = yield home.createCalendarWithName("inbox")
 
         name = "test.ics"
-        component = VComponent.fromString(test_event_text)
+        component = Component.fromString(test_event_text)
         metadata = {
             "accessMode": "PUBLIC",
             "isScheduleObject": True,
@@ -922,7 +925,7 @@
         """
         home = yield self.homeUnderTest()
         inbox = yield home.createCalendarWithName("inbox")
-        component = VComponent.fromString(test_event_text)
+        component = Component.fromString(test_event_text)
         inboxItem = yield inbox.createCalendarObjectWithName("inbox.ics", component)
         self.assertEquals(ChangeCategory.inbox, inboxItem.removeNotifyCategory())
         yield self.commit()
@@ -935,7 +938,7 @@
         """
         home = yield self.homeUnderTest()
         nonInbox = yield home.createCalendarWithName("noninbox")
-        component = VComponent.fromString(test_event_text)
+        component = Component.fromString(test_event_text)
         nonInboxItem = yield nonInbox.createCalendarObjectWithName("inbox.ics", component)
         self.assertEquals(ChangeCategory.default, nonInboxItem.removeNotifyCategory())
         yield self.commit()
@@ -1105,9 +1108,10 @@
         self.assertTrue(calendar2_vtodo is not None)
         children = yield calendar2_vtodo.listCalendarObjects()
         self.assertEqual(len(children), 2)
-        changed, deleted = yield calendar2_vtodo.resourceNamesSinceToken(None)
+        changed, deleted, invalid = yield calendar2_vtodo.resourceNamesSinceToken(None)
         self.assertEqual(sorted(changed), ["3.ics", "5.ics"])
         self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
         result = yield calendar2_vtodo.getSupportedComponents()
         self.assertEquals(result, "VTODO")
         self.assertTrue(pkey in calendar2_vtodo.properties())
@@ -1118,9 +1122,10 @@
         self.assertEqual(len(children), 3)
         new_sync_token2 = yield calendar2.syncToken()
         self.assertNotEqual(new_sync_token2, original_sync_token2)
-        changed, deleted = yield calendar2.resourceNamesSinceToken(original_sync_token2)
+        changed, deleted, invalid = yield calendar2.resourceNamesSinceToken(original_sync_token2)
         self.assertEqual(len(changed), 0)
         self.assertEqual(sorted(deleted), ["3.ics", "5.ics"])
+        self.assertEqual(len(invalid), 0)
         result = yield calendar2.getSupportedComponents()
         self.assertEquals(result, "VEVENT")
         self.assertTrue(pkey in calendar2.properties())
@@ -1369,7 +1374,7 @@
     @inlineCallbacks
     def test_notExpandedWithin(self):
         """
-        Test PostgresLegacyIndexEmulator.notExpandedWithin to make sure it returns the correct
+        Test Calendar.notExpandedWithin to make sure it returns the correct
         result based on the ranges passed in.
         """
 
@@ -1378,7 +1383,6 @@
         # Create the index on a new calendar
         home = yield self.homeUnderTest()
         newcalendar = yield home.createCalendarWithName("index_testing")
-        index = PostgresLegacyIndexEmulator(newcalendar)
 
         # Create the calendar object to use for testing
         nowYear = self.nowYear["now"]
@@ -1406,37 +1410,37 @@
         # Fully within range
         testMin = DateTime(nowYear, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         testMax = DateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
-        result = yield index.notExpandedWithin(testMin, testMax)
+        result = yield newcalendar.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, [])
 
         # Upper bound exceeded
         testMin = DateTime(nowYear, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         testMax = DateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
-        result = yield index.notExpandedWithin(testMin, testMax)
+        result = yield newcalendar.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, ["indexing.ics"])
 
         # Lower bound exceeded
         testMin = DateTime(nowYear - 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         testMax = DateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
-        result = yield index.notExpandedWithin(testMin, testMax)
+        result = yield newcalendar.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, ["indexing.ics"])
 
         # Lower and upper bounds exceeded
         testMin = DateTime(nowYear - 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
         testMax = DateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
-        result = yield index.notExpandedWithin(testMin, testMax)
+        result = yield newcalendar.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, ["indexing.ics"])
 
         # Lower none within range
         testMin = None
         testMax = DateTime(nowYear + 1, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
-        result = yield index.notExpandedWithin(testMin, testMax)
+        result = yield newcalendar.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, [])
 
         # Lower none and upper bounds exceeded
         testMin = None
         testMax = DateTime(nowYear + 5, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
-        result = yield index.notExpandedWithin(testMin, testMax)
+        result = yield newcalendar.notExpandedWithin(testMin, testMax)
         self.assertEqual(result, ["indexing.ics"])
 
 
@@ -1542,8 +1546,8 @@
 
         # Tests on inbox - resources with properties
         txn = self.transactionUnderTest()
-        yield txn.homeWithUID(ECALENDARTYPE, "byNameTest", create=True)
-        inbox = yield self.calendarUnderTest(txn=txn, name="inbox", home="byNameTest")
+        yield txn.homeWithUID(ECALENDARTYPE, "user01", create=True)
+        inbox = yield self.calendarUnderTest(txn=txn, name="inbox", home="user01")
         caldata = """BEGIN:VCALENDAR
 VERSION:2.0
 CALSCALE:GREGORIAN
@@ -1574,7 +1578,7 @@
         yield _createInboxItem("4.ics", "p4")
         yield self.commit()
 
-        inbox = yield self.calendarUnderTest(name="inbox", home="byNameTest")
+        inbox = yield self.calendarUnderTest(name="inbox", home="user01")
         yield _tests(inbox)
 
         resources = yield inbox.objectResourcesWithNames(("1.ics",))
@@ -2415,7 +2419,8 @@
         will = yield cobj.willSplit()
         self.assertTrue(will)
 
-        newUID = yield cobj.split()
+        newObj = yield cobj.split()
+        newUID = newObj.uid()
         yield self.commit()
 
         cobj1 = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
@@ -5144,3 +5149,1085 @@
         self.assertEqual(details[1][0], "urn:uuid:user01")
         self.assertEqual(details[1][1], ("mailto:cuser01 at example.org",))
         self.assertEqual(normalize_iCalStr(details[1][2]), normalize_iCalStr(data_past_external) % relsubs, "Failed past: %s\n%s" % (title, diff_iCalStrs(details[1][2], data_past_external % relsubs),))
+
+
+    @inlineCallbacks
+    def test_calendarObjectSplit_timeout(self):
+        """
+        Test that splitting of calendar objects works.
+        """
+        data_init = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back30)s
+DURATION:PT2H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+RRULE:FREQ=DAILY
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+END:VEVENT
+END:VCALENDAR
+"""
+
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back30)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+RRULE:FREQ=DAILY
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+END:VEVENT
+END:VCALENDAR
+"""
+
+        data_future = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back14)s
+DURATION:PT2H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR
+"""
+
+        data_past = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:%(relID)s
+DTSTART:%(now_back30)s
+DURATION:PT2H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;UNTIL=%(now_back14_1)s
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR
+"""
+
+        data_future2 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back14)s
+DURATION:PT2H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:12345-67890
+X-CALENDARSERVER-PERUSER-UID:user02
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+TRANSP:TRANSPARENT
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+"""
+
+        data_past2 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:%(relID)s
+DTSTART:%(now_back30)s
+DURATION:PT2H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;UNTIL=%(now_back14_1)s
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:%(relID)s
+X-CALENDARSERVER-PERUSER-UID:user02
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+TRANSP:TRANSPARENT
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+"""
+
+        data_inbox2 = """BEGIN:VCALENDAR
+VERSION:2.0
+METHOD:REQUEST
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back14)s
+DURATION:PT2H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR
+"""
+
+        # Create one event without active split
+        self.patch(config.Scheduling.Options.Splitting, "Enabled", False)
+        calendar = yield self.calendarUnderTest(name="calendar", home="user01")
+        component = Component.fromString(data_init % self.subs)
+        cobj = yield calendar.createCalendarObjectWithName("data1.ics", component)
+        self.assertFalse(hasattr(cobj, "_workItems"))
+        yield self.commit()
+
+        w = schema.CALENDAR_OBJECT_SPLITTER_WORK
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        # Turn on splitting
+        self.patch(config.Scheduling.Options.Splitting, "Enabled", True)
+        self.patch(config.Scheduling.Options.Splitting, "Size", 1024)
+        self.patch(config.Scheduling.Options.Splitting, "PastDays", 14)
+        self.patch(config.Scheduling.Options.Splitting, "Delay", 2)
+
+        # Setup timeouts
+        c = Clock()
+        self.patch(CommonStoreTransactionMonitor, "callLater", c.callLater)
+
+        # Patch config to turn on transaction timeouts then rebuild the store
+        self.patch(self.storeUnderTest(), "timeoutTransactions", 1)
+        cobj = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+
+        self.assertFalse(self.transactionUnderTest().timedout)
+
+        oldScheduling = ImplicitScheduler.doImplicitScheduling
+        def newScheduling(self, do_smart_merge=False, split_details=None):
+            c.advance(2)
+            return oldScheduling(self, do_smart_merge, split_details)
+        self.patch(ImplicitScheduler, "doImplicitScheduling", newScheduling)
+
+        component = Component.fromString(data % self.subs)
+        yield self.failUnlessFailure(cobj.setComponent(component), AlreadyFinishedError)
+        self.assertTrue(self.transactionUnderTest().timedout)
+        work = cobj._workItems[0]
+
+        # Clear out timed out state
+        self.lastTransaction = None
+        self.patch(self.storeUnderTest(), "timeoutTransactions", 0)
+
+        w = schema.CALENDAR_OBJECT_SPLITTER_WORK
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 1)
+        self.assertEqual(rows[0][0], cobj._resourceID)
+        yield self.abort()
+
+        # Wait for it to complete
+        yield work.whenExecuted()
+
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        # Get the existing and new object data
+        cobj1 = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+        self.assertTrue(cobj1.isScheduleObject)
+        ical1 = yield cobj1.component()
+        newUID = ical1.masterComponent().propertyValue("RELATED-TO")
+
+        cobj2 = yield self.calendarObjectUnderTest(name="%s.ics" % (newUID,), calendar_name="calendar", home="user01")
+        self.assertTrue(cobj2 is not None)
+        self.assertTrue(cobj2.isScheduleObject)
+
+        ical_future = yield cobj1.component()
+        ical_past = yield cobj2.component()
+
+        # Verify user01 data
+        title = "user01"
+        relsubs = dict(self.subs)
+        relsubs["relID"] = newUID
+        self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, "Failed future: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_past), normalize_iCalStr(data_past) % relsubs, "Failed past: %s" % (title,))
+
+        # Get user02 data
+        cal = yield self.calendarUnderTest(name="calendar", home="user02")
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 2)
+        for cobj in cobjs:
+            ical = yield cobj.component()
+            if ical.resourceUID() == "12345-67890":
+                ical_future = ical
+            else:
+                ical_past = ical
+
+        cal = yield self.calendarUnderTest(name="inbox", home="user02")
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 1)
+        ical_inbox = yield cobjs[0].component()
+
+        # Verify user02 data
+        title = "user02"
+        self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future2) % relsubs, "Failed future: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_past), normalize_iCalStr(data_past2) % relsubs, "Failed past: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_inbox), normalize_iCalStr(data_inbox2) % relsubs, "Failed inbox: %s" % (title,))
+
+
+    @inlineCallbacks
+    def _setupSplitAt(self):
+        """
+        Test that user triggered splitting of calendar objects works.
+        """
+        self.patch(config.Scheduling.Options.Splitting, "Enabled", False)
+        self.patch(config.Scheduling.Options.Splitting, "Size", 1024)
+        self.patch(config.Scheduling.Options.Splitting, "PastDays", 14)
+        self.patch(config.Scheduling.Options.Splitting, "Delay", 2)
+
+        # Create one event that will split
+        calendar = yield self.calendarUnderTest(name="calendar", home="user01")
+
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back28)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+RRULE:FREQ=DAILY;COUNT=50
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01 at example.com
+ATTENDEE:mailto:user02 at example.com
+DTSTAMP:20051222T210507Z
+ORGANIZER:mailto:user01 at example.com
+END:VEVENT
+END:VCALENDAR
+"""
+
+        data_future = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back14)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;COUNT=36
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR
+"""
+
+        data_past = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:%(relID)s
+DTSTART:%(now_back28)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;UNTIL=%(now_back14_1)s
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR
+"""
+
+        data_future2 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back14)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;COUNT=36
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:12345-67890
+X-CALENDARSERVER-PERUSER-UID:user02
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+TRANSP:TRANSPARENT
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+"""
+
+        data_past2 = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:%(relID)s
+DTSTART:%(now_back28)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;UNTIL=%(now_back14_1)s
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+BEGIN:X-CALENDARSERVER-PERUSER
+UID:%(relID)s
+X-CALENDARSERVER-PERUSER-UID:user02
+BEGIN:X-CALENDARSERVER-PERINSTANCE
+TRANSP:TRANSPARENT
+END:X-CALENDARSERVER-PERINSTANCE
+END:X-CALENDARSERVER-PERUSER
+END:VCALENDAR
+"""
+
+        data_inbox2 = """BEGIN:VCALENDAR
+VERSION:2.0
+METHOD:REQUEST
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back14)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;COUNT=36
+SEQUENCE:1
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+ATTENDEE;CN=User 01;EMAIL=user01 at example.com;PARTSTAT=ACCEPTED:urn:uuid:user01
+ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE:urn:uuid:user02
+DTSTAMP:20051222T210507Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR
+"""
+
+        # Create it
+        component = Component.fromString(data % self.subs)
+        cobj = yield calendar.createCalendarObjectWithName("data1.ics", component)
+        self.assertFalse(hasattr(cobj, "_workItems"))
+        yield self.commit()
+
+        w = schema.CALENDAR_OBJECT_SPLITTER_WORK
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        returnValue((data_future, data_past, data_future2, data_past2, data_inbox2,))
+
+
+    @inlineCallbacks
+    def _setupSplitAt2(self):
+        """
+        Test that user triggered splitting of calendar objects works.
+        """
+        self.patch(config.Scheduling.Options.Splitting, "Enabled", False)
+        self.patch(config.Scheduling.Options.Splitting, "Size", 1024)
+        self.patch(config.Scheduling.Options.Splitting, "PastDays", 14)
+        self.patch(config.Scheduling.Options.Splitting, "Delay", 2)
+
+        # Create one event that will split
+        calendar = yield self.calendarUnderTest(name="calendar", home="user01")
+
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back28)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+RRULE:FREQ=DAILY;COUNT=50
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+END:VEVENT
+END:VCALENDAR
+"""
+
+        data_future = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:%(now_back14)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;COUNT=36
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:%(now_fwd10)s
+DTSTART:%(now_fwd10)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+END:VEVENT
+END:VCALENDAR
+"""
+
+        data_past = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:%(relID)s
+DTSTART:%(now_back28)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+RRULE:FREQ=DAILY;UNTIL=%(now_back14_1)s
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back25)s
+DTSTART:%(now_back25)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+END:VEVENT
+BEGIN:VEVENT
+UID:%(relID)s
+RECURRENCE-ID:%(now_back24)s
+DTSTART:%(now_back24)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
+END:VEVENT
+END:VCALENDAR
+"""
+
+        # Create it
+        component = Component.fromString(data % self.subs)
+        cobj = yield calendar.createCalendarObjectWithName("data1.ics", component)
+        self.assertFalse(hasattr(cobj, "_workItems"))
+        yield self.commit()
+
+        w = schema.CALENDAR_OBJECT_SPLITTER_WORK
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        returnValue((data_future, data_past,))
+
+
+    @inlineCallbacks
+    def test_calendarObjectSplit_splitat_ok(self):
+        """
+        Test that user triggered splitting of calendar objects works.
+        """
+
+        data_future, data_past, data_future2, data_past2, data_inbox2 = yield self._setupSplitAt()
+
+        # Update it
+        cobj = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+        oldobj = yield cobj.splitAt(DateTime.parseText("%(now_back14)s" % self.subs))
+        oldname = oldobj.name()
+        self.assertFalse(hasattr(cobj, "_workItems"))
+        yield self.commit()
+
+        w = schema.CALENDAR_OBJECT_SPLITTER_WORK
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        # Get the existing and new object data
+        cobj1 = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+        self.assertTrue(cobj1.isScheduleObject)
+        ical1 = yield cobj1.component()
+        newUID = 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)
+
+        ical_future = yield cobj1.component()
+        ical_past = yield cobj2.component()
+
+        # Verify user01 data
+        title = "user01"
+        relsubs = dict(self.subs)
+        relsubs["relID"] = newUID
+        self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, "Failed future: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_past), normalize_iCalStr(data_past) % relsubs, "Failed past: %s" % (title,))
+
+        # Get user02 data
+        cal = yield self.calendarUnderTest(name="calendar", home="user02")
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 2)
+        for cobj in cobjs:
+            ical = yield cobj.component()
+            if ical.resourceUID() == "12345-67890":
+                ical_future = ical
+            else:
+                ical_past = ical
+
+        cal = yield self.calendarUnderTest(name="inbox", home="user02")
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 1)
+        ical_inbox = yield cobjs[0].component()
+
+        # Verify user02 data
+        title = "user02"
+        self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future2) % relsubs, "Failed future: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_past), normalize_iCalStr(data_past2) % relsubs, "Failed past: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_inbox), normalize_iCalStr(data_inbox2) % relsubs, "Failed inbox: %s" % (title,))
+
+
+    @inlineCallbacks
+    def test_calendarObjectSplit_splitat_ok_not_instance_rid(self):
+        """
+        Test that user triggered splitting of calendar objects works when split between instances.
+        """
+
+        data_future, data_past, data_future2, data_past2, data_inbox2 = yield self._setupSplitAt()
+
+        # Update it
+        cobj = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+        oldobj = yield cobj.splitAt(DateTime.parseText("%(now_back15_12h)s" % self.subs))
+        oldname = oldobj.name()
+        self.assertFalse(hasattr(cobj, "_workItems"))
+        yield self.commit()
+
+        w = schema.CALENDAR_OBJECT_SPLITTER_WORK
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        # Get the existing and new object data
+        cobj1 = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+        self.assertTrue(cobj1.isScheduleObject)
+        ical1 = yield cobj1.component()
+        newUID = 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)
+
+        ical_future = yield cobj1.component()
+        ical_past = yield cobj2.component()
+
+        # Verify user01 data
+        title = "user01"
+        relsubs = dict(self.subs)
+        relsubs["relID"] = newUID
+        self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, "Failed future: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_past), normalize_iCalStr(data_past) % relsubs, "Failed past: %s" % (title,))
+
+        # Get user02 data
+        cal = yield self.calendarUnderTest(name="calendar", home="user02")
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 2)
+        for cobj in cobjs:
+            ical = yield cobj.component()
+            if ical.resourceUID() == "12345-67890":
+                ical_future = ical
+            else:
+                ical_past = ical
+
+        cal = yield self.calendarUnderTest(name="inbox", home="user02")
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 1)
+        ical_inbox = yield cobjs[0].component()
+
+        # Verify user02 data
+        title = "user02"
+        self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future2) % relsubs, "Failed future: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_past), normalize_iCalStr(data_past2) % relsubs, "Failed past: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_inbox), normalize_iCalStr(data_inbox2) % relsubs, "Failed inbox: %s" % (title,))
+
+
+    @inlineCallbacks
+    def test_calendarObjectSplit_splitat_no_organizer(self):
+        """
+        Test that user triggered splitting of calendar objects works when no organizer is present.
+        """
+
+        data_future, data_past = yield self._setupSplitAt2()
+
+        # Update it
+        cobj = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+        oldobj = yield cobj.splitAt(DateTime.parseText("%(now_back14)s" % self.subs))
+        oldname = oldobj.name()
+        self.assertFalse(hasattr(cobj, "_workItems"))
+        yield self.commit()
+
+        w = schema.CALENDAR_OBJECT_SPLITTER_WORK
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        rows = yield Select(
+            [w.RESOURCE_ID, ],
+            From=w
+        ).on(self.transactionUnderTest())
+        self.assertEqual(len(rows), 0)
+        yield self.abort()
+
+        # Get the existing and new object data
+        cobj1 = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+        self.assertTrue(cobj1.isScheduleObject)
+        ical1 = yield cobj1.component()
+        newUID = 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)
+
+        ical_future = yield cobj1.component()
+        ical_past = yield cobj2.component()
+
+        # Verify user01 data
+        title = "user01"
+        relsubs = dict(self.subs)
+        relsubs["relID"] = newUID
+        self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, "Failed future: %s" % (title,))
+        self.assertEqual(normalize_iCalStr(ical_past), normalize_iCalStr(data_past) % relsubs, "Failed past: %s" % (title,))
+
+
+    @inlineCallbacks
+    def test_calendarObjectSplit_splitat_no_attendee_split(self):
+        """
+        Test that user triggered splitting of calendar objects does not work if done by attendee.
+        """
+
+        yield self._setupSplitAt()
+
+        # Update it
+        cal = yield self.calendarUnderTest(name="calendar", home="user02")
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 1)
+        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText("%(now_back14)s" % self.subs)), InvalidSplit)
+
+
+    @inlineCallbacks
+    def test_calendarObjectSplit_splitat_too_old(self):
+        """
+        Test that user triggered splitting of calendar objects does not work if split before first instance.
+        """
+
+        yield self._setupSplitAt()
+
+        # Update it
+        cal = yield self.calendarUnderTest(name="calendar", home="user02")
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 1)
+        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText("%(now_back30)s" % self.subs)), InvalidSplit)
+
+
+    @inlineCallbacks
+    def test_calendarObjectSplit_splitat_too_new(self):
+        """
+        Test that user triggered splitting of calendar objects does not work if split after last instance.
+        """
+
+        yield self._setupSplitAt()
+
+        # Update it
+        cal = yield self.calendarUnderTest(name="calendar", home="user02")
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 1)
+        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText("%(now_fwd25)s" % self.subs)), InvalidSplit)

Copied: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql_external.py (from rev 12321, CalendarServer/trunk/txdav/caldav/datastore/test/test_sql_external.py)
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql_external.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql_external.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -0,0 +1,682 @@
+##
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+
+from twisted.internet.defer import inlineCallbacks
+
+from twext.python.clsprop import classproperty
+from txdav.common.datastore.test.util import populateCalendarsFrom
+from txdav.common.datastore.sql_tables import _BIND_MODE_READ, \
+    _BIND_STATUS_INVITED, _BIND_MODE_DIRECT, _BIND_STATUS_ACCEPTED
+from txdav.common.datastore.podding.test.util import MultiStoreConduitTest
+
+
+class BaseSharingTests(MultiStoreConduitTest):
+
+    """
+    Test store-based calendar sharing.
+    """
+
+    @inlineCallbacks
+    def setUp(self):
+        yield super(BaseSharingTests, self).setUp()
+        yield self.populate()
+
+
+    @inlineCallbacks
+    def populate(self):
+        yield populateCalendarsFrom(self.requirements, self.storeUnderTest())
+        self.notifierFactory.reset()
+
+    cal1 = """BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:uid1
+DTSTART:20131122T140000
+DURATION:PT1H
+CREATED:20060102T190000Z
+DTSTAMP:20051222T210507Z
+SUMMARY:event 1
+END:VEVENT
+END:VCALENDAR
+"""
+
+    @classproperty(cache=False)
+    def requirements(cls): #@NoSelf
+        return {
+        "user01": {
+            "calendar": {
+                "cal1.ics": (cls.cal1, None,),
+            },
+            "inbox": {
+            },
+        },
+        "user02": {
+            "calendar": {
+            },
+            "inbox": {
+            },
+        },
+        "user03": {
+            "calendar": {
+            },
+            "inbox": {
+            },
+        },
+    }
+
+
+
+class CalendarSharing(BaseSharingTests):
+
+    @inlineCallbacks
+    def test_no_shares(self):
+        """
+        Test that initially there are no shares.
+        """
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+        self.assertFalse(calendar.isShared())
+
+
+    @inlineCallbacks
+    def test_invite_sharee(self):
+        """
+        Test invite/uninvite creates/removes shares and notifications.
+        """
+
+        # Invite
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+        self.assertFalse(calendar.isShared())
+
+        shareeView = yield calendar.inviteUserToShare("puser02", _BIND_MODE_READ, "summary")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 1)
+        self.assertEqual(invites[0].uid, shareeView.shareUID())
+        self.assertEqual(invites[0].ownerUID, "user01")
+        self.assertEqual(invites[0].shareeUID, "puser02")
+        self.assertEqual(invites[0].mode, _BIND_MODE_READ)
+        self.assertEqual(invites[0].status, _BIND_STATUS_INVITED)
+        self.assertEqual(invites[0].summary, "summary")
+
+        inviteUID = shareeView.shareUID()
+        sharedName = shareeView.name()
+
+        self.assertTrue(calendar.isShared())
+
+        yield self.commit()
+
+        shared = yield self.calendarUnderTest(txn=self.newOtherTransaction(), home="puser02", name=sharedName)
+        self.assertTrue(shared is None)
+
+        notifyHome = yield self.otherTransactionUnderTest().notificationsWithUID("puser02")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [inviteUID, ])
+        yield self.otherCommit()
+
+        # Uninvite
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 1)
+
+        yield calendar.uninviteUserFromShare("puser02")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+
+        self.assertTrue(calendar.isShared())
+
+        yield self.commit()
+
+        notifyHome = yield self.otherTransactionUnderTest().notificationsWithUID("puser02")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [])
+        yield self.otherCommit()
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertTrue(calendar.isShared())
+        yield calendar.setShared(False)
+        self.assertFalse(calendar.isShared())
+
+
+    @inlineCallbacks
+    def test_accept_share(self):
+        """
+        Test that invite+accept creates shares and notifications.
+        """
+
+        # Invite
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+        self.assertFalse(calendar.isShared())
+
+        shareeView = yield calendar.inviteUserToShare("puser02", _BIND_MODE_READ, "summary")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 1)
+
+        inviteUID = shareeView.shareUID()
+        sharedName = shareeView.name()
+
+        self.assertTrue(calendar.isShared())
+
+        yield self.commit()
+
+        shared = yield self.calendarUnderTest(txn=self.newOtherTransaction(), home="puser02", name=sharedName)
+        self.assertTrue(shared is None)
+
+        notifyHome = yield self.otherTransactionUnderTest().notificationsWithUID("puser02")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(len(notifications), 1)
+        yield self.otherCommit()
+
+        # Accept
+        txn2 = self.newOtherTransaction()
+        shareeHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        yield shareeHome.acceptShare(inviteUID)
+
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is not None)
+        yield self.otherCommit()
+
+        notifyHome = yield self.transactionUnderTest().notificationsWithUID("user01")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [inviteUID + "-reply", ])
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertTrue(calendar.isShared())
+
+        yield self.commit()
+
+        # Re-accept
+        txn2 = self.newOtherTransaction()
+        shareeHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        yield shareeHome.acceptShare(inviteUID)
+
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is not None)
+        yield self.otherCommit()
+
+        notifyHome = yield self.transactionUnderTest().notificationsWithUID("user01")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [inviteUID + "-reply", ])
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertTrue(calendar.isShared())
+
+
+    @inlineCallbacks
+    def test_decline_share(self):
+        """
+        Test that invite+decline does not create shares but does create notifications.
+        """
+
+        # Invite
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+        self.assertFalse(calendar.isShared())
+
+        shareeView = yield calendar.inviteUserToShare("puser02", _BIND_MODE_READ, "summary")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 1)
+
+        inviteUID = shareeView.shareUID()
+        sharedName = shareeView.name()
+
+        self.assertTrue(calendar.isShared())
+
+        yield self.commit()
+
+        txn2 = self.newOtherTransaction()
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is None)
+
+        notifyHome = yield txn2.notificationsWithUID("puser02")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(len(notifications), 1)
+        yield self.otherCommit()
+
+        # Decline
+        txn2 = self.newOtherTransaction()
+        shareeHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        yield shareeHome.declineShare(inviteUID)
+
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is None)
+        yield self.otherCommit()
+
+        notifyHome = yield self.transactionUnderTest().notificationsWithUID("user01")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [inviteUID + "-reply", ])
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertTrue(calendar.isShared())
+
+        yield self.commit()
+
+        # Redecline
+        txn2 = self.newOtherTransaction()
+        shareeHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        yield shareeHome.declineShare(inviteUID)
+
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is None)
+        yield self.otherCommit()
+
+        notifyHome = yield self.transactionUnderTest().notificationsWithUID("user01")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [inviteUID + "-reply", ])
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertTrue(calendar.isShared())
+
+
+    @inlineCallbacks
+    def test_accept_decline_share(self):
+        """
+        Test that invite+accept/decline creates/removes shares and notifications.
+        Decline via the home.
+        """
+
+        # Invite
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+        self.assertFalse(calendar.isShared())
+
+        shareeView = yield calendar.inviteUserToShare("puser02", _BIND_MODE_READ, "summary")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 1)
+        inviteUID = shareeView.shareUID()
+
+        sharedName = shareeView.name()
+
+        self.assertTrue(calendar.isShared())
+
+        yield self.commit()
+
+        txn2 = self.newOtherTransaction()
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is None)
+
+        notifyHome = yield txn2.notificationsWithUID("puser02")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(len(notifications), 1)
+        yield self.otherCommit()
+
+        # Accept
+        txn2 = self.newOtherTransaction()
+        shareeHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        yield shareeHome.acceptShare(inviteUID)
+
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is not None)
+        yield self.otherCommit()
+
+        notifyHome = yield self.transactionUnderTest().notificationsWithUID("user01")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [inviteUID + "-reply", ])
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertTrue(calendar.isShared())
+
+        yield self.commit()
+
+        # Decline
+        txn2 = self.newOtherTransaction()
+        shareeHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        yield shareeHome.declineShare(inviteUID)
+
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is None)
+        yield self.otherCommit()
+
+        notifyHome = yield self.transactionUnderTest().notificationsWithUID("user01")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [inviteUID + "-reply", ])
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertTrue(calendar.isShared())
+
+
+    @inlineCallbacks
+    def test_accept_remove_share(self):
+        """
+        Test that invite+accept/decline creates/removes shares and notifications.
+        Decline via the shared collection (removal).
+        """
+
+        # Invite
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+
+        shareeView = yield calendar.inviteUserToShare("puser02", _BIND_MODE_READ, "summary")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 1)
+
+        inviteUID = shareeView.shareUID()
+        sharedName = shareeView.name()
+
+        yield self.commit()
+
+        txn2 = self.newOtherTransaction()
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is None)
+
+        notifyHome = yield txn2.notificationsWithUID("puser02")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(len(notifications), 1)
+        yield self.otherCommit()
+
+        # Accept
+        txn2 = self.newOtherTransaction()
+        shareeHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        yield shareeHome.acceptShare(inviteUID)
+
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is not None)
+        yield self.otherCommit()
+
+        notifyHome = yield self.transactionUnderTest().notificationsWithUID("user01")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [inviteUID + "-reply", ])
+
+        yield self.commit()
+
+        # Delete
+        txn2 = self.newOtherTransaction()
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        yield shared.deleteShare()
+        yield self.otherCommit()
+
+        txn2 = self.newOtherTransaction()
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertTrue(shared is None)
+        yield self.otherCommit()
+
+        notifyHome = yield self.transactionUnderTest().notificationsWithUID("user01")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(notifications, [inviteUID + "-reply", ])
+
+
+    @inlineCallbacks
+    def test_accept_remove_accept(self):
+        yield self.createShare()
+        yield self.removeShare()
+        shared_name = yield self.createShare()
+
+        txn2 = self.newOtherTransaction()
+        otherCal = yield self.calendarUnderTest(txn=txn2, home="puser02", name=shared_name)
+        self.assertTrue(otherCal is not None)
+        yield self.otherCommit()
+
+
+    @inlineCallbacks
+    def test_accept_remove_accept_newcalendar(self):
+        """
+        Test that deleting and re-creating a share with the same sharer name works.
+        """
+
+        home = yield self.homeUnderTest(name="user01", create=True)
+        yield home.createCalendarWithName("shared")
+        yield self.commit()
+
+        shared_name = yield self.createShare(name="shared")
+
+        txn2 = self.newOtherTransaction()
+        otherCal = yield self.calendarUnderTest(txn=txn2, home="puser02", name=shared_name)
+        self.assertTrue(otherCal is not None)
+        yield self.otherCommit()
+
+        yield self.removeShare(name="shared")
+        home = yield self.homeUnderTest(name="user01", create=True)
+        yield home.removeCalendarWithName("shared")
+        yield self.commit()
+
+        txn2 = self.newOtherTransaction()
+        otherCal = yield self.calendarUnderTest(txn=txn2, home="puser02", name=shared_name)
+        self.assertTrue(otherCal is None)
+        yield self.otherCommit()
+
+        home = yield self.homeUnderTest(name="user01", create=True)
+        yield home.createCalendarWithName("shared")
+        yield self.commit()
+
+        shared_name = yield self.createShare(name="shared")
+
+        txn2 = self.newOtherTransaction()
+        otherCal = yield self.calendarUnderTest(txn=txn2, home="puser02", name=shared_name)
+        self.assertTrue(otherCal is not None)
+        yield self.otherCommit()
+
+
+    @inlineCallbacks
+    def test_inviteProperties(self):
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        yield calendar.setUsedForFreeBusy(True)
+        yield self.commit()
+
+        shared_name = yield self.createShare()
+
+        txn2 = self.newOtherTransaction()
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=shared_name)
+        self.assertFalse(shared.isUsedForFreeBusy())
+
+
+    @inlineCallbacks
+    def test_direct_sharee(self):
+        """
+        Test invite/uninvite creates/removes shares and notifications.
+        """
+
+        # Invite
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+        self.assertFalse(calendar.isShared())
+
+        shareeView = yield calendar.directShareWithUser("puser02")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 1)
+        self.assertEqual(invites[0].uid, shareeView.shareUID())
+        self.assertEqual(invites[0].ownerUID, "user01")
+        self.assertEqual(invites[0].shareeUID, "puser02")
+        self.assertEqual(invites[0].mode, _BIND_MODE_DIRECT)
+        self.assertEqual(invites[0].status, _BIND_STATUS_ACCEPTED)
+
+        sharedName = shareeView.name()
+
+        yield self.commit()
+
+        txn2 = self.newOtherTransaction()
+        shared = yield self.calendarUnderTest(txn=txn2, home="user02", name=sharedName)
+        self.assertTrue(shared is not None)
+
+        notifyHome = yield txn2.notificationsWithUID("user02")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(len(notifications), 0)
+        yield self.otherCommit()
+
+        # Remove
+        txn2 = self.newOtherTransaction()
+        shared = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        yield shared.deleteShare()
+        yield self.otherCommit()
+
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+
+        notifyHome = yield self.transactionUnderTest().notificationsWithUID("user01")
+        notifications = yield notifyHome.listNotificationObjects()
+        self.assertEqual(len(notifications), 0)
+
+    test_direct_sharee.skip = True
+
+    @inlineCallbacks
+    def test_sharedNotifierID(self):
+        shared_name = yield self.createShare()
+
+        home = yield self.homeUnderTest(name="user01")
+        self.assertEquals(home.notifierID(), ("CalDAV", "user01",))
+        calendar = yield home.calendarWithName("calendar")
+        self.assertEquals(calendar.notifierID(), ("CalDAV", "user01/calendar",))
+        yield self.commit()
+
+        txn2 = self.newOtherTransaction()
+        home = yield self.homeUnderTest(txn=txn2, name="puser02")
+        self.assertEquals(home.notifierID(), ("CalDAV", "puser02",))
+        calendar = yield home.calendarWithName(shared_name)
+        self.assertEquals(calendar.notifierID(), ("CalDAV", "user01/calendar",))
+
+
+    @inlineCallbacks
+    def test_sharedWithTwo(self):
+        shared_name1 = yield self.createShare(shareeGUID="puser02")
+        shared_name2 = yield self.createShare(shareeGUID="puser03")
+
+        txn2 = self.newOtherTransaction()
+        otherCal = yield self.calendarUnderTest(txn=txn2, home="puser02", name=shared_name1)
+        self.assertTrue(otherCal is not None)
+        yield self.otherCommit()
+
+        txn2 = self.newOtherTransaction()
+        otherCal = yield self.calendarUnderTest(txn=txn2, home="puser03", name=shared_name2)
+        self.assertTrue(otherCal is not None)
+        yield self.otherCommit()
+
+
+
+class SharingRevisions(BaseSharingTests):
+    """
+    Test store-based sharing and interaction with revision table.
+    """
+
+    @inlineCallbacks
+    def test_shareWithRevision(self):
+        """
+        Verify that bindRevision on calendars and shared calendars has the correct value.
+        """
+        sharedName = yield self.createShare()
+
+        normalCal = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertEqual(normalCal._bindRevision, 0)
+
+        txn2 = self.newOtherTransaction()
+        otherCal = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertNotEqual(otherCal._bindRevision, 0)
+
+
+    @inlineCallbacks
+    def test_updateShareRevision(self):
+        """
+        Verify that bindRevision on calendars and shared calendars has the correct value.
+        """
+        # Invite
+        calendar = yield self.calendarUnderTest(home="user01", name="calendar")
+        invites = yield calendar.sharingInvites()
+        self.assertEqual(len(invites), 0)
+
+        shareeView = yield calendar.inviteUserToShare("puser02", _BIND_MODE_READ, "summary")
+        newCalName = shareeView.shareUID()
+        yield self.commit()
+
+        normalCal = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertEqual(normalCal._bindRevision, 0)
+        yield self.commit()
+
+        txn2 = self.newOtherTransaction()
+        otherHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        otherCal = yield otherHome.anyObjectWithShareUID(newCalName)
+        self.assertEqual(otherCal._bindRevision, 0)
+        yield self.otherCommit()
+
+        txn2 = self.newOtherTransaction()
+        shareeHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        shareeView = yield shareeHome.acceptShare(newCalName)
+        sharedName = shareeView.name()
+        yield self.otherCommit()
+
+        normalCal = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertEqual(normalCal._bindRevision, 0)
+
+        txn2 = self.newOtherTransaction()
+        otherCal = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertNotEqual(otherCal._bindRevision, 0)
+
+
+    @inlineCallbacks
+    def test_sharedRevisions(self):
+        """
+        Verify that resourceNamesSinceRevision returns all resources after initial bind and sync.
+        """
+        sharedName = yield self.createShare()
+
+        normalCal = yield self.calendarUnderTest(home="user01", name="calendar")
+        self.assertEqual(normalCal._bindRevision, 0)
+
+        txn2 = self.newOtherTransaction()
+        otherHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+        otherCal = yield self.calendarUnderTest(txn=txn2, home="puser02", name=sharedName)
+        self.assertNotEqual(otherCal._bindRevision, 0)
+
+        sync_token = yield otherCal.syncToken()
+        revision = otherCal.revisionFromToken(sync_token)
+
+        changed, deleted, invalid = yield otherCal.resourceNamesSinceRevision(0)
+        self.assertNotEqual(len(changed), 0)
+        self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
+
+        changed, deleted, invalid = yield otherCal.resourceNamesSinceRevision(revision)
+        self.assertEqual(len(changed), 0)
+        self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
+
+        sync_token = yield otherHome.syncToken()
+        revision = otherHome.revisionFromToken(sync_token)
+
+        for depth in ("1", "infinity",):
+            changed, deleted, invalid = yield otherHome.resourceNamesSinceRevision(revision - 1, depth)
+            self.assertEqual(len(changed), 0 if depth == "infinity" else 1)
+            self.assertEqual(len(deleted), 0)
+            self.assertEqual(len(invalid), 1 if depth == "infinity" else 0)
+
+            changed, deleted, invalid = yield otherHome.resourceNamesSinceRevision(revision, depth)
+            self.assertEqual(len(changed), 0)
+            self.assertEqual(len(deleted), 0)
+            self.assertEqual(len(invalid), 1 if depth == "infinity" else 0)
+
+        yield self.otherCommit()
+
+        yield self.removeShare()
+
+        txn2 = self.newOtherTransaction()
+        otherHome = yield self.homeUnderTest(txn=txn2, name="puser02")
+
+        for depth in ("1", "infinity",):
+            changed, deleted, invalid = yield otherHome.resourceNamesSinceRevision(revision, depth)
+            self.assertEqual(len(changed), 0)
+            self.assertEqual(len(deleted), 1)
+            self.assertEqual(len(invalid), 0)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql_sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql_sharing.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_sql_sharing.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -554,13 +554,15 @@
         otherCal = yield self.calendarUnderTest(home="user02", name=sharedName)
         self.assertNotEqual(otherCal._bindRevision, 0)
 
-        changed, deleted = yield otherCal.resourceNamesSinceRevision(0)
+        changed, deleted, invalid = yield otherCal.resourceNamesSinceRevision(0)
         self.assertNotEqual(len(changed), 0)
         self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
 
-        changed, deleted = yield otherCal.resourceNamesSinceRevision(otherCal._bindRevision)
+        changed, deleted, invalid = yield otherCal.resourceNamesSinceRevision(otherCal._bindRevision)
         self.assertEqual(len(changed), 0)
         self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
 
         for depth, result in (
             ("1", [otherCal.name() + '/',
@@ -572,10 +574,12 @@
                          'calendar/',
                          'inbox/'],
              )):
-            changed, deleted = yield otherHome.resourceNamesSinceRevision(0, depth)
+            changed, deleted, invalid = yield otherHome.resourceNamesSinceRevision(0, depth)
             self.assertEqual(set(changed), set(result))
             self.assertEqual(len(deleted), 0)
+            self.assertEqual(len(invalid), 0)
 
-            changed, deleted = yield otherHome.resourceNamesSinceRevision(otherCal._bindRevision, depth)
+            changed, deleted, invalid = yield otherHome.resourceNamesSinceRevision(otherCal._bindRevision, depth)
             self.assertEqual(len(changed), 0)
             self.assertEqual(len(deleted), 0)
+            self.assertEqual(len(invalid), 0)

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/test_util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-from txdav.caldav.datastore.test.util import buildCalendarStore
 
 """
 Tests for txdav.caldav.datastore.util.
@@ -30,6 +29,7 @@
 from twistedcaldav.test.util import TestCase
 
 from txdav.common.datastore.test.util import populateCalendarsFrom, CommonCommonTests
+from txdav.caldav.datastore.test.util import buildCalendarStore
 
 from txdav.caldav.datastore.util import dropboxIDFromCalendarObject, \
     StorageTransportBase, migrateHome
@@ -323,7 +323,12 @@
     @inlineCallbacks
     def setUp(self):
         yield super(HomeMigrationTests, self).setUp()
-        self.theStore = yield buildCalendarStore(self, self.notifierFactory, homes=("conflict1", "conflict2",))
+        self.theStore = yield buildCalendarStore(self, self.notifierFactory, homes=(
+            "conflict1",
+            "conflict2",
+            "empty_home",
+            "non_empty_home",
+        ))
 
 
     def storeUnderTest(self):

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/test/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.carddav.datastore.test -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -62,18 +62,13 @@
         calendarUserAddresses,
         cutype="INDIVIDUAL",
         thisServer=True,
+        server=None,
         extras={},
     ):
 
-        super(TestCalendarStoreDirectoryRecord, self).__init__(uid, shortNames,
-            fullName, extras=extras)
-        self.uid = uid
-        self.shortNames = shortNames
-        self.fullName = fullName
-        self.displayName = self.fullName if self.fullName else self.shortNames[0]
+        super(TestCalendarStoreDirectoryRecord, self).__init__(uid, shortNames, fullName, thisServer, server, extras=extras)
         self.calendarUserAddresses = calendarUserAddresses
         self.cutype = cutype
-        self._thisServer = thisServer
 
 
     def canonicalCalendarUserAddress(self):
@@ -92,10 +87,6 @@
         return cua
 
 
-    def thisServer(self):
-        return self._thisServer
-
-
     def calendarsEnabled(self):
         return True
 
@@ -150,12 +141,19 @@
     homes.update((
         "home1",
         "home2",
-        "Home_attachments",
+        "home3",
+        "home_attachments",
         "home_bad",
         "home_defaults",
         "home_no_splits",
+        "home_provision1",
+        "home_provision2",
         "home_splits",
         "home_splits_shared",
+        "uid1",
+        "uid2",
+        "new-home",
+        "xyzzy",
     ))
     for uid in homes:
         directory.addRecord(buildDirectoryRecord(uid))

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/datastore/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.caldav.datastore.test.test_util -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/icalendardirectoryservice.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/icalendardirectoryservice.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/icalendardirectoryservice.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2013 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -60,14 +60,6 @@
         @rtype: C{str}
         """
 
-    def thisServer(): #@NoSelf
-        """
-        Indicates whether the record is hosted on this server "pod".
-
-        @return: C{True} if hosted by this service.
-        @rtype: C{bool}
-        """
-
     def calendarsEnabled(): #@NoSelf
         """
         Indicates whether the record enabled for using the calendar service.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/icalendarstore.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/icalendarstore.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/icalendarstore.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.caldav.datastore -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -843,6 +843,13 @@
 
 
 
+class InvalidSplit(CommonStoreError):
+    """
+    A user triggered split operation is invalid.
+    """
+
+
+
 #
 # FIXME: These may belong elsewhere.
 #
@@ -907,7 +914,7 @@
     NORMAL_NO_IMPLICIT -    this is an application layer (user) generated remove that deliberately turns
                             off implicit scheduling operations.
 
-    INTERNAL -              remove the resource without implicit scheduling.
+    INTERNAL -              remove the resource without implicit scheduling or attachment processing.
     """
 
     NORMAL = NamedConstant()

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/caldav/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/file.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.carddav.datastore.test.test_file -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/index_file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/index_file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/index_file.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -37,10 +37,6 @@
 
 from twisted.internet.defer import maybeDeferred
 
-from twistedcaldav import carddavxml
-from txdav.common.icommondatastore import SyncTokenValidException, \
-    ReservationError
-from twistedcaldav.query import addressbookquery
 from twistedcaldav.sql import AbstractSQLDatabase
 from twistedcaldav.sql import db_prefix
 from twistedcaldav.vcard import Component
@@ -49,6 +45,12 @@
 from twistedcaldav.config import config
 from twistedcaldav.memcachepool import CachePoolUserMixIn
 
+from txdav.carddav.datastore.query.builder import buildExpression
+from txdav.carddav.datastore.query.filter import Filter
+from txdav.common.datastore.query.filegenerator import sqllitegenerator
+from txdav.common.icommondatastore import SyncTokenValidException, \
+    ReservationError
+
 log = Logger()
 
 db_basename = db_prefix + "sqlite"
@@ -218,6 +220,24 @@
 
 
 
+def sqladdressbookquery(filter, addressbookid=None):
+    """
+    Convert the supplied addressbook-query into a partial SQL statement.
+
+    @param filter: the L{Filter} for the addressbook-query to convert.
+    @return: a C{tuple} of (C{str}, C{list}), where the C{str} is the partial SQL statement,
+            and the C{list} is the list of argument substitutions to use with the SQL API execute method.
+            Or return C{None} if it is not possible to create an SQL query to fully match the addressbook-query.
+    """
+    try:
+        expression = buildExpression(filter, sqllitegenerator.FIELDS)
+        sql = sqllitegenerator(expression, addressbookid, None)
+        return sql.generate()
+    except ValueError:
+        return None
+
+
+
 class AddressBookIndex(AbstractSQLDatabase):
     """
     AddressBook collection index abstract base class that defines the apis for the index.
@@ -410,6 +430,7 @@
 
         changed = []
         deleted = []
+        invalid = []
         for name, wasdeleted in results:
             if name:
                 if wasdeleted == 'Y':
@@ -420,7 +441,7 @@
             else:
                 raise SyncTokenValidException
 
-        return changed, deleted,
+        return (changed, deleted, invalid)
 
 
     def lastRevision(self):
@@ -445,8 +466,8 @@
 
 
     def searchValid(self, filter):
-        if isinstance(filter, carddavxml.Filter):
-            qualifiers = addressbookquery.sqladdressbookquery(filter)
+        if isinstance(filter, Filter):
+            qualifiers = sqladdressbookquery(filter)
         else:
             qualifiers = None
 
@@ -466,8 +487,8 @@
         # start caching...
 
         # Make sure we have a proper Filter element and get the partial SQL statement to use.
-        if isinstance(filter, carddavxml.Filter):
-            qualifiers = addressbookquery.sqladdressbookquery(filter)
+        if isinstance(filter, Filter):
+            qualifiers = sqladdressbookquery(filter)
         else:
             qualifiers = None
         if qualifiers is not None:

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/sql.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.carddav.datastore.test.test_sql -*-
 # #
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,8 +14,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 # #
-from txdav.xml import element
 
+
 """
 SQL backend for CardDAV storage.
 """
@@ -47,12 +47,14 @@
 
 from txdav.base.propertystore.base import PropertyName
 from txdav.base.propertystore.sql import PropertyStore
+from txdav.carddav.datastore.query.builder import buildExpression
+from txdav.carddav.datastore.query.filter import Filter
 from txdav.carddav.iaddressbookstore import IAddressBookHome, IAddressBook, \
     IAddressBookObject, GroupWithUnsharedAddressNotAllowedError, \
     KindChangeNotAllowedError
+from txdav.common.datastore.query.generator import SQLQueryGenerator
 from txdav.common.datastore.sql import CommonHome, CommonHomeChild, \
     CommonObjectResource, EADDRESSBOOKTYPE, SharingMixIn, SharingInvitation
-from txdav.common.datastore.sql_legacy import PostgresLegacyABIndexEmulator
 from txdav.common.datastore.sql_tables import _ABO_KIND_PERSON, \
     _ABO_KIND_GROUP, _ABO_KIND_RESOURCE, _ABO_KIND_LOCATION, schema, \
     _BIND_MODE_OWN, _BIND_MODE_WRITE, _BIND_STATUS_ACCEPTED, \
@@ -61,7 +63,8 @@
     InvalidUIDError, UIDExistsError, ObjectResourceTooBigError, \
     InvalidObjectResourceError, InvalidComponentForStoreError, \
     AllRetriesFailed, ObjectResourceNameAlreadyExistsError, \
-    SyncTokenValidException
+    SyncTokenValidException, IndexedSearchException
+from txdav.xml import element
 
 from zope.interface.declarations import implements
 
@@ -86,7 +89,6 @@
 
     def __init__(self, transaction, ownerUID):
 
-        self._childClass = AddressBook
         super(AddressBookHome, self).__init__(transaction, ownerUID)
         self._addressbookPropertyStoreID = None
         self._addressbook = None
@@ -450,6 +452,8 @@
     """
     implements(IAddressBook)
 
+    _homeType = EADDRESSBOOKTYPE
+
     # structured tables.  (new, preferred)
     _homeSchema = schema.ADDRESSBOOK_HOME
     _bindSchema = schema.SHARED_ADDRESSBOOK_BIND
@@ -458,14 +462,87 @@
     _revisionsSchema = schema.ADDRESSBOOK_OBJECT_REVISIONS
     _objectSchema = schema.ADDRESSBOOK_OBJECT
 
+    # Mapping of vCard property name to DB column name
+    _queryFields = {
+        "UID": _objectSchema.UID,
+    }
 
-    def __init__(self, home, name, resourceID, mode, status, revision=0, message=None, ownerHome=None, ownerName=None):
+
+    @classmethod
+    @inlineCallbacks
+    def _getDBDataIndirect(cls, home, name, resourceID, externalID):
+
+        # Get the bind row data
+        row = None
+
+        # TODO: query cacher
+
+        rows = None
+        ownerHome = None
+
+        # TODO: add queryCacher support
+
+        if rows is None:
+            # No cached copy
+            if name:
+                ownerHome = yield home._txn.addressbookHomeWithUID(name)
+                if ownerHome is None:
+                    returnValue(None)
+                resourceID = ownerHome.addressbook()._resourceID
+            rows = yield AddressBookObject._bindForHomeIDAndAddressBookID.on(
+                home._txn, homeID=home._resourceID, addressbookID=resourceID
+            )
+
+        if not rows:
+            returnValue(None)
+
+        groupID = None
+        overallBindStatus = _BIND_STATUS_INVITED
+        minBindRevision = None
+        for row in rows:
+            bindMode, homeID, resourceGroupID, externalID, name, bindStatus, bindRevision, bindMessage = row[:cls.bindColumnCount] #@UnusedVariable
+            if groupID is None:
+                groupID = resourceGroupID
+            minBindRevision = min(minBindRevision, bindRevision) if minBindRevision is not None else bindRevision
+            if bindStatus == _BIND_STATUS_ACCEPTED:
+                overallBindStatus = _BIND_STATUS_ACCEPTED
+
+        if ownerHome is None:
+            ownerAddressBookID = yield AddressBookObject.ownerAddressBookIDFromGroupID(home._txn, groupID)
+            ownerHome = yield home.ownerHomeWithChildID(ownerAddressBookID)
+
+        bindData = row[:cls.bindColumnCount]
+        additionalBindData = row[cls.bindColumnCount:cls.bindColumnCount + len(cls.additionalBindColumns())]
+
+        # Adjust for aggregate values
+        bindData[cls.bindColumns().index(cls._bindSchema.RESOURCE_ID)] = resourceID
+        bindData[cls.bindColumns().index(cls._bindSchema.RESOURCE_NAME)] = ownerHome.uid()
+        bindData[cls.bindColumns().index(cls._bindSchema.BIND_MODE)] = _BIND_MODE_INDIRECT
+        bindData[cls.bindColumns().index(cls._bindSchema.BIND_STATUS)] = overallBindStatus
+        bindData[cls.bindColumns().index(cls._bindSchema.BIND_REVISION)] = minBindRevision
+        bindData[cls.bindColumns().index(cls._bindSchema.MESSAGE)] = ""
+
+        # Get the matching metadata data
+        metadataData = None
+        queryCacher = home._txn._queryCacher
+        if queryCacher:
+            # Retrieve from cache
+            cacheKey = queryCacher.keyForHomeChildMetaData(resourceID)
+            metadataData = yield queryCacher.get(cacheKey)
+
+        if metadataData is None:
+            # No cached copy
+            metadataData = (yield cls._metadataByIDQuery.on(home._txn, resourceID=resourceID))[0]
+            if queryCacher:
+                # Cache the results
+                yield queryCacher.setAfterCommit(home._txn, cacheKey, metadataData)
+
+        returnValue((bindData, additionalBindData, metadataData, ownerHome,))
+
+
+    def __init__(self, home, name, resourceID, mode, status, revision=0, message=None, ownerHome=None, ownerName=None, externalID=None):
         ownerName = ownerHome.addressbook().name() if ownerHome else None
-        super(AddressBook, self).__init__(
-            home, name, resourceID, mode, status, revision=revision,
-            message=message, ownerHome=ownerHome, ownerName=ownerName
-        )
-        self._index = PostgresLegacyABIndexEmulator(self)
+        super(AddressBook, self).__init__(home, name, resourceID, mode, status, revision=revision, message=message, ownerHome=ownerHome, ownerName=ownerName, externalID=externalID)
 
 
     def __repr__(self):
@@ -579,13 +656,14 @@
                 raise SyncTokenValidException
 
         # call sharedChildResourceNamesSinceRevision() and filter results
-        sharedChildChanged, sharedChildDeleted = yield self.sharedChildResourceNamesSinceRevision(revision, "infinity")
+        sharedChildChanged, sharedChildDeleted, sharedChildInvalid = yield self.sharedChildResourceNamesSinceRevision(revision, "infinity")
 
         selfPath = self.name() + '/'
         lenpath = len(selfPath)
         changed = [item[lenpath:] for item in sharedChildChanged if item.startswith(selfPath) and item != selfPath]
         deleted = [item[lenpath:] for item in sharedChildDeleted if item.startswith(selfPath) and item != selfPath]
-        returnValue((changed, deleted,))
+        invalid = [item[lenpath:] for item in sharedChildInvalid if item.startswith(selfPath) and item != selfPath]
+        returnValue((changed, deleted, invalid))
 
 
     @inlineCallbacks
@@ -622,7 +700,7 @@
                 self._txn, homeID=self._home._resourceID, addressbookID=self._resourceID
         )
         if groupBindRows:
-            bindRevisions += [groupBindRow[5] for groupBindRow in groupBindRows]
+            bindRevisions += [groupBindRow[self.bindColumns().index(self._bindSchema.BIND_REVISION)] for groupBindRow in groupBindRows]
 
         if revision != 0 and revision < max(bindRevisions):
             if depth != '1':
@@ -634,20 +712,17 @@
 
         if self.fullyShared():
             # add change for addressbook group
-            changed, deleted = yield super(AddressBook, self).sharedChildResourceNamesSinceRevision(revision, depth)
+            changed, deleted, invalid = yield super(AddressBook, self).sharedChildResourceNamesSinceRevision(revision, depth)
 
-            #===================================================================
-            # # Add the following to add the addressbook group in sync report:
-            #
-            # if changed and depth != "1":
-            #     changed.add("%s/%s" % (path, self._groupForSharedAddressBookName(),))
-            #===================================================================
+            if revision == 0 and depth != "1":
+                changed.add("%s/%s" % (path, self._groupForSharedAddressBookName(),))
 
-            returnValue((changed, deleted))
+            returnValue((changed, deleted, invalid))
 
         changed = set()
         deleted = set()
-        acceptedGroupIDs = set([groupBindRow[2] for groupBindRow in groupBindRows])
+        invalid = set()
+        acceptedGroupIDs = set([groupBindRow[self.bindColumns().index(self._bindSchema.RESOURCE_ID)] for groupBindRow in groupBindRows])
 
         allowedObjectIDs = set((yield self.expandGroupIDs(self._txn, acceptedGroupIDs)))
         oldAllowedObjectIDs = set((yield self.expandGroupIDs(self._txn, acceptedGroupIDs, revision))) if revision else set()
@@ -719,7 +794,7 @@
                 for addedObjectID in allowedObjectIDs:
                     changed.add("%s/%s" % (path, idToNameMap[addedObjectID],))
 
-        returnValue((changed, deleted))
+        returnValue((changed, deleted, invalid,))
 
 
     @inlineCallbacks
@@ -747,6 +822,37 @@
         )
 
 
+    def getInviteCopyProperties(self):
+        """
+        Get a dictionary of property name/values (as strings) for properties that are shadowable and
+        need to be copied to a sharee's collection when an external (cross-pod) share is created.
+        Sub-classes should override to expose the properties they care about.
+        """
+        props = {}
+        for elem in (element.DisplayName, carddavxml.AddressBookDescription,):
+            if PropertyName.fromElement(elem) in self.properties():
+                props[elem.sname()] = str(self.properties()[PropertyName.fromElement(elem)])
+        return props
+
+
+    def setInviteCopyProperties(self, props):
+        """
+        Copy a set of shadowable properties (as name/value strings) onto this shared resource when
+        a cross-pod invite is processed. Sub-classes should override to expose the properties they
+        care about.
+        """
+        # Initialize these for all shares
+        for elem in (carddavxml.AddressBookDescription,):
+            if PropertyName.fromElement(elem) not in self.properties() and elem.sname() in props:
+                self.properties()[PropertyName.fromElement(elem)] = elem.fromString(props[elem.sname()])
+
+        # Only initialize these for direct shares
+        if self.direct():
+            for elem in (element.DisplayName,):
+                if PropertyName.fromElement(elem) not in self.properties() and elem.sname() in props:
+                    self.properties()[PropertyName.fromElement(elem)] = elem.fromString(props[elem.sname()])
+
+
     def contentType(self):
         """
         The content type of addressbook objects is text/vcard.
@@ -755,7 +861,7 @@
 
 
     @classmethod
-    def create(cls, home, name):
+    def create(cls, home, name, externalID=None):
         if name == home.addressbook().name():
             # raise HomeChildNameAlreadyExistsError
             pass
@@ -781,13 +887,15 @@
     def remove(self):
 
         if self._resourceID == self._home._resourceID:
+
+            # Stop sharing first
+            yield self.ownerDeleteShare()
+
             # Allow remove, as a way to reset the address book to an empty state
             for abo in (yield self.objectResources()):
                 yield abo.remove()
                 yield self.removedObjectResource(abo)
 
-            yield self.unshare()  # storebridge should already have done this
-
             yield self.properties()._removeResource()
             yield self._loadPropertyStore()
 
@@ -944,6 +1052,57 @@
             returnValue((yield super(AddressBook, self).bumpModified()))
 
 
+    @inlineCallbacks
+    def search(self, filter):
+        """
+        Finds resources matching the given qualifiers.
+        @param filter: the L{Filter} for the addressbook-query to execute.
+        @return: an iterable of tuples for each resource matching the
+            given C{qualifiers}. The tuples are C{(name, uid)}, where
+            C{name} is the resource name, C{uid} is the resource UID.
+        """
+
+        # We might be passed an L{Filter} or a serialization of one
+        if isinstance(filter, dict):
+            try:
+                filter = Filter.deserialize(filter)
+            except Exception:
+                filter = None
+
+        # Make sure we have a proper Filter element and get the partial SQL statement to use.
+        sql_stmt = self._sqlquery(filter)
+
+        # No result means it is too complex for us
+        if sql_stmt is None:
+            raise IndexedSearchException()
+
+        sql_stmt, args = sql_stmt
+        rowiter = yield sql_stmt.on(self._txn, **args)
+
+        returnValue(list(rowiter))
+
+
+    def _sqlquery(self, filter):
+        """
+        Convert the supplied addressbook-query into a partial SQL statement.
+
+        @param filter: the L{Filter} for the addressbook-query to convert.
+        @return: a C{tuple} of (C{str}, C{list}), where the C{str} is the partial SQL statement,
+                and the C{list} is the list of argument substitutions to use with the SQL API execute method.
+                Or return C{None} if it is not possible to create an SQL query to fully match the addressbook-query.
+        """
+
+        if not isinstance(filter, Filter):
+            return None
+
+        try:
+            expression = buildExpression(filter, self._queryFields)
+            sql = SQLQueryGenerator(expression, self, self.id())
+            return sql.generate()
+        except ValueError:
+            return None
+
+
     @classmethod
     @inlineCallbacks
     def listObjects(cls, home):
@@ -965,7 +1124,7 @@
             home._txn, homeID=home._resourceID
         )
         for groupRow in groupRows:
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
+            bindMode, homeID, resourceID, externalID, bindName, bindStatus, bindRevision, bindMessage = groupRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
             ownerAddressBookID = yield AddressBookObject.ownerAddressBookIDFromGroupID(home._txn, resourceID)
             ownerHome = yield home._txn.homeWithResourceID(home._homeType, ownerAddressBookID, create=True)
             names |= set([ownerHome.uid()])
@@ -993,7 +1152,7 @@
         )
         # get ownerHomeIDs
         for dataRow in dataRows:
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = dataRow[:cls.bindColumnCount] #@UnusedVariable
+            bindMode, homeID, resourceID, externalID, bindName, bindStatus, bindRevision, bindMessage = dataRow[:cls.bindColumnCount] #@UnusedVariable
             ownerHome = yield home.ownerHomeWithChildID(resourceID)
             ownerHomeToDataRowMap[ownerHome] = dataRow
 
@@ -1002,7 +1161,7 @@
             home._txn, homeID=home._resourceID
         )
         for groupBindRow in groupBindRows:
-            bindMode, homeID, resourceID, name, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
+            bindMode, homeID, resourceID, externalID, name, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
             ownerAddressBookID = yield AddressBookObject.ownerAddressBookIDFromGroupID(home._txn, resourceID)
             ownerHome = yield home.ownerHomeWithChildID(ownerAddressBookID)
             if ownerHome not in ownerHomeToDataRowMap:
@@ -1023,32 +1182,17 @@
 
             # Create the actual objects merging in properties
             for ownerHome, dataRow in ownerHomeToDataRowMap.iteritems():
-                bindMode, homeID, resourceID, name, bindStatus, bindRevision, bindMessage = dataRow[:cls.bindColumnCount] #@UnusedVariable
-                additionalBind = dataRow[cls.bindColumnCount:cls.bindColumnCount + len(cls.additionalBindColumns())]
-                metadata = dataRow[cls.bindColumnCount + len(cls.additionalBindColumns()):]
+                bindData = dataRow[:cls.bindColumnCount]
+                additionalBindData = dataRow[cls.bindColumnCount:cls.bindColumnCount + len(cls.additionalBindColumns())]
+                metadataData = dataRow[cls.bindColumnCount + len(cls.additionalBindColumns()):]
+                propstore = propertyStores.get(ownerHome._addressbookPropertyStoreID, None)
 
-                child = cls(
-                    home=home,
-                    name=ownerHome.uid(),
-                    resourceID=ownerHome._resourceID,
-                    mode=bindMode,
-                    status=bindStatus,
-                    revision=bindRevision,
-                    message=bindMessage,
-                    ownerHome=ownerHome,
-                )
+                # Some adjustments for addressbook share model
+                bindData[cls.bindColumns().index(cls._bindSchema.RESOURCE_ID)] = ownerHome._resourceID
+                bindData[cls.bindColumns().index(cls._bindSchema.RESOURCE_NAME)] = ownerHome.uid()
 
-                for attr, value in zip(cls.additionalBindAttributes(), additionalBind):
-                    setattr(child, attr, value)
-                for attr, value in zip(cls.metadataAttributes(), metadata):
-                    setattr(child, attr, value)
+                child = yield cls.makeClass(home, bindData, additionalBindData, metadataData, propstore, ownerHome)
                 child._syncTokenRevision = revisions[child._resourceID]
-                propstore = propertyStores.get(ownerHome._addressbookPropertyStoreID, None)
-                # We have to re-adjust the property store object to account for possible shared
-                # collections as previously we loaded them all as if they were owned
-                if propstore:
-                    propstore._setDefaultUserUID(ownerHome.uid())
-                yield child._loadPropertyStore(propstore)
                 results.append(child)
 
         returnValue(results)
@@ -1111,7 +1255,7 @@
 
     @classmethod
     @inlineCallbacks
-    def _indirectObjectWithNameOrID(cls, home, name=None, resourceID=None, accepted=True):
+    def _indirectObjectWithNameOrID(cls, home, name=None, resourceID=None, externalID=None, accepted=True):
         # replaces objectWithName()
         """
         Synthesize and indirect child for matching name or id based on whether shared groups exist.
@@ -1123,56 +1267,17 @@
         @return: an L{CommonHomeChild} or C{None} if no such child
             exists.
         """
-        rows = None
-        ownerHome = None
 
-        # TODO: add queryCacher support
-
-        if rows is None:
-            # No cached copy
-            if name:
-                ownerHome = yield home._txn.addressbookHomeWithUID(name)
-                if ownerHome is None:
-                    returnValue(None)
-                resourceID = ownerHome.addressbook()._resourceID
-            rows = yield AddressBookObject._bindForHomeIDAndAddressBookID.on(
-                home._txn, homeID=home._resourceID, addressbookID=resourceID
-            )
-
-        if not rows:
+        dbData = yield cls._getDBDataIndirect(home, name, resourceID, externalID)
+        if dbData is None:
             returnValue(None)
+        bindData, additionalBindData, metadataData, ownerHome = dbData
 
-        groupID = None
-        overallBindStatus = _BIND_STATUS_INVITED
-        minBindRevision = None
-        for row in rows:
-            bindMode, homeID, resourceGroupID, name, bindStatus, bindRevision, bindMessage = row[:cls.bindColumnCount] #@UnusedVariable
-            if groupID is None:
-                groupID = resourceGroupID
-            minBindRevision = min(minBindRevision, bindRevision) if minBindRevision is not None else bindRevision
-            if bindStatus == _BIND_STATUS_ACCEPTED:
-                overallBindStatus = _BIND_STATUS_ACCEPTED
-
-        if accepted is not None and (overallBindStatus == _BIND_STATUS_ACCEPTED) != bool(accepted):
+        bindStatus = bindData[cls.bindColumns().index(cls._bindSchema.BIND_STATUS)]
+        if accepted is not None and (bindStatus == _BIND_STATUS_ACCEPTED) != bool(accepted):
             returnValue(None)
-        additionalBind = row[cls.bindColumnCount:cls.bindColumnCount + len(cls.additionalBindColumns())]
 
-        if ownerHome is None:
-            ownerAddressBookID = yield AddressBookObject.ownerAddressBookIDFromGroupID(home._txn, groupID)
-            ownerHome = yield home.ownerHomeWithChildID(ownerAddressBookID)
-
-        child = cls(
-            home=home,
-            name=ownerHome.uid(),
-            resourceID=resourceID,
-            mode=_BIND_MODE_INDIRECT,
-            status=overallBindStatus,
-            revision=minBindRevision,
-            message="",
-            ownerHome=ownerHome,
-            ownerName=ownerHome.uid()
-        )
-        yield child.initFromStore(additionalBind)
+        child = yield cls.makeClass(home, bindData, additionalBindData, metadataData, None, ownerHome)
         returnValue(child)
 
 
@@ -1266,7 +1371,7 @@
             groupBindRows = yield AddressBookObject._unacceptedBindForHomeIDAndAddressBookID.on(
                 self._txn, homeID=self._home._resourceID, addressbookID=self._resourceID
             )
-            returnValue([groupBindRow[2] for groupBindRow in groupBindRows])
+            returnValue([groupBindRow[self.bindColumns().index(self._bindSchema.RESOURCE_ID)] for groupBindRow in groupBindRows])
 
 
     @inlineCallbacks
@@ -1280,7 +1385,7 @@
             groupBindRows = yield AddressBookObject._acceptedBindForHomeIDAndAddressBookID.on(
                 self._txn, homeID=self._home._resourceID, addressbookID=self._resourceID
             )
-            returnValue([groupBindRow[2] for groupBindRow in groupBindRows])
+            returnValue([groupBindRow[self.bindColumns().index(self._bindSchema.RESOURCE_ID)] for groupBindRow in groupBindRows])
 
 
     @inlineCallbacks
@@ -1299,7 +1404,7 @@
             readWriteGroupIDs = set()
             readOnlyGroupIDs = set()
             for groupBindRow in groupBindRows:
-                bindMode, homeID, resourceID, name, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
+                bindMode, homeID, resourceID, externalID, name, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
                 if bindMode == _BIND_MODE_WRITE:
                     readWriteGroupIDs.add(resourceID)
                 else:
@@ -1360,7 +1465,7 @@
         readWriteGroupIDs = []
         readOnlyGroupIDs = []
         for groupBindRow in groupBindRows:
-            bindMode, homeID, resourceID, name, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
+            bindMode, homeID, resourceID, externalID, name, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
             if bindMode == _BIND_MODE_WRITE:
                 readWriteGroupIDs.append(resourceID)
             else:
@@ -1445,7 +1550,7 @@
 
 
     @inlineCallbacks
-    def shareWith(self, shareeHome, mode, status=None, summary=None):
+    def shareWith(self, shareeHome, mode, status=None, summary=None, shareName=None):
         """
         Share this (owned) L{AddressBookObject} with another home.
 
@@ -1473,11 +1578,12 @@
 
         @inlineCallbacks
         def doInsert(subt):
-            newName = self.newShareName()
+            newName = shareName if shareName is not None else self.newShareName()
             yield self._bindInsertQuery.on(
                 subt,
                 homeID=shareeHome._resourceID,
                 resourceID=self._resourceID,
+                externalID=None,
                 name=newName,
                 mode=mode,
                 bindStatus=status,
@@ -1514,14 +1620,14 @@
 
 
     @inlineCallbacks
-    def createShare(self, shareeUID, mode, summary=None):
+    def createShare(self, shareeUID, mode, summary=None, shareName=None):
         """
         Create a new shared resource. If the mode is direct, the share is created in accepted state,
         otherwise the share is created in invited state.
         """
 
         if self._kind == _ABO_KIND_GROUP:
-            shareeView = yield super(AddressBookObjectSharingMixIn, self).createShare(shareeUID, mode, summary)
+            shareeView = yield super(AddressBookObjectSharingMixIn, self).createShare(shareeUID, mode, summary, shareName)
             returnValue(shareeView)
         else:
             returnValue(None)
@@ -1617,8 +1723,9 @@
                         # update revision in all remaining bind table rows for this address book
                         yield shareeView.addressbook().notifyPropertyChanged()
                         for groupBindRow in groupBindRows:
-                            if groupBindRow[2] != shareeView._resourceID:
-                                groupObject = yield shareeView.addressbook().objectResourceWithID(groupBindRow[2])
+                            resid = groupBindRow[self.bindColumns().index(self._bindSchema.RESOURCE_ID)]
+                            if resid != shareeView._resourceID:
+                                groupObject = yield shareeView.addressbook().objectResourceWithID(resid)
                                 yield groupObject._initBindRevision()
                         if shareeView.addressbook().fullyShared():
                             yield shareeView.addressbook()._initBindRevision()
@@ -1670,7 +1777,9 @@
                 yield addressbookAsShared.notifyPropertyChanged()
                 #update revision in all remaining bind table rows for this address book
                 for groupBindRow in groupBindRows:
-                    groupObject = yield addressbookAsShared.objectResourceWithID(groupBindRow[2])
+                    groupObject = yield addressbookAsShared.objectResourceWithID(
+                        groupBindRow[self.bindColumns().index(self._bindSchema.RESOURCE_ID)]
+                    )
                     yield groupObject._initBindRevision()
                 addressbookAsShared._objects = {}
                 addressbookAsShared._objectNames = None
@@ -1750,25 +1859,147 @@
     _objectSchema = schema.ADDRESSBOOK_OBJECT
     _bindSchema = schema.SHARED_GROUP_BIND
 
+    _componentClass = VCard
+
     # used by CommonHomeChild._childrenAndMetadataForHomeID() only
     # _homeChildSchema = schema.ADDRESSBOOK_OBJECT
     # _homeChildMetaDataSchema = schema.ADDRESSBOOK_OBJECT
 
 
+    @classmethod
+    @inlineCallbacks
+    def makeClass(cls, parent, objectData, groupBindData=None, propstore=None):
+        """
+        Given the various database rows, build the actual class.
+
+        @param parent: the parent collection object
+        @type parent: L{AddressBook}
+        @param objectData: the standard set of object columns
+        @type objectData: C{list}
+        @param groupBindData: additional group bind data
+        @type groupBindData: C{list}
+        @param propstore: a property store to use, or C{None} to load it automatically
+        @type propstore: L{PropertyStore}
+
+        @return: the constructed child class
+        @rtype: L{CommonHomeChild}
+        """
+
+        c = cls._externalClass if parent.external() else cls
+        child = c(
+            parent,
+            objectData[cls._allColumns().index(cls._objectSchema.RESOURCE_NAME)],
+            objectData[cls._allColumns().index(cls._objectSchema.UID)],
+        )
+
+        for attr, value in zip(child._rowAttributes(), objectData):
+            setattr(child, attr, value)
+
+        yield child._loadPropertyStore(propstore)
+
+        if groupBindData:
+            bindMode, homeID, resourceID, externalID, bindName, bindStatus, bindRevision, bindMessage = groupBindData[:AddressBookObject.bindColumnCount] #@UnusedVariable
+            child._bindMode = bindMode
+            child._bindStatus = bindStatus
+            child._bindMessage = bindMessage
+            child._bindName = bindName
+            child._bindRevision = bindRevision
+        else:
+            invites = yield child.sharingInvites()
+            if len(invites):
+                child._bindMessage = "shared"
+
+        returnValue(child)
+
+
+    @classmethod
+    @inlineCallbacks
+    def _getDBData(cls, parent, name, uid, resourceID):
+        """
+        Given a set of identifying information, load the data rows for the object. Only one of
+        L{name}, L{uid} or L{resourceID} is specified - others are C{None}.
+
+        @param parent: the parent collection object
+        @type parent: L{AddressBook}
+        @param name: the resource name
+        @type name: C{str}
+        @param uid: the UID of the data
+        @type uid: C{str}
+        @param resourceID: the resource ID
+        @type resourceID: C{int}
+        """
+
+        row = None
+        groupBindRow = None
+
+        if parent.owned() or parent.fullyShared():  # owned or fully shared
+            row = yield super(AddressBookObject, cls)._getDBData(parent, name, uid, resourceID)
+
+            # Might be special group
+            if row is None and parent.fullyShared():
+                if name:
+                    if name == parent._groupForSharedAddressBookName():
+                        row = parent._groupForSharedAddressBookRow()
+                elif uid:
+                    if uid == (yield parent._groupForSharedAddressBookUID()):
+                        row = parent._groupForSharedAddressBookRow()
+                elif resourceID:
+                    if resourceID == parent.id():
+                        rows = parent._groupForSharedAddressBookRow()
+
+        else:
+            acceptedGroupIDs = yield parent.acceptedGroupIDs()
+            allowedObjectIDs = yield parent.expandGroupIDs(parent._txn, acceptedGroupIDs)
+            rows = None
+            if name:
+                if allowedObjectIDs:
+                    rows = (yield cls._allColumnsWithResourceIDsAndName(allowedObjectIDs).on(
+                        parent._txn,
+                        name=name,
+                        resourceIDs=allowedObjectIDs,
+                    ))
+            elif uid:
+                if allowedObjectIDs:
+                    rows = (yield cls._allColumnsWithResourceIDsAndUID(allowedObjectIDs).on(
+                        parent._txn,
+                        uid=uid,
+                        resourceIDs=allowedObjectIDs,
+                    ))
+            elif resourceID:
+                # Also allow invited groups
+                if resourceID in allowedObjectIDs or resourceID in (yield parent.unacceptedGroupIDs()):
+                    rows = (yield cls._allColumnsWithResourceID.on(
+                        parent._txn,
+                        resourceID=resourceID,
+                    ))
+            if rows:
+                row = rows[0]
+
+        if row is not None:
+            if row[cls._allColumns().index(cls._objectSchema.KIND)] == _ABO_KIND_GROUP:
+
+                resourceID = row[cls._allColumns().index(cls._objectSchema.RESOURCE_ID)]
+                groupBindRows = yield AddressBookObject._bindForResourceIDAndHomeID.on(
+                    parent._txn, resourceID=resourceID, homeID=parent._home._resourceID
+                )
+
+                if groupBindRows:
+                    groupBindRow = groupBindRows[0]
+
+        returnValue((row, groupBindRow,))
+
+
     def __init__(self, addressbook, name, uid, resourceID=None, options=None):
 
         self._kind = None
         self._ownerAddressBookResourceID = None
-        # _self._component is the cached, current component
-        # super._objectText now contains the text as read of the database only,
-        #     not including group member text
-        self._component = None
         self._bindMode = None
         self._bindStatus = None
         self._bindMessage = None
         self._bindName = None
         self._bindRevision = None
         super(AddressBookObject, self).__init__(addressbook, name, uid, resourceID, options)
+        self._externalID = None
         self._options = {} if options is None else options
 
 
@@ -1793,6 +2024,15 @@
         return self._resourceID == self.addressbook()._resourceID
 
 
+    def external(self):
+        """
+        Is this an external object.
+
+        @return: a string.
+        """
+        return self.addressbook().external()
+
+
     @inlineCallbacks
     def remove(self):
 
@@ -1882,7 +2122,8 @@
         yield super(AddressBookObject, self).remove()
         self._kind = None
         self._ownerAddressBookResourceID = None
-        self._component = None
+        self._objectText = None
+        self._cachedComponent = None
 
 
     @inlineCallbacks
@@ -1911,7 +2152,7 @@
         """
         obj = cls._objectSchema
         return Select(
-            cls._allColumns, From=obj,
+            cls._allColumns(), From=obj,
             Where=(column == Parameter(paramName)).And(
                 obj.RESOURCE_ID.In(Parameter("resourceIDs", len(resourceIDs)))),
         )
@@ -1931,7 +2172,7 @@
     def _allColumnsWithResourceID(cls): #@NoSelf
         obj = cls._objectSchema
         return Select(
-            cls._allColumns, From=obj,
+            cls._allColumns(), From=obj,
             Where=obj.RESOURCE_ID == Parameter("resourceID"),)
 
 
@@ -1954,7 +2195,7 @@
         )
         if groupBindRows:
             groupBindRow = groupBindRows[0]
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
+            bindMode, homeID, resourceID, externalID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
 
             if accepted is not None and (bindStatus == _BIND_STATUS_ACCEPTED) != bool(accepted):
                 returnValue(None)
@@ -1967,93 +2208,20 @@
         returnValue(None)
 
 
+    @classmethod
     @inlineCallbacks
-    def initFromStore(self):
-        """
-        Initialise this object from the store. We read in and cache all the
-        extra metadata from the DB to avoid having to do DB queries for those
-        individually later. Either the name or uid is present, so we have to
-        tweak the query accordingly.
+    def objectWith(cls, parent, name=None, uid=None, resourceID=None):
 
-        @return: L{self} if object exists in the DB, else C{None}
-        """
-        abo = None
-        if self.owned() or self.addressbook().fullyShared():  # owned or fully shared
-            abo = yield super(AddressBookObject, self).initFromStore()
+        row, groupBindRow = yield cls._getDBData(parent, name, uid, resourceID)
 
-            # Might be special group
-            if abo is None and self.addressbook().fullyShared():
-                rows = None
-                if self._name:
-                    if self._name == self.addressbook()._groupForSharedAddressBookName():
-                        rows = [self.addressbook()._groupForSharedAddressBookRow()]
-                elif self._uid:
-                    if self._uid == (yield self.addressbook()._groupForSharedAddressBookUID()):
-                        rows = [self.addressbook()._groupForSharedAddressBookRow()]
-                elif self._resourceID:
-                    if self.isGroupForSharedAddressBook():
-                        rows = [self.addressbook()._groupForSharedAddressBookRow()]
-
-                if rows:
-                    self._initFromRow(tuple(rows[0]))
-                    yield self._loadPropertyStore()
-                    abo = self
-
+        if row:
+            child = yield cls.makeClass(parent, row, groupBindRow)
+            returnValue(child)
         else:
-            acceptedGroupIDs = yield self.addressbook().acceptedGroupIDs()
-            allowedObjectIDs = yield self.addressbook().expandGroupIDs(self._txn, acceptedGroupIDs)
-            rows = None
-            if self._name:
-                if allowedObjectIDs:
-                    rows = (yield self._allColumnsWithResourceIDsAndName(allowedObjectIDs).on(
-                        self._txn, name=self._name,
-                        resourceIDs=allowedObjectIDs,
-                    ))
-            elif self._uid:
-                if allowedObjectIDs:
-                    rows = (yield self._allColumnsWithResourceIDsAndUID(allowedObjectIDs).on(
-                        self._txn, uid=self._uid,
-                        resourceIDs=allowedObjectIDs,
-                    ))
-            elif self._resourceID:
-                if (self._resourceID in allowedObjectIDs or
-                        self._resourceID in (yield self.addressbook().unacceptedGroupIDs())): # allow invited groups
-                    rows = (yield self._allColumnsWithResourceID.on(
-                        self._txn, resourceID=self._resourceID,
-                    ))
-            if rows:
-                self._initFromRow(tuple(rows[0]))
-                yield self._loadPropertyStore()
-                abo = self
-
-        if abo is not None:
-            if self._kind == _ABO_KIND_GROUP:
-
-                groupBindRows = yield AddressBookObject._bindForResourceIDAndHomeID.on(
-                    self._txn, resourceID=self._resourceID, homeID=self._home._resourceID
-                )
-
-                if groupBindRows:
-                    groupBindRow = groupBindRows[0]
-                    bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
-                    self._bindMode = bindMode
-                    self._bindStatus = bindStatus
-                    self._bindMessage = bindMessage
-                    self._bindName = bindName
-                    self._bindRevision = bindRevision
-                else:
-                    invites = yield self.sharingInvites()
-                    if len(invites):
-                        self._bindMessage = "shared"
-
-            yield self._loadPropertyStore()
-
-            returnValue(self)
-        else:
             returnValue(None)
 
 
-    @classproperty
+    @classmethod
     def _allColumns(cls): #@NoSelf
         """
         Full set of columns in the object table that need to be loaded to
@@ -2069,24 +2237,23 @@
             obj.MD5,
             Len(obj.TEXT),
             obj.CREATED,
-            obj.MODIFIED,
+            obj.MODIFIED
         ]
 
 
-    def _initFromRow(self, row):
-        """
-        Given a select result using the columns from L{_allColumns}, initialize
-        the object resource state.
-        """
-        (self._ownerAddressBookResourceID,
-         self._resourceID,
-         self._name,
-         self._uid,
-         self._kind,
-         self._md5,
-         self._size,
-         self._created,
-         self._modified,) = tuple(row)
+    @classmethod
+    def _rowAttributes(cls): #@NoSelf
+        return (
+            "_ownerAddressBookResourceID",
+            "_resourceID",
+            "_name",
+            "_uid",
+            "_kind",
+            "_md5",
+            "_size",
+            "_created",
+            "_modified",
+         )
 
 
     @classmethod
@@ -2109,7 +2276,7 @@
         else:
             acceptedGroupIDs = yield addressbook.acceptedGroupIDs()
             allowedObjectIDs = yield addressbook.expandGroupIDs(addressbook._txn, acceptedGroupIDs)
-            rows = yield cls._columnsWithResourceIDsQuery(cls._allColumns, allowedObjectIDs).on(
+            rows = yield cls._columnsWithResourceIDsQuery(cls._allColumns(), allowedObjectIDs).on(
                 addressbook._txn, resourceIDs=allowedObjectIDs
             )
         returnValue(rows)
@@ -2118,7 +2285,7 @@
     @classmethod
     def _allColumnsWithResourceIDsAndNamesQuery(cls, resourceIDs, names):
         obj = cls._objectSchema
-        return Select(cls._allColumns, From=obj,
+        return Select(cls._allColumns(), From=obj,
                       Where=(obj.RESOURCE_ID.In(Parameter("resourceIDs", len(resourceIDs))).And(
                           obj.RESOURCE_NAME.In(Parameter("names", len(names))))),)
 
@@ -2234,6 +2401,13 @@
     @inlineCallbacks
     def setComponent(self, component, inserting=False):
 
+        if isinstance(component, str) or isinstance(component, unicode):
+            component = self._componentClass.fromString(component)
+            try:
+                component = self._componentClass.fromString(component)
+            except InvalidVCardDataError as e:
+                raise InvalidComponentForStoreError(str(e))
+
         self._componentChanged = False
 
         if "coaddedUIDs" not in self._options:
@@ -2387,7 +2561,7 @@
             self._objectText = componentText
 
         self._size = len(self._objectText)
-        self._component = component
+        self._cachedComponent = component
         self._md5 = hashlib.md5(componentText).hexdigest()
         self._componentChanged = originalComponentText != componentText
 
@@ -2502,7 +2676,7 @@
         only allowed in good data.
         """
 
-        if self._component is None:
+        if self._cachedComponent is None:
 
             if self.isGroupForSharedAddressBook():
                 component = yield self.addressbook()._groupForSharedAddressBookComponent()
@@ -2562,9 +2736,9 @@
                     component.addProperty(Property("X-ADDRESSBOOKSERVER-KIND", "group"))
                     component.addProperty(Property("UID", self._uid))
 
-            self._component = component
+            self._cachedComponent = component
 
-        returnValue(self._component)
+        returnValue(self._cachedComponent)
 
 
     def moveValidation(self, destination, name):
@@ -2679,4 +2853,10 @@
         )
 
 
+# Hook-up class relationships at the end after they have all been defined
+from txdav.carddav.datastore.sql_external import AddressBookHomeExternal, AddressBookExternal, AddressBookObjectExternal
+AddressBookHome._externalClass = AddressBookHomeExternal
+AddressBookHome._childClass = AddressBook
+AddressBook._externalClass = AddressBookExternal
 AddressBook._objectResourceClass = AddressBookObject
+AddressBookObject._externalClass = AddressBookObjectExternal

Copied: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/sql_external.py (from rev 12321, CalendarServer/trunk/txdav/carddav/datastore/sql_external.py)
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/sql_external.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/sql_external.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -0,0 +1,83 @@
+# -*- test-case-name: txdav.caldav.datastore.test.test_sql -*-
+##
+# Copyright (c) 2013-2014 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+"""
+SQL backend for CardDAV storage when resources are external.
+"""
+
+from twisted.internet.defer import succeed
+
+from twext.python.log import Logger
+
+from txdav.carddav.datastore.sql import AddressBookHome, AddressBook, \
+    AddressBookObject
+from txdav.common.datastore.sql_external import CommonHomeExternal, CommonHomeChildExternal, \
+    CommonObjectResourceExternal
+
+log = Logger()
+
+class AddressBookHomeExternal(CommonHomeExternal, AddressBookHome):
+
+    def __init__(self, transaction, ownerUID, resourceID):
+
+        AddressBookHome.__init__(self, transaction, ownerUID)
+        CommonHomeExternal.__init__(self, transaction, ownerUID, resourceID)
+
+
+    def hasAddressBookResourceUIDSomewhereElse(self, uid, ok_object, mode):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def getAddressBookResourcesForUID(self, uid):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def createdHome(self):
+        """
+        No children - make this a no-op.
+        """
+        return succeed(None)
+
+
+    def addressbook(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+
+class AddressBookExternal(CommonHomeChildExternal, AddressBook):
+    """
+    SQL-based implementation of L{IAddressBook}.
+    """
+    pass
+
+
+
+class AddressBookObjectExternal(CommonObjectResourceExternal, AddressBookObject):
+    """
+    SQL-based implementation of L{IAddressBookObject}.
+    """
+    pass
+
+AddressBookExternal._objectResourceClass = AddressBookObjectExternal

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.carddav.datastore.test -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/common.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/common.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.carddav.datastore,txdav.carddav.datastore.test.test_sql.AddressBookSQLStorageTests -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_file.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_index_file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_index_file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_index_file.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -189,12 +189,12 @@
         self.db.deleteResource("data3.vcf")
 
         tests = (
-            (0, (["data1.vcf", "data2.vcf", ], [],)),
-            (1, (["data2.vcf", ], ["data3.vcf", ],)),
-            (2, ([], ["data3.vcf", ],)),
-            (3, ([], ["data3.vcf", ],)),
-            (4, ([], [],)),
-            (5, ([], [],)),
+            (0, (["data1.vcf", "data2.vcf", ], [], [],)),
+            (1, (["data2.vcf", ], ["data3.vcf", ], [],)),
+            (2, ([], ["data3.vcf", ], [],)),
+            (3, ([], ["data3.vcf", ], [],)),
+            (4, ([], [], [],)),
+            (5, ([], [], [],)),
         )
 
         for revision, results in tests:

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_sql.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@
 from txdav.common.icommondatastore import NoSuchObjectResourceError
 from txdav.common.datastore.sql import EADDRESSBOOKTYPE, CommonObjectResource
 from txdav.common.datastore.sql_tables import  _ABO_KIND_PERSON, _ABO_KIND_GROUP, schema
-from txdav.common.datastore.test.util import buildStore
+from txdav.common.datastore.test.util import buildStore, cleanStore
 from txdav.carddav.datastore.sql import AddressBook
 
 from txdav.xml.rfc2518 import GETContentLanguage, ResourceType
@@ -56,7 +56,22 @@
     @inlineCallbacks
     def setUp(self):
         yield super(AddressBookSQLStorageTests, self).setUp()
-        self._sqlStore = yield buildStore(self, self.notifierFactory)
+        self._sqlStore = yield buildStore(
+            self,
+            self.notifierFactory,
+            homes=(
+                "home1",
+                "home2",
+                "home3",
+                "home_bad",
+                "home_empty",
+                "homeNew",
+                "new-home",
+                "uid1",
+                "uid2",
+                "xyzzy",
+            )
+        )
         yield self.populate()
 
 
@@ -289,7 +304,7 @@
         Test that two concurrent attempts to PUT different address book object resources to the
         same address book home does not cause a deadlock.
         """
-        addressbookStore = yield buildStore(self, self.notifierFactory)
+        addressbookStore = self._sqlStore
 
         # Provision the home and addressbook now
         txn = addressbookStore.newTransaction()
@@ -395,7 +410,7 @@
         """
         Test that kind property UID is stored correctly in database
         """
-        addressbookStore = yield buildStore(self, self.notifierFactory)
+        addressbookStore = self._sqlStore
 
         # Provision the home and addressbook, one user and one group
         txn = addressbookStore.newTransaction()
@@ -441,7 +456,7 @@
         """
         Test that kind property vCard is stored correctly in database
         """
-        addressbookStore = yield buildStore(self, self.notifierFactory)
+        addressbookStore = self._sqlStore
 
         # Provision the home and addressbook, one user and one group
         txn = addressbookStore.newTransaction()
@@ -532,7 +547,8 @@
         """
         Test that kind property vCard is stored correctly in database
         """
-        addressbookStore = yield buildStore(self, self.notifierFactory)
+        addressbookStore = self._sqlStore
+        cleanStore(self, addressbookStore)
 
         # Provision the home and addressbook, one user and one group
         txn = addressbookStore.newTransaction()

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_sql_sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_sql_sharing.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/test/test_sql_sharing.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -1134,23 +1134,27 @@
         otherAB = yield self.addressbookUnderTest(home="user02", name="user01")
         self.assertNotEqual(otherAB._bindRevision, 0)
 
-        changed, deleted = yield otherAB.resourceNamesSinceRevision(0)
+        changed, deleted, invalid = yield otherAB.resourceNamesSinceRevision(0)
         self.assertNotEqual(len(changed), 0)
         self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
 
-        changed, deleted = yield otherAB.resourceNamesSinceRevision(otherAB._bindRevision)
+        changed, deleted, invalid = yield otherAB.resourceNamesSinceRevision(otherAB._bindRevision)
         self.assertEqual(len(changed), 0)
         self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
 
         otherHome = yield self.addressbookHomeUnderTest(name="user02")
         for depth in ("1", "infinity",):
-            changed, deleted = yield otherHome.resourceNamesSinceRevision(0, depth)
+            changed, deleted, invalid = yield otherHome.resourceNamesSinceRevision(0, depth)
             self.assertNotEqual(len(changed), 0)
             self.assertEqual(len(deleted), 0)
+            self.assertEqual(len(invalid), 0)
 
-            changed, deleted = yield otherHome.resourceNamesSinceRevision(otherAB._bindRevision, depth)
+            changed, deleted, invalid = yield otherHome.resourceNamesSinceRevision(otherAB._bindRevision, depth)
             self.assertEqual(len(changed), 0)
             self.assertEqual(len(deleted), 0)
+            self.assertEqual(len(invalid), 0)
 
 
     @inlineCallbacks
@@ -1166,13 +1170,15 @@
         otherAB = yield self.addressbookUnderTest(home="user02", name="user01")
         self.assertNotEqual(otherAB._bindRevision, 0)
 
-        changed, deleted = yield otherAB.resourceNamesSinceRevision(0)
+        changed, deleted, invalid = yield otherAB.resourceNamesSinceRevision(0)
         self.assertEqual(set(changed), set(['card1.vcf', 'card2.vcf', 'group1.vcf']))
         self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
 
-        changed, deleted = yield otherAB.resourceNamesSinceRevision(otherAB._bindRevision)
+        changed, deleted, invalid = yield otherAB.resourceNamesSinceRevision(otherAB._bindRevision)
         self.assertEqual(len(changed), 0)
         self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
 
         for depth, result in (
             ("1", ['addressbook/',
@@ -1184,13 +1190,15 @@
                              'user01/card2.vcf',
                              'user01/group1.vcf']
              )):
-            changed, deleted = yield otherAB.viewerHome().resourceNamesSinceRevision(0, depth)
+            changed, deleted, invalid = yield otherAB.viewerHome().resourceNamesSinceRevision(0, depth)
             self.assertEqual(set(changed), set(result))
             self.assertEqual(len(deleted), 0)
+            self.assertEqual(len(invalid), 0)
 
-            changed, deleted = yield otherAB.viewerHome().resourceNamesSinceRevision(otherAB._bindRevision, depth)
+            changed, deleted, invalid = yield otherAB.viewerHome().resourceNamesSinceRevision(otherAB._bindRevision, depth)
             self.assertEqual(len(changed), 0)
             self.assertEqual(len(deleted), 0)
+            self.assertEqual(len(invalid), 0)
 
 
     @inlineCallbacks

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/datastore/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.carddav.datastore.test.test_sql -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/iaddressbookstore.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/iaddressbookstore.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/iaddressbookstore.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.carddav.datastore,txdav.carddav.datastore.test.test_sql.AddressBookSQLStorageTests -*-
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/carddav/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/clean