[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/cleanrevisions/txdav/common/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/common/datastore/common.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/common.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/common.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav -*-
 ##
-# 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/common/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/file.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/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.
@@ -852,7 +852,8 @@
     def resourceNamesSinceToken(self, token, depth):
         deleted = []
         changed = []
-        return succeed((changed, deleted))
+        invalid = []
+        return succeed((changed, deleted, invalid))
 
 
     # @cached

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/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,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,9 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-from collections import namedtuple
-from txdav.xml import element
-from txdav.base.propertystore.base import PropertyName
 
 """
 SQL data store.
@@ -57,32 +54,40 @@
 
 from txdav.base.datastore.util import QueryCacher
 from txdav.base.datastore.util import normalizeUUIDOrNot
+from txdav.base.propertystore.base import PropertyName
 from txdav.base.propertystore.none import PropertyStore as NonePropertyStore
 from txdav.base.propertystore.sql import PropertyStore
 from txdav.caldav.icalendarstore import ICalendarTransaction, ICalendarStore
 from txdav.carddav.iaddressbookstore import IAddressBookTransaction
 from txdav.common.datastore.common import HomeChildBase
+from txdav.common.datastore.podding.conduit import PoddingConduit
 from txdav.common.datastore.sql_tables import _BIND_MODE_OWN, \
     _BIND_STATUS_ACCEPTED, _BIND_STATUS_DECLINED, _BIND_STATUS_INVALID, \
     _BIND_STATUS_INVITED, _BIND_MODE_DIRECT, _BIND_STATUS_DELETED, \
-    _BIND_MODE_INDIRECT
+    _BIND_MODE_INDIRECT, _HOME_STATUS_NORMAL, _HOME_STATUS_EXTERNAL
 from txdav.common.datastore.sql_tables import schema, splitSQLString
-from txdav.common.icommondatastore import ConcurrentModification
+from txdav.common.icommondatastore import ConcurrentModification, \
+    RecordNotAllowedError, ExternalShareFailed, ShareNotAllowed, \
+    IndexedSearchException
 from txdav.common.icommondatastore import HomeChildNameNotAllowedError, \
     HomeChildNameAlreadyExistsError, NoSuchHomeChildError, \
     ObjectResourceNameNotAllowedError, ObjectResourceNameAlreadyExistsError, \
     NoSuchObjectResourceError, AllRetriesFailed, InvalidSubscriptionValues, \
     InvalidIMIPTokenValues, TooManyObjectResourcesError, \
     SyncTokenValidException
-from txdav.common.idirectoryservice import IStoreDirectoryService
+from txdav.common.idirectoryservice import IStoreDirectoryService, \
+    DirectoryRecordNotFoundError
 from txdav.common.inotifications import INotificationCollection, \
     INotificationObject
 from txdav.idav import ChangeCategory
+from txdav.xml import element
 
 from uuid import uuid4, UUID
 
 from zope.interface import implements, directlyProvides
 
+from collections import namedtuple
+import itertools
 import json
 import sys
 import time
@@ -189,6 +194,8 @@
         else:
             self.queryCacher = None
 
+        self.conduit = PoddingConduit(self)
+
         # Always import these here to trigger proper "registration" of the calendar and address book
         # home classes
         __import__("txdav.caldav.datastore.sql")
@@ -210,16 +217,18 @@
 
 
     @inlineCallbacks
-    def _withEachHomeDo(self, homeTable, homeFromTxn, action, batchSize): #@UnusedVariable
+    def _withEachHomeDo(self, homeTable, homeFromTxn, action, batchSize, processExternal=False):
         """
         Implementation of L{ICalendarStore.withEachCalendarHomeDo} and
         L{IAddressbookStore.withEachAddressbookHomeDo}.
         """
         txn = yield self.newTransaction()
         try:
-            allUIDs = yield (Select([homeTable.OWNER_UID], From=homeTable)
-                             .on(txn))
+            allUIDs = yield (Select([homeTable.OWNER_UID], From=homeTable).on(txn))
             for [uid] in allUIDs:
+                home = yield homeFromTxn(txn, uid)
+                if not processExternal and home.external():
+                    continue
                 yield action(txn, (yield homeFromTxn(txn, uid)))
         except:
             a, b, c = sys.exc_info()
@@ -229,25 +238,25 @@
             yield txn.commit()
 
 
-    def withEachCalendarHomeDo(self, action, batchSize=None):
+    def withEachCalendarHomeDo(self, action, batchSize=None, processExternal=False):
         """
         Implementation of L{ICalendarStore.withEachCalendarHomeDo}.
         """
         return self._withEachHomeDo(
             schema.CALENDAR_HOME,
             lambda txn, uid: txn.calendarHomeWithUID(uid),
-            action, batchSize
+            action, batchSize, processExternal
         )
 
 
-    def withEachAddressbookHomeDo(self, action, batchSize=None):
+    def withEachAddressbookHomeDo(self, action, batchSize=None, processExternal=False):
         """
         Implementation of L{IAddressbookStore.withEachAddressbookHomeDo}.
         """
         return self._withEachHomeDo(
             schema.ADDRESSBOOK_HOME,
             lambda txn, uid: txn.addressbookHomeWithUID(uid),
-            action, batchSize
+            action, batchSize, processExternal
         )
 
 
@@ -445,7 +454,7 @@
                 if self.delayedLog:
                     self.delayedLog.cancel()
                     self.delayedLog = None
-                self.txn.abort()
+                self.txn.timeout()
 
         if self.timeoutSeconds:
             self.delayedTimeout = self.callLater(self.timeoutSeconds, _forceAbort)
@@ -473,7 +482,7 @@
         self._label = label
         self._migrating = migrating
         self._primaryHomeType = None
-        self._disableCache = disableCache
+        self._disableCache = disableCache or not store.queryCachingEnabled()
         if disableCache:
             self._queryCacher = None
         else:
@@ -503,6 +512,7 @@
         self.statementCount = 0
         self.iudCount = 0
         self.currentStatement = None
+        self.timedout = False
 
         self.logItems = {}
 
@@ -1074,6 +1084,14 @@
         return self._sqlTxn.abort()
 
 
+    def timeout(self):
+        """
+        Abort the transaction due to time out.
+        """
+        self.timedout = True
+        return self.abort()
+
+
     def statsReport(self):
         """
         Print the stats report and record log items
@@ -1467,10 +1485,108 @@
         if shareeView is not None:
             yield shareeView.declineShare()
 
-        returnValue(shareeView)
+        returnValue(shareeView is not None)
 
 
+    #
+    # External (cross-pod) sharing - entry point is the sharee's home collection.
+    #
+    @inlineCallbacks
+    def processExternalInvite(self, ownerUID, ownerRID, ownerName, shareUID, bindMode, summary, copy_invite_properties, supported_components=None):
+        """
+        External invite received.
+        """
 
+        # Get the owner home - create external one if not present
+        ownerHome = yield self._txn.homeWithUID(self._homeType, ownerUID, create=True)
+        if ownerHome is None or not ownerHome.external():
+            raise ExternalShareFailed("Invalid owner UID: {}".format(ownerUID))
+
+        # Try to find owner calendar via its external id
+        ownerView = yield ownerHome.childWithExternalID(ownerRID)
+        if ownerView is None:
+            try:
+                ownerView = yield ownerHome.createChildWithName(ownerName, externalID=ownerRID)
+            except HomeChildNameAlreadyExistsError:
+                # This is odd - it means we possibly have a left over sharer collection which the sharer likely removed
+                # and re-created with the same name but now it has a different externalID and is not found by the initial
+                # query. What we do is check to see whether any shares still reference the old ID - if they do we are hosed.
+                # If not, we can remove the old item and create a new one.
+                oldOwnerView = yield ownerHome.childWithName(ownerName)
+                invites = yield oldOwnerView.sharingInvites()
+                if len(invites) != 0:
+                    log.error("External invite collection name is present with a different externalID and still has shares")
+                    raise
+                log.error("External invite collection name is present with a different externalID - trying to fix")
+                yield ownerHome.removeExternalChild(oldOwnerView)
+                ownerView = yield ownerHome.createChildWithName(ownerName, externalID=ownerRID)
+
+            if supported_components is not None and hasattr(ownerView, "setSupportedComponents"):
+                yield ownerView.setSupportedComponents(supported_components)
+
+        # Now carry out the share operation
+        if bindMode == _BIND_MODE_DIRECT:
+            shareeView = yield ownerView.directShareWithUser(self.uid(), shareName=shareUID)
+        else:
+            shareeView = yield ownerView.inviteUserToShare(self.uid(), bindMode, summary, shareName=shareUID)
+
+        shareeView.setInviteCopyProperties(copy_invite_properties)
+
+
+    @inlineCallbacks
+    def processExternalUninvite(self, ownerUID, ownerRID, shareUID):
+        """
+        External invite received.
+        """
+
+        # Get the owner home
+        ownerHome = yield self._txn.homeWithUID(self._homeType, ownerUID)
+        if ownerHome is None or not ownerHome.external():
+            raise ExternalShareFailed("Invalid owner UID: {}".format(ownerUID))
+
+        # Try to find owner calendar via its external id
+        ownerView = yield ownerHome.childWithExternalID(ownerRID)
+        if ownerView is None:
+            raise ExternalShareFailed("Invalid share ID: {}".format(shareUID))
+
+        # Now carry out the share operation
+        yield ownerView.uninviteUserFromShare(self.uid())
+
+        # See if there are any references to the external share - if not remove it
+        invites = yield ownerView.sharingInvites()
+        if len(invites) == 0:
+            yield ownerHome.removeExternalChild(ownerView)
+
+
+    @inlineCallbacks
+    def processExternalReply(self, ownerUID, shareeUID, shareUID, bindStatus, summary=None):
+        """
+        External invite received.
+        """
+
+        # Make sure the shareeUID and shareUID match
+
+        # Get the owner home - create external one if not present
+        shareeHome = yield self._txn.homeWithUID(self._homeType, shareeUID)
+        if shareeHome is None or not shareeHome.external():
+            raise ExternalShareFailed("Invalid sharee UID: {}".format(shareeUID))
+
+        # Try to find owner calendar via its external id
+        shareeView = yield shareeHome.anyObjectWithShareUID(shareUID)
+        if shareeView is None:
+            raise ExternalShareFailed("Invalid share UID: {}".format(shareUID))
+
+        # Now carry out the share operation
+        if bindStatus == _BIND_STATUS_ACCEPTED:
+            yield shareeHome.acceptShare(shareUID, summary)
+        elif bindStatus == _BIND_STATUS_DECLINED:
+            if shareeView.direct():
+                yield shareeView.deleteShare()
+            else:
+                yield shareeHome.declineShare(shareUID)
+
+
+
 class CommonHome(SharingHomeMixIn):
     log = Logger()
 
@@ -1478,6 +1594,7 @@
     _homeType = None
     _homeTable = None
     _homeMetaDataTable = None
+    _externalClass = None
     _childClass = None
     _childTable = None
     _notifierPrefix = None
@@ -1487,10 +1604,30 @@
 
     _cacher = None  # Initialize in derived classes
 
+    @classmethod
+    @inlineCallbacks
+    def makeClass(cls, transaction, ownerUID, no_cache=False):
+        """
+        Build the actual home class taking into account the possibility that we might need to
+        switch in the external version of the class.
+
+        @param transaction: transaction
+        @type transaction: L{CommonStoreTransaction}
+        @param ownerUID: owner UID of home to load
+        @type ownerUID: C{str}
+        @param no_cache: should cached query be used
+        @type no_cache: C{bool}
+        """
+        home = cls(transaction, ownerUID)
+        actualHome = yield home.initFromStore(no_cache)
+        returnValue(actualHome)
+
+
     def __init__(self, transaction, ownerUID):
         self._txn = transaction
         self._ownerUID = ownerUID
         self._resourceID = None
+        self._status = _HOME_STATUS_NORMAL
         self._dataVersion = None
         self._childrenLoaded = False
         self._children = {}
@@ -1554,6 +1691,7 @@
         return (
             cls._homeSchema.RESOURCE_ID,
             cls._homeSchema.OWNER_UID,
+            cls._homeSchema.STATUS,
         )
 
 
@@ -1568,6 +1706,7 @@
         return (
             "_resourceID",
             "_ownerUID",
+            "_status",
         )
 
 
@@ -1612,39 +1751,57 @@
         """
         result = yield self._cacher.get(self._ownerUID)
         if result is None:
-            result = yield self._homeColumnsFromOwnerQuery.on(
-                self._txn, ownerUID=self._ownerUID)
-            if result and not no_cache:
-                yield self._cacher.set(self._ownerUID, result)
+            result = yield self._homeColumnsFromOwnerQuery.on(self._txn, ownerUID=self._ownerUID)
+            if result:
+                result = result[0]
+                if not no_cache:
+                    yield self._cacher.set(self._ownerUID, result)
 
         if result:
-            for attr, value in zip(self.homeAttributes(), result[0]):
+            for attr, value in zip(self.homeAttributes(), result):
                 setattr(self, attr, value)
 
-            queryCacher = self._txn._queryCacher
-            if queryCacher:
-                # Get cached copy
-                cacheKey = queryCacher.keyForHomeMetaData(self._resourceID)
-                data = yield queryCacher.get(cacheKey)
+            # STOP! If the status is external we need to convert this object to a CommonHomeExternal class which will
+            # have the right behavior for non-hosted external users.
+            if self._status == _HOME_STATUS_EXTERNAL:
+                actualHome = self._externalClass(self._txn, self._ownerUID, self._resourceID)
             else:
-                data = None
-            if data is None:
-                # Don't have a cached copy
-                data = (yield self._metaDataQuery.on(
-                    self._txn, resourceID=self._resourceID))[0]
-                if queryCacher:
-                    # Cache the data
-                    yield queryCacher.setAfterCommit(self._txn, cacheKey, data)
+                actualHome = self
+            yield actualHome.initMetaDataFromStore()
+            yield actualHome._loadPropertyStore()
 
-            for attr, value in zip(self.metadataAttributes(), data):
-                setattr(self, attr, value)
+            for factory_type, factory in self._txn._notifierFactories.items():
+                actualHome.addNotifier(factory_type, factory.newNotifier(actualHome))
 
-            yield self._loadPropertyStore()
-            returnValue(self)
+            returnValue(actualHome)
         else:
             returnValue(None)
 
 
+    @inlineCallbacks
+    def initMetaDataFromStore(self):
+        """
+        Load up the metadata and property store
+        """
+
+        queryCacher = self._txn._queryCacher
+        if queryCacher:
+            # Get cached copy
+            cacheKey = queryCacher.keyForHomeMetaData(self._resourceID)
+            data = yield queryCacher.get(cacheKey)
+        else:
+            data = None
+        if data is None:
+            # Don't have a cached copy
+            data = (yield self._metaDataQuery.on(self._txn, resourceID=self._resourceID))[0]
+            if queryCacher:
+                # Cache the data
+                yield queryCacher.setAfterCommit(self._txn, cacheKey, data)
+
+        for attr, value in zip(self.metadataAttributes(), data):
+            setattr(self, attr, value)
+
+
     @classmethod
     @inlineCallbacks
     def listHomes(cls, txn):
@@ -1664,16 +1821,20 @@
     @classmethod
     @inlineCallbacks
     def homeWithUID(cls, txn, uid, create=False):
-        homeObject = cls(txn, uid)
-        for factory_type, factory in txn._notifierFactories.items():
-            homeObject.addNotifier(factory_type, factory.newNotifier(homeObject))
-        homeObject = (yield homeObject.initFromStore())
+        homeObject = yield cls.makeClass(txn, uid)
         if homeObject is not None:
             returnValue(homeObject)
         else:
             if not create:
                 returnValue(None)
 
+            # Determine if the user is local or external
+            record = txn.directoryService().recordWithUID(uid)
+            if record is None:
+                raise DirectoryRecordNotFoundError("Cannot create home for UID since no directory record exists: {}".format(uid))
+
+            state = _HOME_STATUS_NORMAL if record.thisServer() else _HOME_STATUS_EXTERNAL
+
             # Use savepoint so we can do a partial rollback if there is a race condition
             # where this row has already been inserted
             savepoint = SavepointAction("homeWithUID")
@@ -1685,19 +1846,17 @@
                 resourceid = (yield Insert(
                     {
                         cls._homeSchema.OWNER_UID: uid,
+                        cls._homeSchema.STATUS: state,
                         cls._homeSchema.DATAVERSION: cls._dataVersionValue,
                     },
-                    Return=cls._homeSchema.RESOURCE_ID).on(txn))[0][0]
-                yield Insert(
-                    {cls._homeMetaDataSchema.RESOURCE_ID: resourceid}).on(txn)
+                    Return=cls._homeSchema.RESOURCE_ID
+                ).on(txn))[0][0]
+                yield Insert({cls._homeMetaDataSchema.RESOURCE_ID: resourceid}).on(txn)
             except Exception:  # FIXME: Really want to trap the pg.DatabaseError but in a non-DB specific manner
                 yield savepoint.rollback(txn)
 
                 # Retry the query - row may exist now, if not re-raise
-                homeObject = cls(txn, uid)
-                for factory_type, factory in txn._notifierFactories.items():
-                    homeObject.addNotifier(factory_type, factory.newNotifier(homeObject))
-                homeObject = (yield homeObject.initFromStore())
+                homeObject = yield cls.makeClass(txn, uid)
                 if homeObject:
                     returnValue(homeObject)
                 else:
@@ -1708,10 +1867,7 @@
                 # Note that we must not cache the owner_uid->resource_id
                 # mapping in _cacher when creating as we don't want that to appear
                 # until AFTER the commit
-                home = cls(txn, uid)
-                for factory_type, factory in txn._notifierFactories.items():
-                    home.addNotifier(factory_type, factory.newNotifier(home))
-                home = (yield home.initFromStore(no_cache=True))
+                home = yield cls.makeClass(txn, uid, no_cache=True)
                 yield home.createdHome()
                 returnValue(home)
 
@@ -1727,7 +1883,7 @@
 
 
     def __repr__(self):
-        return "<%s: %s>" % (self.__class__.__name__, self._resourceID)
+        return "<%s: %s, %s>" % (self.__class__.__name__, self._resourceID, self._ownerUID)
 
 
     def id(self):
@@ -1749,6 +1905,15 @@
         return self._ownerUID
 
 
+    def external(self):
+        """
+        Is this an external home.
+
+        @return: a string.
+        """
+        return False
+
+
     def transaction(self):
         return self._txn
 
@@ -1866,6 +2031,17 @@
         return self._childClass.objectWithID(self, resourceID)
 
 
+    def childWithExternalID(self, externalID):
+        """
+        Retrieve the child with the given C{externalID} contained in this
+        home.
+
+        @param name: a string.
+        @return: an L{ICalendar} or C{None} if no such child exists.
+        """
+        return self._childClass.objectWithExternalID(self, externalID)
+
+
     def allChildWithID(self, resourceID):
         """
         Retrieve the child with the given C{resourceID} contained in this
@@ -1878,12 +2054,11 @@
 
 
     @inlineCallbacks
-    def createChildWithName(self, name):
+    def createChildWithName(self, name, externalID=None):
         if name.startswith("."):
             raise HomeChildNameNotAllowedError(name)
 
-        yield self._childClass.create(self, name)
-        child = (yield self.childWithName(name))
+        child = yield self._childClass.create(self, name, externalID=externalID)
         returnValue(child)
 
 
@@ -2025,6 +2200,10 @@
         record a revision for the sharee home and sharee collection name with the "deleted" flag set. That way
         the shared collection can be reported as removed.
 
+        For external shared collections we need to report them as invalid as we cannot aggregate the sync token
+        for this home with the sync token from the external share which is under the control of the other pod.
+        Reporting it as invalid means that clients should do requests directly on the share itself to sync it.
+
         @param revision: the sync revision to compare to
         @type revision: C{str}
         @param depth: depth for determine what changed
@@ -2033,6 +2212,7 @@
 
         changed = set()
         deleted = set()
+        invalid = set()
         if revision:
             cs = schema.CALENDARSERVER
             minValidRevision = int((yield Select(
@@ -2090,13 +2270,17 @@
                         for name in (yield share.listObjectResources()):
                             changed.add("%s/%s" % (path, name,))
             else:
-                sharedChanged, sharedDeleted = yield share.sharedChildResourceNamesSinceRevision(revision, depth)
+                sharedChanged, sharedDeleted, sharedInvalid = yield share.sharedChildResourceNamesSinceRevision(revision, depth)
                 changed |= sharedChanged
+                changed -= sharedInvalid
                 deleted |= sharedDeleted
+                deleted -= sharedInvalid
+                invalid |= sharedInvalid
 
         changed = sorted(changed)
         deleted = sorted(deleted)
-        returnValue((changed, deleted))
+        invalid = sorted(invalid)
+        returnValue((changed, deleted, invalid,))
 
 
     @inlineCallbacks
@@ -2419,7 +2603,7 @@
     def revisionFromToken(self, token):
         if token is None:
             return 0
-        elif isinstance(token, str):
+        elif isinstance(token, str) or isinstance(token, unicode):
             _ignore_uuid, revision = token.split("_", 1)
             return int(revision)
         else:
@@ -2476,6 +2660,7 @@
         """
         changed = []
         deleted = []
+        invalid = []
         if revision:
             cs = schema.CALENDARSERVER
             minValidRevision = int((yield Select(
@@ -2504,7 +2689,7 @@
         else:
             changed = yield self.listObjectResources()
 
-        returnValue((changed, deleted))
+        returnValue((changed, deleted, invalid))
 
 
     @classproperty
@@ -2789,6 +2974,7 @@
         return Insert({
             bind.HOME_RESOURCE_ID: Parameter("homeID"),
             bind.RESOURCE_ID: Parameter("resourceID"),
+            bind.EXTERNAL_ID: Parameter("externalID"),
             bind.RESOURCE_NAME: Parameter("name"),
             bind.BIND_MODE: Parameter("mode"),
             bind.BIND_STATUS: Parameter("bindStatus"),
@@ -2870,11 +3056,21 @@
         """
         bind = cls._bindSchema
         return cls._bindFor((bind.RESOURCE_ID == Parameter("resourceID"))
-                               .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
-                               )
+                            .And(bind.HOME_RESOURCE_ID == Parameter("homeID")))
 
 
     @classproperty
+    def _bindForExternalIDAndHomeID(cls): #@NoSelf
+        """
+        DAL query that looks up home bind rows by home child
+        resource ID and home resource ID.
+        """
+        bind = cls._bindSchema
+        return cls._bindFor((bind.EXTERNAL_ID == Parameter("externalID"))
+                            .And(bind.HOME_RESOURCE_ID == Parameter("homeID")))
+
+
+    @classproperty
     def _bindForNameAndHomeID(cls): #@NoSelf
         """
         DAL query that looks up any bind rows by home child
@@ -2882,15 +3078,14 @@
         """
         bind = cls._bindSchema
         return cls._bindFor((bind.RESOURCE_NAME == Parameter("name"))
-                               .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
-                               )
+                            .And(bind.HOME_RESOURCE_ID == Parameter("homeID")))
 
 
     #
     # Higher level API
     #
     @inlineCallbacks
-    def inviteUserToShare(self, shareeUID, mode, summary):
+    def inviteUserToShare(self, shareeUID, mode, summary, shareName=None):
         """
         Invite a user to share this collection - either create the share if it does not exist, or
         update the existing share with new values. Make sure a notification is sent as well.
@@ -2909,15 +3104,19 @@
             status = _BIND_STATUS_INVITED if shareeView.shareStatus() in (_BIND_STATUS_DECLINED, _BIND_STATUS_INVALID) else None
             yield self.updateShare(shareeView, mode=mode, status=status, summary=summary)
         else:
-            shareeView = yield self.createShare(shareeUID=shareeUID, mode=mode, summary=summary)
+            shareeView = yield self.createShare(shareeUID=shareeUID, mode=mode, summary=summary, shareName=shareName)
 
-        # Send invite notification
-        yield self._sendInviteNotification(shareeView)
+        # Check for external
+        if shareeView.viewerHome().external():
+            yield self._sendExternalInvite(shareeView)
+        else:
+            # Send invite notification
+            yield self._sendInviteNotification(shareeView)
         returnValue(shareeView)
 
 
     @inlineCallbacks
-    def directShareWithUser(self, shareeUID):
+    def directShareWithUser(self, shareeUID, shareName=None):
         """
         Create a direct share with the specified user. Note it is currently up to the app layer
         to enforce access control - this is not ideal as we really should have control of that in
@@ -2932,8 +3131,13 @@
         # Ignore if it already exists
         shareeView = yield self.shareeView(shareeUID)
         if shareeView is None:
-            shareeView = yield self.createShare(shareeUID=shareeUID, mode=_BIND_MODE_DIRECT)
+            shareeView = yield self.createShare(shareeUID=shareeUID, mode=_BIND_MODE_DIRECT, shareName=shareName)
             yield shareeView.newShare()
+
+            # Check for external
+            if shareeView.viewerHome().external():
+                yield self._sendExternalInvite(shareeView)
+
         returnValue(shareeView)
 
 
@@ -2949,13 +3153,16 @@
 
         shareeView = yield self.shareeView(shareeUID)
         if shareeView is not None:
-            # If current user state is accepted then we send an invite with the new state, otherwise
-            # we cancel any existing invites for the user
-            if not shareeView.direct():
-                if shareeView.shareStatus() != _BIND_STATUS_ACCEPTED:
-                    yield self._removeInviteNotification(shareeView)
-                else:
-                    yield self._sendInviteNotification(shareeView, notificationState=_BIND_STATUS_DELETED)
+            if shareeView.viewerHome().external():
+                yield self._sendExternalUninvite(shareeView)
+            else:
+                # If current user state is accepted then we send an invite with the new state, otherwise
+                # we cancel any existing invites for the user
+                if not shareeView.direct():
+                    if shareeView.shareStatus() != _BIND_STATUS_ACCEPTED:
+                        yield self._removeInviteNotification(shareeView)
+                    else:
+                        yield self._sendInviteNotification(shareeView, notificationState=_BIND_STATUS_DELETED)
 
             # Remove the bind
             yield self.removeShare(shareeView)
@@ -2968,10 +3175,13 @@
         """
 
         if not self.direct() and self.shareStatus() != _BIND_STATUS_ACCEPTED:
+            if self.external():
+                yield self._replyExternalInvite(_BIND_STATUS_ACCEPTED, summary)
             ownerView = yield self.ownerView()
             yield ownerView.updateShare(self, status=_BIND_STATUS_ACCEPTED)
             yield self.newShare(displayname=summary)
-            yield self._sendReplyNotification(ownerView, summary)
+            if not ownerView.external():
+                yield self._sendReplyNotification(ownerView, summary)
 
 
     @inlineCallbacks
@@ -2981,24 +3191,43 @@
         """
 
         if not self.direct() and self.shareStatus() != _BIND_STATUS_DECLINED:
+            if self.external():
+                yield self._replyExternalInvite(_BIND_STATUS_DECLINED)
             ownerView = yield self.ownerView()
             yield ownerView.updateShare(self, status=_BIND_STATUS_DECLINED)
-            yield self._sendReplyNotification(ownerView)
+            if not ownerView.external():
+                yield self._sendReplyNotification(ownerView)
 
 
     @inlineCallbacks
     def deleteShare(self):
         """
-        This share is being deleted - either decline or remove (for direct shares).
+        This share is being deleted (by the sharee) - either decline or remove (for direct shares).
         """
 
         ownerView = yield self.ownerView()
         if self.direct():
             yield ownerView.removeShare(self)
+            if ownerView.external():
+                yield self._replyExternalInvite(_BIND_STATUS_DECLINED)
         else:
             yield self.declineShare()
 
 
+    @inlineCallbacks
+    def ownerDeleteShare(self):
+        """
+        This share is being deleted (by the owner) - either decline or remove (for direct shares).
+        """
+
+        # Change status on store object
+        yield self.setShared(False)
+
+        # Remove all sharees (direct and invited)
+        for invitation in (yield self.sharingInvites()):
+            yield self.uninviteUserFromShare(invitation.shareeUID)
+
+
     def newShare(self, displayname=None):
         """
         Override in derived classes to do any specific operations needed when a share
@@ -3098,10 +3327,57 @@
 
 
     #
-    # Lower level API
+    # External/cross-pod API
     #
+    @inlineCallbacks
+    def _sendExternalInvite(self, shareeView):
 
+        yield self._txn.store().conduit.send_shareinvite(
+            self._txn,
+            shareeView.ownerHome()._homeType,
+            shareeView.ownerHome().uid(),
+            self.id(),
+            self.shareName(),
+            shareeView.viewerHome().uid(),
+            shareeView.shareUID(),
+            shareeView.shareMode(),
+            shareeView.shareMessage(),
+            self.getInviteCopyProperties(),
+            supported_components=self.getSupportedComponents() if hasattr(self, "getSupportedComponents") else None,
+        )
+
+
     @inlineCallbacks
+    def _sendExternalUninvite(self, shareeView):
+
+        yield self._txn.store().conduit.send_shareuninvite(
+            self._txn,
+            shareeView.ownerHome()._homeType,
+            shareeView.ownerHome().uid(),
+            self.id(),
+            shareeView.viewerHome().uid(),
+            shareeView.shareUID(),
+        )
+
+
+    @inlineCallbacks
+    def _replyExternalInvite(self, status, summary=None):
+
+        yield self._txn.store().conduit.send_sharereply(
+            self._txn,
+            self.viewerHome()._homeType,
+            self.ownerHome().uid(),
+            self.viewerHome().uid(),
+            self.shareUID(),
+            status,
+            summary,
+        )
+
+
+    #
+    # Lower level API
+    #
+    @inlineCallbacks
     def ownerView(self):
         """
         Return the owner resource counterpart of this shared resource.
@@ -3124,7 +3400,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{CommonHomeChild} with another home.
 
@@ -3152,11 +3428,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=self._externalID,
                 name=newName,
                 mode=mode,
                 bindStatus=status,
@@ -3190,7 +3467,7 @@
 
 
     @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.
@@ -3202,6 +3479,7 @@
             mode=mode,
             status=_BIND_STATUS_INVITED if mode != _BIND_MODE_DIRECT else _BIND_STATUS_ACCEPTED,
             summary=summary,
+            shareName=shareName,
         )
         shareeView = yield self.shareeView(shareeUID)
         returnValue(shareeView)
@@ -3262,12 +3540,7 @@
             if summary is not None:
                 shareeView._bindMessage = columnMap[bind.MESSAGE]
 
-            queryCacher = self._txn._queryCacher
-            if queryCacher:
-                cacheKey = queryCacher.keyForObjectWithName(shareeView._home._resourceID, shareeView._name)
-                yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
-                cacheKey = queryCacher.keyForObjectWithResourceID(shareeView._home._resourceID, shareeView._resourceID)
-                yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
+            yield shareeView.invalidateQueryCache()
 
             # Must send notification to ensure cache invalidation occurs
             yield self.notifyPropertyChanged()
@@ -3321,12 +3594,7 @@
             homeID=shareeHome._resourceID,
         )
 
-        queryCacher = self._txn._queryCacher
-        if queryCacher:
-            cacheKey = queryCacher.keyForObjectWithName(shareeHome._resourceID, shareeView._name)
-            yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
-            cacheKey = queryCacher.keyForObjectWithResourceID(shareeHome._resourceID, shareeView._resourceID)
-            yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
+        yield shareeView.invalidateQueryCache()
 
 
     @inlineCallbacks
@@ -3526,6 +3794,24 @@
         return self._bindMessage
 
 
+    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.
+        """
+        return {}
+
+
+    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.
+        """
+        pass
+
+
     @classmethod
     def metadataColumns(cls):
         """
@@ -3570,13 +3856,14 @@
             cls._bindSchema.BIND_MODE,
             cls._bindSchema.HOME_RESOURCE_ID,
             cls._bindSchema.RESOURCE_ID,
+            cls._bindSchema.EXTERNAL_ID,
             cls._bindSchema.RESOURCE_NAME,
             cls._bindSchema.BIND_STATUS,
             cls._bindSchema.BIND_REVISION,
             cls._bindSchema.MESSAGE
         )
 
-    bindColumnCount = 7
+    bindColumnCount = 8
 
     @classmethod
     def additionalBindColumns(cls):
@@ -3636,6 +3923,7 @@
             yield queryCacher.invalidateAfterCommit(self._txn, queryCacher.keyForHomeChildMetaData(self._resourceID))
             yield queryCacher.invalidateAfterCommit(self._txn, queryCacher.keyForObjectWithName(self._home._resourceID, self._name))
             yield queryCacher.invalidateAfterCommit(self._txn, queryCacher.keyForObjectWithResourceID(self._home._resourceID, self._resourceID))
+            yield queryCacher.invalidateAfterCommit(self._txn, queryCacher.keyForObjectWithExternalID(self._home._resourceID, self._externalID))
 
 
 
@@ -3651,6 +3939,7 @@
         "_resourceID",
     )
 
+    _externalClass = None
     _objectResourceClass = None
 
     _bindSchema = None
@@ -3661,11 +3950,148 @@
     _objectSchema = None
 
 
-    def __init__(self, home, name, resourceID, mode, status, revision=0, message=None, ownerHome=None, ownerName=None):
+    @classmethod
+    @inlineCallbacks
+    def makeClass(cls, home, bindData, additionalBindData, metadataData, propstore=None, ownerHome=None):
+        """
+        Given the various database rows, build the actual class.
 
+        @param home: the parent home object
+        @type home: L{CommonHome}
+        @param bindData: the standard set of bind columns
+        @type bindData: C{list}
+        @param additionalBindData: additional bind data specific to sub-classes
+        @type additionalBindData: C{list}
+        @param metadataData: metadata data
+        @type metadataData: C{list}
+        @param propstore: a property store to use, or C{None} to load it automatically
+        @type propstore: L{PropertyStore}
+        @param ownerHome: the home of the owner, or C{None} to figure it out automatically
+        @type ownerHome: L{CommonHome}
+
+        @return: the constructed child class
+        @rtype: L{CommonHomeChild}
+        """
+
+        bindMode, _ignore_homeID, resourceID, externalID, name, bindStatus, bindRevision, bindMessage = bindData
+
+        if ownerHome is None:
+            if bindMode == _BIND_MODE_OWN:
+                ownerHome = home
+                ownerName = name
+            else:
+                ownerHome, ownerName = yield home.ownerHomeAndChildNameForChildID(resourceID)
+        else:
+            ownerName = None
+
+        c = cls._externalClass if ownerHome.external() else cls
+        child = c(
+            home=home,
+            name=name,
+            resourceID=resourceID,
+            mode=bindMode,
+            status=bindStatus,
+            revision=bindRevision,
+            message=bindMessage,
+            ownerHome=ownerHome,
+            ownerName=ownerName,
+            externalID=externalID,
+        )
+
+        if additionalBindData:
+            for attr, value in zip(child.additionalBindAttributes(), additionalBindData):
+                setattr(child, attr, value)
+
+        if metadataData:
+            for attr, value in zip(child.metadataAttributes(), metadataData):
+                setattr(child, attr, value)
+
+        # 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 and bindMode != _BIND_MODE_OWN:
+            propstore._setDefaultUserUID(ownerHome.uid())
+        yield child._loadPropertyStore(propstore)
+
+        returnValue(child)
+
+
+    @classmethod
+    @inlineCallbacks
+    def _getDBData(cls, home, name, resourceID, externalID):
+        """
+        Given a set of identifying information, load the data rows for the object. Only one of
+        L{name}, L{resourceID} or L{externalID} is specified - others are C{None}.
+
+        @param home: the parent home object
+        @type home: L{CommonHome}
+        @param name: the resource name
+        @type name: C{str}
+        @param resourceID: the resource ID
+        @type resourceID: C{int}
+        @param externalID: the resource ID of the external (cross-pod) referenced item
+        @type externalID: C{int}
+        """
+
+        # Get the bind row data
+        row = None
+        queryCacher = home._txn._queryCacher
+
+        if queryCacher:
+            # Retrieve data from cache
+            if name:
+                cacheKey = queryCacher.keyForObjectWithName(home._resourceID, name)
+            elif resourceID:
+                cacheKey = queryCacher.keyForObjectWithResourceID(home._resourceID, resourceID)
+            elif externalID:
+                cacheKey = queryCacher.keyForObjectWithExternalID(home._resourceID, externalID)
+            row = yield queryCacher.get(cacheKey)
+
+        if row is None:
+            # No cached copy
+            if name:
+                rows = yield cls._bindForNameAndHomeID.on(home._txn, name=name, homeID=home._resourceID)
+            elif resourceID:
+                rows = yield cls._bindForResourceIDAndHomeID.on(home._txn, resourceID=resourceID, homeID=home._resourceID)
+            elif externalID:
+                rows = yield cls._bindForExternalIDAndHomeID.on(home._txn, externalID=externalID, homeID=home._resourceID)
+            row = rows[0] if rows else None
+
+        if not row:
+            returnValue(None)
+
+        if queryCacher:
+            # Cache the result
+            queryCacher.setAfterCommit(home._txn, queryCacher.keyForObjectWithName(home._resourceID, name), row)
+            queryCacher.setAfterCommit(home._txn, queryCacher.keyForObjectWithResourceID(home._resourceID, resourceID), row)
+            queryCacher.setAfterCommit(home._txn, queryCacher.keyForObjectWithExternalID(home._resourceID, externalID), row)
+
+        bindData = row[:cls.bindColumnCount]
+        additionalBindData = row[cls.bindColumnCount:cls.bindColumnCount + len(cls.additionalBindColumns())]
+        resourceID = bindData[cls.bindColumns().index(cls._bindSchema.RESOURCE_ID)]
+
+        # Get the matching metadata data
+        metadataData = None
+        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,))
+
+
+    def __init__(self, home, name, resourceID, mode, status, revision=0, message=None, ownerHome=None, ownerName=None, externalID=None):
+
         self._home = home
         self._name = name
         self._resourceID = resourceID
+        self._externalID = externalID
         self._bindMode = mode
         self._bindStatus = status
         self._bindRevision = revision
@@ -3687,9 +4113,7 @@
         else:
             self._notifiers = None
 
-        self._index = None  # Derived classes need to set this
 
-
     def memoMe(self, key, memo): #@UnusedVariable
         """
         Add this object to the memo dictionary in whatever fashion is appropriate.
@@ -3715,7 +4139,7 @@
         rows = yield cls._acceptedBindForHomeID.on(
             home._txn, homeID=home._resourceID
         )
-        names = [row[3] for row in rows]
+        names = [row[cls.bindColumns().index(cls._bindSchema.RESOURCE_NAME)] for row in rows]
         returnValue(names)
 
 
@@ -3748,119 +4172,66 @@
 
         # Create the actual objects merging in properties
         for dataRow in dataRows:
-            bindMode, homeID, resourceID, bindName, 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] #@UnusedVariable
+            resourceID = bindData[cls.bindColumns().index(cls._bindSchema.RESOURCE_ID)]
+            additionalBindData = dataRow[cls.bindColumnCount:cls.bindColumnCount + len(cls.additionalBindColumns())]
+            metadataData = dataRow[cls.bindColumnCount + len(cls.additionalBindColumns()):]
+            propstore = propertyStores.get(resourceID, None)
 
-            if bindMode == _BIND_MODE_OWN:
-                ownerHome = home
-                ownerName = bindName
-            else:
-                #TODO: get all ownerHomeIDs at once
-                ownerHome, ownerName = yield home.ownerHomeAndChildNameForChildID(resourceID)
-
-            child = cls(
-                home=home,
-                name=bindName,
-                resourceID=resourceID,
-                mode=bindMode,
-                status=bindStatus,
-                revision=bindRevision,
-                message=bindMessage,
-                ownerHome=ownerHome,
-                ownerName=ownerName,
-            )
-            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)
             child._syncTokenRevision = revisions[resourceID]
-            propstore = propertyStores.get(resourceID, 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 and bindMode != _BIND_MODE_OWN:
-                propstore._setDefaultUserUID(ownerHome.uid())
-            yield child._loadPropertyStore(propstore)
             results.append(child)
+
         returnValue(results)
 
 
     @classmethod
     def objectWithName(cls, home, name, accepted=True):
-        return cls._objectWithNameOrID(home, name=name, accepted=accepted)
+        return cls.objectWith(home, name=name, accepted=accepted)
 
 
     @classmethod
     def objectWithID(cls, home, resourceID, accepted=True):
-        return cls._objectWithNameOrID(home, resourceID=resourceID, accepted=accepted)
+        return cls.objectWith(home, resourceID=resourceID, accepted=accepted)
 
 
     @classmethod
+    def objectWithExternalID(cls, home, externalID, accepted=True):
+        return cls.objectWith(home, externalID=externalID, accepted=accepted)
+
+
+    @classmethod
     @inlineCallbacks
-    def _objectWithNameOrID(cls, home, name=None, resourceID=None, accepted=True):
-        # replaces objectWithName()
+    def objectWith(cls, home, name=None, resourceID=None, externalID=None, accepted=True):
         """
-        Retrieve the child with the given C{name} or C{resourceID} contained in the given
-        C{home}.
+        Create the object using one of the specified arguments as the key to load it. One
+        and only one of the keyword arguments must be set.
 
-        @param home: a L{CommonHome}.
+        @param parent: parent collection
+        @type parent: L{CommonHomeChild}
+        @param name: name of the resource, or C{None}
+        @type name: C{str}
+        @param uid: resource data UID, or C{None}
+        @type uid: C{str}
+        @param resourceID: resource id
+        @type resourceID: C{int}
+        @param accepted: if C{True} only load owned or accepted share items
+        @type accepted: C{bool}
 
-        @param name: a string; the name of the L{CommonHomeChild} to retrieve.
-
-        @return: an L{CommonHomeChild} or C{None} if no such child
-            exists.
+        @return: the new object or C{None} if not found
+        @rtype: C{CommonHomeChild}
         """
-        rows = None
-        queryCacher = home._txn._queryCacher
 
-        if queryCacher:
-            # Retrieve data from cache
-            if name:
-                cacheKey = queryCacher.keyForObjectWithName(home._resourceID, name)
-            else:
-                cacheKey = queryCacher.keyForObjectWithResourceID(home._resourceID, resourceID)
-            rows = yield queryCacher.get(cacheKey)
-
-        if rows is None:
-            # No cached copy
-            if name:
-                rows = yield cls._bindForNameAndHomeID.on(home._txn, name=name, homeID=home._resourceID)
-            else:
-                rows = yield cls._bindForResourceIDAndHomeID.on(home._txn, resourceID=resourceID, homeID=home._resourceID)
-
-        if not rows:
+        dbData = yield cls._getDBData(home, name, resourceID, externalID)
+        if dbData is None:
             returnValue(None)
+        bindData, additionalBindData, metadataData = dbData
 
-        row = rows[0]
-        bindMode, homeID, resourceID, name, bindStatus, bindRevision, bindMessage = row[:cls.bindColumnCount] #@UnusedVariable
-
-        if queryCacher:
-            # Cache the result
-            queryCacher.setAfterCommit(home._txn, queryCacher.keyForObjectWithName(home._resourceID, name), rows)
-            queryCacher.setAfterCommit(home._txn, queryCacher.keyForObjectWithResourceID(home._resourceID, resourceID), rows)
-
+        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 bindMode == _BIND_MODE_OWN:
-            ownerHome = home
-            ownerName = name
-        else:
-            ownerHome, ownerName = yield home.ownerHomeAndChildNameForChildID(resourceID)
-
-        child = cls(
-            home=home,
-            name=name,
-            resourceID=resourceID,
-            mode=bindMode,
-            status=bindStatus,
-            revision=bindRevision,
-            message=bindMessage,
-            ownerHome=ownerHome,
-            ownerName=ownerName
-        )
-        yield child.initFromStore(additionalBind)
+        child = yield cls.makeClass(home, bindData, additionalBindData, metadataData)
         returnValue(child)
 
 
@@ -3888,35 +4259,28 @@
 
     @classmethod
     @inlineCallbacks
-    def create(cls, home, name):
+    def create(cls, home, name, externalID=None):
 
-        if (yield cls._bindForNameAndHomeID.on(home._txn,
-            name=name, homeID=home._resourceID)):
+        if (yield cls._bindForNameAndHomeID.on(home._txn, name=name, homeID=home._resourceID)):
             raise HomeChildNameAlreadyExistsError(name)
 
         if name.startswith("."):
             raise HomeChildNameNotAllowedError(name)
 
         # Create this object
-        resourceID = (
-            yield cls._insertHomeChild.on(home._txn))[0][0]
+        resourceID = (yield cls._insertHomeChild.on(home._txn))[0][0]
 
         # Initialize this object
-        _created, _modified = (
-            yield cls._insertHomeChildMetaData.on(home._txn,
-                                                  resourceID=resourceID))[0]
+        _created, _modified = (yield cls._insertHomeChildMetaData.on(home._txn, resourceID=resourceID))[0]
         # Bind table needs entry
         yield cls._bindInsertQuery.on(
-            home._txn, homeID=home._resourceID, resourceID=resourceID,
+            home._txn, homeID=home._resourceID, resourceID=resourceID, externalID=externalID,
             name=name, mode=_BIND_MODE_OWN, bindStatus=_BIND_STATUS_ACCEPTED,
             message=None,
         )
 
         # Initialize other state
-        child = cls(home, name, resourceID, _BIND_MODE_OWN, _BIND_STATUS_ACCEPTED)
-        child._created = _created
-        child._modified = _modified
-        yield child._loadPropertyStore()
+        child = yield cls.objectWithID(home, resourceID)
 
         yield child._initSyncToken()
 
@@ -3937,44 +4301,32 @@
                       Where=child.RESOURCE_ID == Parameter("resourceID"))
 
 
-    @inlineCallbacks
-    def initFromStore(self, additionalBind=None):
+    def id(self):
         """
-        Initialise this object from the store, based on its already-populated
-        resource ID. We read in and cache all the extra metadata from the DB to
-        avoid having to do DB queries for those individually later.
+        Retrieve the store identifier for this collection.
+
+        @return: store identifier.
+        @rtype: C{int}
         """
-        queryCacher = self._txn._queryCacher
-        if queryCacher:
-            # Retrieve from cache
-            cacheKey = queryCacher.keyForHomeChildMetaData(self._resourceID)
-            dataRows = yield queryCacher.get(cacheKey)
-        else:
-            dataRows = None
-        if dataRows is None:
-            # No cached copy
-            dataRows = (yield self._metadataByIDQuery.on(self._txn, resourceID=self._resourceID))[0]
-            if queryCacher:
-                # Cache the results
-                yield queryCacher.setAfterCommit(self._txn, cacheKey, dataRows)
+        return self._resourceID
 
-        if additionalBind:
-            for attr, value in zip(self.additionalBindAttributes(), additionalBind):
-                setattr(self, attr, value)
 
-        for attr, value in zip(self.metadataAttributes(), dataRows):
-            setattr(self, attr, value)
-        yield self._loadPropertyStore()
+    def external_id(self):
+        """
+        Retrieve the external store identifier for this collection.
 
+        @return: a string.
+        """
+        return self._externalID
 
-    def id(self):
+
+    def external(self):
         """
-        Retrieve the store identifier for this collection.
+        Is this an external home.
 
-        @return: store identifier.
-        @rtype: C{int}
+        @return: a string.
         """
-        return self._resourceID
+        return self.ownerHome().external()
 
 
     @property
@@ -3986,10 +4338,6 @@
         return self._txn.store().directoryService()
 
 
-    def retrieveOldIndex(self):
-        return self._index
-
-
     def __repr__(self):
         return "<%s: %s>" % (self.__class__.__name__, self._resourceID)
 
@@ -4024,14 +4372,13 @@
 
         @return: a L{Deferred} which fires when the modification is complete.
         """
+
+        if self.isShared() or self.external():
+            raise ShareNotAllowed("Cannot rename a shared collection")
+
         oldName = self._name
 
-        queryCacher = self._home._txn._queryCacher
-        if queryCacher:
-            cacheKey = queryCacher.keyForObjectWithName(self._home._resourceID, oldName)
-            yield queryCacher.invalidateAfterCommit(self._home._txn, cacheKey)
-            cacheKey = queryCacher.keyForObjectWithResourceID(self._home._resourceID, self._resourceID)
-            yield queryCacher.invalidateAfterCommit(self._home._txn, cacheKey)
+        yield self.invalidateQueryCache()
 
         yield self._renameQuery.on(self._txn, name=name,
                                    resourceID=self._resourceID,
@@ -4058,19 +4405,16 @@
     @inlineCallbacks
     def remove(self):
 
+        # Stop sharing first
+        yield self.ownerDeleteShare()
+
         # Do before setting _resourceID making changes
         yield self.notifyPropertyChanged()
 
-        queryCacher = self._home._txn._queryCacher
-        if queryCacher:
-            cacheKey = queryCacher.keyForObjectWithName(self._home._resourceID, self._name)
-            yield queryCacher.invalidateAfterCommit(self._home._txn, cacheKey)
-            cacheKey = queryCacher.keyForObjectWithResourceID(self._home._resourceID, self._resourceID)
-            yield queryCacher.invalidateAfterCommit(self._home._txn, cacheKey)
+        yield self.invalidateQueryCache()
 
         yield self._deletedSyncToken()
-        yield self._deleteQuery.on(self._txn, NoSuchHomeChildError,
-                                   resourceID=self._resourceID)
+        yield self._deleteQuery.on(self._txn, NoSuchHomeChildError, resourceID=self._resourceID)
         yield self.properties()._removeResource()
 
         # Set to non-existent state
@@ -4122,6 +4466,7 @@
         for result in results:
             self._objects[result.name()] = result
             self._objects[result.uid()] = result
+            self._objects[result.id()] = result
         self._objectNames = sorted([result.name() for result in results])
         returnValue(results)
 
@@ -4135,6 +4480,7 @@
         for result in results:
             self._objects[result.name()] = result
             self._objects[result.uid()] = result
+            self._objects[result.id()] = result
         self._objectNames = sorted([result.name() for result in results])
         returnValue(results)
 
@@ -4171,8 +4517,7 @@
     @inlineCallbacks
     def countObjectResources(self):
         if self._objectNames is None:
-            rows = yield self._objectCountQuery.on(
-                self._txn, resourceID=self._resourceID)
+            rows = yield self._objectCountQuery.on(self._txn, resourceID=self._resourceID)
             returnValue(rows[0][0])
         returnValue(len(self._objectNames))
 
@@ -4204,18 +4549,13 @@
         We create the empty object first then have it initialize itself from the
         store.
         """
-        if resourceID:
-            objectResource = (
-                yield self._objectResourceClass.objectWithID(self, resourceID)
-            )
-        else:
-            objectResource = (
-                yield self._objectResourceClass.objectWithName(self, name, uid)
-            )
+        objectResource = (
+            yield self._objectResourceClass.objectWith(self, name=name, uid=uid, resourceID=resourceID)
+        )
         if objectResource:
             self._objects[objectResource.name()] = objectResource
             self._objects[objectResource.uid()] = objectResource
-            self._objects[objectResource._resourceID] = objectResource
+            self._objects[objectResource.id()] = objectResource
         else:
             if resourceID:
                 self._objects[resourceID] = None
@@ -4262,7 +4602,7 @@
         obj = cls._objectSchema
         return Select(
             [obj.UID], From=obj,
-            Where=(obj.UID == Parameter("name")
+            Where=(obj.RESOURCE_NAME == Parameter("name")
                   ).And(obj.PARENT_RESOURCE_ID == Parameter("resourceID")))
 
 
@@ -4305,6 +4645,7 @@
         )
         self._objects[objectResource.name()] = objectResource
         self._objects[objectResource.uid()] = objectResource
+        self._objects[objectResource.id()] = objectResource
 
         # Note: create triggers a notification when the component is set, so we
         # don't need to call notify() here like we do for object removal.
@@ -4315,6 +4656,7 @@
     def removedObjectResource(self, child):
         self._objects.pop(child.name(), None)
         self._objects.pop(child.uid(), None)
+        self._objects.pop(child.id(), None)
         if self._objectNames and child.name() in self._objectNames:
             self._objectNames.remove(child.name())
         yield self._deleteRevision(child.name())
@@ -4347,10 +4689,9 @@
 
 
     @inlineCallbacks
-    def moveObjectResource(self, child, newparent, newname=None):
+    def _validObjectResource(self, child, newparent, newname=None):
         """
-        Move a child of this collection into another collection without actually removing/re-inserting the data.
-        Make sure sync and cache details for both collections are updated.
+        Check that the move operation is valid
 
         TODO: check that the resource name does not exist in the new parent, or that the UID
         does not exist there too.
@@ -4364,7 +4705,6 @@
         """
 
         name = child.name()
-        uid = child.uid()
 
         if newname is None:
             newname = name
@@ -4383,10 +4723,34 @@
             if child_count >= config.MaxResourcesPerCollection:
                 raise TooManyObjectResourcesError()
 
+        returnValue(newname)
+
+
+    @inlineCallbacks
+    def moveObjectResource(self, child, newparent, newname=None):
+        """
+        Move a child of this collection into another collection without actually removing/re-inserting the data.
+        Make sure sync and cache details for both collections are updated.
+
+        TODO: check that the resource name does not exist in the new parent, or that the UID
+        does not exist there too.
+
+        @param child: the child resource to move
+        @type child: L{CommonObjectResource}
+        @param newparent: the parent to move to
+        @type newparent: L{CommonHomeChild}
+        @param newname: new name to use in new parent
+        @type newname: C{str} or C{None} for existing name
+        """
+
+        name = child.name()
+        newname = yield self._validObjectResource(child, newparent, newname)
+        uid = child.uid()
+
         # Clean this collections cache and signal sync change
         self._objects.pop(name, None)
         self._objects.pop(uid, None)
-        self._objects.pop(child._resourceID, None)
+        self._objects.pop(child.id(), None)
         yield self._deleteRevision(name)
         yield self.notifyChanged()
 
@@ -4417,15 +4781,87 @@
         # Signal sync change on new collection
         newparent._objects.pop(name, None)
         newparent._objects.pop(uid, None)
-        newparent._objects.pop(child._resourceID, None)
+        newparent._objects.pop(child.id(), None)
         yield newparent._insertRevision(newname)
         yield newparent.notifyChanged()
 
 
+    @inlineCallbacks
+    def moveObjectResourceCreateDelete(self, child, newparent, newname=None):
+        """
+        Move a child of this collection into another collection by doing a create/delete.
+
+        TODO: check that the resource name does not exist in the new parent, or that the UID
+        does not exist there too.
+
+        @param child: the child resource to move
+        @type child: L{CommonObjectResource}
+        @param newparent: the parent to move to
+        @type newparent: L{CommonHomeChild}
+        @param newname: new name to use in new parent
+        @type newname: C{str} or C{None} for existing name
+        """
+
+        name = child.name()
+        newname = yield self._validObjectResource(child, newparent, newname)
+
+        # Do a move as a create/delete
+        component = yield child.component()
+        yield newparent.moveObjectResourceHere(name, component)
+        yield self.moveObjectResourceAway(child.id(), child)
+
+
+    @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}
+        """
+
+        yield self.createObjectResourceWithName(name, component)
+
+
+    @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.remove()
+
+
     def objectResourcesHaveProperties(self):
         return False
 
 
+    def search(self, filter):
+        """
+        Do a query of the contents of this collection.
+
+        @param filter: the query filter to use
+        @type filter: L{Filter}
+
+        @return: the names of the matching resources
+        @rtype: C{list}
+        """
+
+        # This implementation raises - sub-classes override to do the actual query
+        raise IndexedSearchException()
+
+
     @inlineCallbacks
     def sharedChildResourceNamesSinceRevision(self, revision, depth):
         """
@@ -4447,60 +4883,65 @@
         @param depth: depth for determine what changed
         @type depth: C{str}
         """
-        assert not self.owned()
-
-        if revision != 0 and revision < self._bindRevision:
-            if depth != '1':
-                raise SyncTokenValidException
-            else:
-                revision = 0
-
         changed = set()
         deleted = set()
-        if revision:
-            rev = self._revisionsSchema
-            results = [
-                (
-                    self.name(),
-                    name if name else "",
-                    wasdeleted
-                )
-                for name, wasdeleted in
-                (yield Select(
-                    [rev.RESOURCE_NAME, rev.DELETED],
-                    From=rev,
-                    Where=(rev.REVISION > revision).And(
-                    rev.RESOURCE_ID == self._resourceID)
-                ).on(self._txn))
-                if name
-            ]
+        invalid = set()
+        if self.external():
+            if depth == "1":
+                pass
+            else:
+                invalid.add(self.name() + "/")
+        else:
+            if revision != 0 and revision < self._bindRevision:
+                if depth != "1":
+                    raise SyncTokenValidException
+                else:
+                    revision = 0
 
-            for path, name, wasdeleted in results:
-                if wasdeleted:
-                    if depth == "1":
-                        changed.add("%s/" % (path,))
-                    else:
-                        deleted.add("%s/%s" % (path, name,))
+            if revision:
+                rev = self._revisionsSchema
+                results = [
+                    (
+                        self.name(),
+                        name if name else "",
+                        wasdeleted
+                    )
+                    for name, wasdeleted in
+                    (yield Select(
+                        [rev.RESOURCE_NAME, rev.DELETED],
+                        From=rev,
+                        Where=(rev.REVISION > revision).And(
+                        rev.RESOURCE_ID == self._resourceID)
+                    ).on(self._txn))
+                    if name
+                ]
 
+                for path, name, wasdeleted in results:
+                    if wasdeleted:
+                        if depth == "1":
+                            changed.add("%s/" % (path,))
+                        else:
+                            deleted.add("%s/%s" % (path, name,))
+
+                    # Always report collection as changed
+                    changed.add("%s/" % (path,))
+
+                    # Resource changed - for depth "infinity" report resource as changed
+                    if depth != "1":
+                        changed.add("%s/%s" % (path, name,))
+            else:
+                path = self.name()
                 # Always report collection as changed
                 changed.add("%s/" % (path,))
 
                 # Resource changed - for depth "infinity" report resource as changed
                 if depth != "1":
-                    changed.add("%s/%s" % (path, name,))
-        else:
-            path = self.name()
-            # Always report collection as changed
-            changed.add("%s/" % (path,))
+                    for name in (yield self.listObjectResources()):
+                        changed.add("%s/%s" % (path, name,))
 
-            # Resource changed - for depth "infinity" report resource as changed
-            if depth != "1":
-                for name in (yield self.listObjectResources()):
-                    changed.add("%s/%s" % (path, name,))
+        returnValue((changed, deleted, invalid,))
 
-        returnValue((changed, deleted))
 
-
     @inlineCallbacks
     def _loadPropertyStore(self, props=None):
         if props is None:
@@ -4680,10 +5121,85 @@
         "_parentCollection",
     )
 
+    _externalClass = None
     _objectSchema = None
+    _componentClass = None
 
     BATCH_LOAD_SIZE = 50
 
+
+    @classmethod
+    @inlineCallbacks
+    def makeClass(cls, parent, objectData, propstore=None):
+        """
+        Given the various database rows, build the actual class.
+
+        @param parent: the parent collection object
+        @type parent: L{CommonHomeChild}
+        @param objectData: the standard set of object columns
+        @type objectData: 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)
+
+        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{CommonHomeChild}
+        @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}
+        """
+
+        rows = None
+        if name:
+            rows = yield cls._allColumnsWithParentAndName.on(
+                parent._txn,
+                name=name,
+                parentID=parent._resourceID
+            )
+        elif uid:
+            rows = yield cls._allColumnsWithParentAndUID.on(
+                parent._txn,
+                uid=uid,
+                parentID=parent._resourceID
+            )
+        elif resourceID:
+            rows = yield cls._allColumnsWithParentAndID.on(
+                parent._txn,
+                resourceID=resourceID,
+                parentID=parent._resourceID
+            )
+
+        returnValue(rows[0] if rows else None)
+
+
     def __init__(self, parent, name, uid, resourceID=None, options=None): #@UnusedVariable
         self._parentCollection = parent
         self._resourceID = resourceID
@@ -4693,7 +5209,8 @@
         self._size = None
         self._created = None
         self._modified = None
-        self._notificationData = None
+        self._textData = None
+        self._cachedComponent = None
 
         self._locked = False
 
@@ -4701,7 +5218,7 @@
     @classproperty
     def _allColumnsWithParentQuery(cls): #@NoSelf
         obj = cls._objectSchema
-        return Select(cls._allColumns, From=obj,
+        return Select(cls._allColumns(), From=obj,
                       Where=obj.PARENT_RESOURCE_ID == Parameter("parentID"))
 
 
@@ -4742,11 +5259,10 @@
 
         # Create the actual objects merging in properties
         for row in dataRows:
-            child = cls(parent, "", None)
-            child._initFromRow(tuple(row))
-            yield child._loadPropertyStore(
-                props=propertyStores.get(child._resourceID, None)
-            )
+            resourceID = row[cls._allColumns().index(cls._objectSchema.RESOURCE_ID)]
+            propstore = propertyStores.get(resourceID, None)
+
+            child = yield cls.makeClass(parent, row, propstore=propstore)
             results.append(child)
 
         returnValue(results)
@@ -4756,7 +5272,9 @@
     @inlineCallbacks
     def loadAllObjectsWithNames(cls, parent, names):
         """
-        Load all child objects with the specified names, doing so in batches.
+        Load all child objects with the specified names, doing so in batches (because we need to match
+        using SQL "resource_name in (...)" where there might be a character length limit on the number
+        of items in the set).
         """
         names = tuple(names)
         results = []
@@ -4771,7 +5289,7 @@
     @classmethod
     def _allColumnsWithParentAndNamesQuery(cls, names):
         obj = cls._objectSchema
-        return Select(cls._allColumns, From=obj,
+        return Select(cls._allColumns(), From=obj,
                       Where=(obj.PARENT_RESOURCE_ID == Parameter("parentID")).And(
                           obj.RESOURCE_NAME.In(Parameter("names", len(names)))))
 
@@ -4795,7 +5313,7 @@
 
         # Optimize case of single name to load
         if len(names) == 1:
-            obj = yield cls.objectWithName(parent, names[0], None)
+            obj = yield cls.objectWithName(parent, names[0])
             returnValue([obj] if obj else [])
 
         results = []
@@ -4816,30 +5334,61 @@
 
         # Create the actual objects merging in properties
         for row in dataRows:
-            child = cls(parent, "", None)
-            child._initFromRow(tuple(row))
-            yield child._loadPropertyStore(
-                props=propertyStores.get(child._resourceID, None)
-            )
+            resourceID = row[cls._allColumns().index(cls._objectSchema.RESOURCE_ID)]
+            propstore = propertyStores.get(resourceID, None)
+
+            child = yield cls.makeClass(parent, row, propstore=propstore)
             results.append(child)
 
         returnValue(results)
 
 
     @classmethod
-    def objectWithName(cls, parent, name, uid):
-        objectResource = cls(parent, name, uid, None)
-        return objectResource.initFromStore()
+    def objectWithName(cls, parent, name):
+        return cls.objectWith(parent, name=name)
 
 
     @classmethod
+    def objectWithUID(cls, parent, uid):
+        return cls.objectWith(parent, uid=uid)
+
+
+    @classmethod
     def objectWithID(cls, parent, resourceID):
-        objectResource = cls(parent, None, None, resourceID)
-        return objectResource.initFromStore()
+        return cls.objectWith(parent, resourceID=resourceID)
 
 
     @classmethod
     @inlineCallbacks
+    def objectWith(cls, parent, name=None, uid=None, resourceID=None):
+        """
+        Create the object using one of the specified arguments as the key to load it. One
+        and only one of the keyword arguments must be set.
+
+        @param parent: parent collection
+        @type parent: L{CommonHomeChild}
+        @param name: name of the resource, or C{None}
+        @type name: C{str}
+        @param uid: resource data UID, or C{None}
+        @type uid: C{str}
+        @param resourceID: resource id
+        @type resourceID: C{int}
+
+        @return: the new object or C{None} if not found
+        @rtype: C{CommonObjectResource}
+        """
+
+        row = yield cls._getDBData(parent, name, uid, resourceID)
+
+        if row:
+            child = yield cls.makeClass(parent, row)
+            returnValue(child)
+        else:
+            returnValue(None)
+
+
+    @classmethod
+    @inlineCallbacks
     def create(cls, parent, name, component, options=None):
 
         child = (yield parent.objectResourceWithName(name))
@@ -4849,13 +5398,13 @@
         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.setComponent(component, inserting=True)
         yield objectResource._loadPropertyStore(created=True)
 
         # Note: setComponent triggers a notification, so we don't need to
         # call notify( ) here like we do for object removal.
-
         returnValue(objectResource)
 
 
@@ -4866,7 +5415,7 @@
         parameter and a given instance column matches a given parameter name.
         """
         return Select(
-            cls._allColumns, From=cls._objectSchema,
+            cls._allColumns(), From=cls._objectSchema,
             Where=(column == Parameter(paramName)).And(
                 cls._objectSchema.PARENT_RESOURCE_ID == Parameter("parentID"))
         )
@@ -4887,38 +5436,7 @@
         return cls._allColumnsWithParentAnd(cls._objectSchema.RESOURCE_ID, "resourceID")
 
 
-    @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.
-
-        @return: L{self} if object exists in the DB, else C{None}
-        """
-
-        if self._name:
-            rows = yield self._allColumnsWithParentAndName.on(
-                self._txn, name=self._name,
-                parentID=self._parentCollection._resourceID)
-        elif self._uid:
-            rows = yield self._allColumnsWithParentAndUID.on(
-                self._txn, uid=self._uid,
-                parentID=self._parentCollection._resourceID)
-        elif self._resourceID:
-            rows = yield self._allColumnsWithParentAndID.on(
-                self._txn, resourceID=self._resourceID,
-                parentID=self._parentCollection._resourceID)
-        if rows:
-            self._initFromRow(tuple(rows[0]))
-            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
@@ -4936,21 +5454,52 @@
         ]
 
 
-    def _initFromRow(self, row):
+    @classmethod
+    def _rowAttributes(cls): #@NoSelf
+        return (
+            "_resourceID",
+            "_name",
+            "_uid",
+            "_md5",
+            "_size",
+            "_created",
+            "_modified",
+        )
+
+
+    @classmethod
+    def _otherSerializedAttributes(cls): #@NoSelf
+        return (
+            "_componentChanged",
+        )
+
+
+    def externalize(self):
         """
-        Given a select result using the columns from L{_allColumns}, initialize
-        the object resource state.
+        Create a dictionary mapping key attributes so this object can be sent over a cross-pod call
+        and reconstituted at the other end. Note that the other end may have a different schema so
+        the attributes may not match exactly and will need to be processed accordingly.
         """
-        (self._resourceID,
-         self._name,
-         self._uid,
-         self._md5,
-         self._size,
-         self._created,
-         self._modified,) = tuple(row)
+        return dict([(attr[1:], getattr(self, attr, None)) for attr in itertools.chain(self._rowAttributes(), self._otherSerializedAttributes())])
 
 
+    @classmethod
     @inlineCallbacks
+    def internalize(cls, parent, mapping):
+        """
+        Given a mapping generated by L{externalize}, convert the values into an array of database
+        like items that conforms to the ordering of L{_allColumns} so it can be fed into L{makeClass}.
+        Note that there may be a schema mismatch with the external data, so treat missing items as
+        C{None} and ignore extra items.
+        """
+
+        child = yield cls.makeClass(parent, [mapping.get(row[1:]) for row in cls._rowAttributes()])
+        for attr in cls._otherSerializedAttributes():
+            setattr(child, attr, mapping.get(attr[1:]))
+        returnValue(child)
+
+
+    @inlineCallbacks
     def _loadPropertyStore(self, props=None, created=False):
         if props is None:
             if self._parentCollection.objectResourcesHaveProperties():
@@ -5060,7 +5609,7 @@
         self._locked = True
 
 
-    def setComponent(self, component, inserting=False, options=None):
+    def setComponent(self, component, inserting=False):
         raise NotImplementedError
 
 
@@ -5093,9 +5642,15 @@
         """
 
         yield self.moveValidation(destination, name)
-        yield self._parentCollection.moveObjectResource(self, destination, name)
 
+        # If possible we do a "fast" move by simply fixing up the database information directly rather than
+        # re-writing any data. That is only possible when the source and destination are on this pod.
+        if not self._parentCollection.external() and not destination.external():
+            yield self._parentCollection.moveObjectResource(self, destination, name)
+        else:
+            yield self._parentCollection.moveObjectResourceCreateDelete(self, destination, name)
 
+
     def moveValidation(self, destination, name):
         raise NotImplementedError
 
@@ -5116,7 +5671,8 @@
         self._size = None
         self._created = None
         self._modified = None
-        self._notificationData = None
+        self._textData = None
+        self._cachedComponent = None
 
 
     def removeNotifyCategory(self):
@@ -5172,19 +5728,19 @@
 
     @inlineCallbacks
     def _text(self):
-        if self._notificationData is None:
+        if self._textData is None:
             texts = (
                 yield self._textByIDQuery.on(self._txn,
                                              resourceID=self._resourceID)
             )
             if texts:
                 text = texts[0][0]
-                self._notificationData = text
+                self._textData = text
                 returnValue(text)
             else:
                 raise ConcurrentModification()
         else:
-            returnValue(self._notificationData)
+            returnValue(self._textData)
 
 
 
@@ -5248,6 +5804,15 @@
             resourceID = rows[0][0]
             created = False
         elif create:
+            # Determine if the user is local or external
+            record = txn.directoryService().recordWithUID(uid)
+            if record is None:
+                raise DirectoryRecordNotFoundError("Cannot create home for UID since no directory record exists: {}".format(uid))
+
+            state = _HOME_STATUS_NORMAL if record.thisServer() else _HOME_STATUS_EXTERNAL
+            if state == _HOME_STATUS_EXTERNAL:
+                raise RecordNotAllowedError("Cannot store notifications for external user: {}".format(uid))
+
             # Use savepoint so we can do a partial rollback if there is a race
             # condition where this row has already been inserted
             savepoint = SavepointAction("notificationsWithUID")
@@ -5370,6 +5935,7 @@
         Where=schema.NOTIFICATION.NOTIFICATION_HOME_RESOURCE_ID ==
         Parameter("resourceID"))
 
+
     @inlineCallbacks
     def listNotificationObjects(self):
         if self._notificationNames is None:

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_dump.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_dump.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_dump.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.test.test_sql_tables -*-
 ##
-# 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.

Copied: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_external.py (from rev 12321, CalendarServer/trunk/txdav/common/datastore/sql_external.py)
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_external.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_external.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -0,0 +1,470 @@
+# -*- test-case-name: txdav.caldav.datastore.test.test_sql,txdav.carddav.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 data store.
+"""
+
+from twext.internet.decorate import memoizedKey
+from twext.python.log import Logger
+
+from twisted.internet.defer import inlineCallbacks, returnValue, succeed
+
+from txdav.base.propertystore.sql import PropertyStore
+from txdav.common.datastore.sql import CommonHome, CommonHomeChild, \
+    CommonObjectResource
+from txdav.common.datastore.sql_tables import _HOME_STATUS_EXTERNAL
+from txdav.common.icommondatastore import NonExistentExternalShare, \
+    ExternalShareFailed
+
+
+log = Logger()
+
+class CommonHomeExternal(CommonHome):
+    """
+    A CommonHome for a user not hosted on this system, but on another pod. This is needed to provide a
+    "reference" to the external user so we can share with them. Actual operations to list child resources, etc
+    are all stubbed out since no data for the user is actually hosted in this store.
+    """
+
+    def __init__(self, transaction, ownerUID, resourceID):
+        super(CommonHomeExternal, self).__init__(transaction, ownerUID)
+        self._resourceID = resourceID
+        self._status = _HOME_STATUS_EXTERNAL
+
+
+    def initFromStore(self, no_cache=False):
+        """
+        Never called - this should be done by CommonHome.initFromStore only.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def external(self):
+        """
+        Is this an external home.
+
+        @return: a string.
+        """
+        return True
+
+
+    def children(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def loadChildren(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def listChildren(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def objectWithShareUID(self, shareUID):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def invitedObjectWithShareUID(self, shareUID):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    @memoizedKey("name", "_children")
+    @inlineCallbacks
+    def createChildWithName(self, name, externalID=None):
+        """
+        No real children - only external ones.
+        """
+        if externalID is None:
+            raise AssertionError("CommonHomeExternal: not supported")
+        child = yield super(CommonHomeExternal, self).createChildWithName(name, externalID)
+        returnValue(child)
+
+
+    def removeChildWithName(self, name):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    @inlineCallbacks
+    def removeExternalChild(self, child):
+        """
+        Remove an external child. Check that it is invalid or unused before calling this because if there
+        are valid references to it, removing will break things.
+        """
+        if child._externalID is None:
+            raise AssertionError("CommonHomeExternal: not supported")
+        yield super(CommonHomeExternal, self).removeChildWithName(child.name())
+
+
+    def syncToken(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def resourceNamesSinceRevision(self, revision, depth):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    @inlineCallbacks
+    def _loadPropertyStore(self):
+        """
+        No property store - stub to a NonePropertyStore.
+        """
+        props = yield PropertyStore.load(
+            self.uid(),
+            self.uid(),
+            self._txn,
+            self._resourceID,
+            notifyCallback=self.notifyChanged
+        )
+        self._propertyStore = props
+
+
+    def properties(self):
+        return self._propertyStore
+
+
+    def objectResourcesWithUID(self, uid, ignore_children=[], allowShared=True):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def objectResourceWithID(self, rid):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+    def notifyChanged(self):
+        """
+        Notifications are not handled for external homes - make this a no-op.
+        """
+        return succeed(None)
+
+
+    def bumpModified(self):
+        """
+        No changes recorded for external homes - make this a no-op.
+        """
+        return succeed(None)
+
+
+    def removeUnacceptedShares(self):
+        """
+        No children.
+        """
+        raise AssertionError("CommonHomeExternal: not supported")
+
+
+#    def ownerHomeAndChildNameForChildID(self, resourceID):
+#        """
+#        No children.
+#        """
+#        raise AssertionError("CommonHomeExternal: not supported")
+
+
+
+class CommonHomeChildExternal(CommonHomeChild):
+    """
+    A CommonHomeChild for a collection not hosted on this system, but on another pod. This will forward
+    specific apis to the other pod using cross-pod requests.
+    """
+
+    def external(self):
+        """
+        Is this an external home.
+
+        @return: a string.
+        """
+        return True
+
+
+    def fixNonExistentExternalShare(self):
+        """
+        An external request has returned and indicates the external share no longer exists. That
+        means this shared resource is an "orphan" and needs to be remove (uninvited) to clean things up.
+        """
+        log.error("Non-existent share detected and removed for {share}", share=self)
+        ownerView = yield self.ownerView()
+        yield ownerView.removeShare(self)
+
+
+    @inlineCallbacks
+    def remove(self):
+        """
+        External shares are never removed directly - instead they must be "uninvited". However,
+        the owner's external calendar can be removed.
+        """
+        if self.owned():
+            yield super(CommonHomeChildExternal, self).remove()
+        else:
+            raise AssertionError("CommonHomeChildExternal: not supported")
+
+
+    @inlineCallbacks
+    def listObjectResources(self):
+        if self._objectNames is None:
+            try:
+                self._objectNames = yield self._txn.store().conduit.send_listobjects(self)
+            except NonExistentExternalShare:
+                yield self.fixNonExistentExternalShare()
+                raise ExternalShareFailed("External share does not exist")
+
+        returnValue(self._objectNames)
+
+
+    @inlineCallbacks
+    def countObjectResources(self):
+        if self._objectNames is None:
+            try:
+                count = yield self._txn.store().conduit.send_countobjects(self)
+            except NonExistentExternalShare:
+                yield self.fixNonExistentExternalShare()
+                raise ExternalShareFailed("External share does not exist")
+            returnValue(count)
+        returnValue(len(self._objectNames))
+
+
+    @inlineCallbacks
+    def resourceNameForUID(self, uid):
+        try:
+            resource = self._objects[uid]
+            returnValue(resource.name() if resource else None)
+        except KeyError:
+            pass
+
+        try:
+            name = yield self._txn.store().conduit.send_resourcenameforuid(self, uid)
+        except NonExistentExternalShare:
+            yield self.fixNonExistentExternalShare()
+            raise ExternalShareFailed("External share does not exist")
+
+        if name:
+            returnValue(name)
+        else:
+            self._objects[uid] = None
+            returnValue(None)
+
+
+    @inlineCallbacks
+    def resourceUIDForName(self, name):
+        try:
+            resource = self._objects[name]
+            returnValue(resource.uid() if resource else None)
+        except KeyError:
+            pass
+
+        try:
+            uid = yield self._txn.store().conduit.send_resourceuidforname(self, name)
+        except NonExistentExternalShare:
+            yield self.fixNonExistentExternalShare()
+            raise ExternalShareFailed("External share does not exist")
+
+        if uid:
+            returnValue(uid)
+        else:
+            self._objects[name] = None
+            returnValue(None)
+
+
+    @inlineCallbacks
+    def moveObjectResource(self, child, newparent, newname=None):
+        """
+        The base class does an optimization to avoid removing/re-creating
+        the actual object resource data. That might not always be possible
+        with external shares if the shared resource is moved to a collection
+        that is not shared or shared by someone else on a different (third)
+        pod. The best bet here is to treat the move as a delete/create.
+        """
+        raise NotImplementedError("TODO: external resource")
+
+
+    @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}
+        """
+
+        try:
+            result = yield self._txn.store().conduit.send_movehere(self, name, str(component))
+        except NonExistentExternalShare:
+            yield self.fixNonExistentExternalShare()
+            raise ExternalShareFailed("External share does not exist")
+        returnValue(result)
+
+
+    @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}
+        """
+
+        try:
+            result = yield self._txn.store().conduit.send_moveaway(self, rid)
+        except NonExistentExternalShare:
+            yield self.fixNonExistentExternalShare()
+            raise ExternalShareFailed("External share does not exist")
+        returnValue(result)
+
+
+    @inlineCallbacks
+    def syncToken(self):
+        if self._syncTokenRevision is None:
+            try:
+                token = yield self._txn.store().conduit.send_synctoken(self)
+                self._syncTokenRevision = self.revisionFromToken(token)
+            except NonExistentExternalShare:
+                yield self.fixNonExistentExternalShare()
+                raise ExternalShareFailed("External share does not exist")
+        returnValue(("%s_%s" % (self._externalID, self._syncTokenRevision,)))
+
+
+    @inlineCallbacks
+    def resourceNamesSinceRevision(self, revision):
+        try:
+            names = yield self._txn.store().conduit.send_resourcenamessincerevision(self, revision)
+        except NonExistentExternalShare:
+            yield self.fixNonExistentExternalShare()
+            raise ExternalShareFailed("External share does not exist")
+
+        returnValue(names)
+
+
+    @inlineCallbacks
+    def search(self, filter, **kwargs):
+        try:
+            results = yield self._txn.store().conduit.send_search(self, filter.serialize(), **kwargs)
+        except NonExistentExternalShare:
+            yield self.fixNonExistentExternalShare()
+            raise ExternalShareFailed("External share does not exist")
+
+        returnValue(results)
+
+
+
+class CommonObjectResourceExternal(CommonObjectResource):
+    """
+    A CommonObjectResource for a resource not hosted on this system, but on another pod. This will forward
+    specific apis to the other pod using cross-pod requests.
+    """
+
+    @classmethod
+    @inlineCallbacks
+    def loadAllObjects(cls, parent):
+        mapping_list = yield parent._txn.store().conduit.send_loadallobjects(parent, None)
+
+        results = []
+        if mapping_list:
+            for mapping in mapping_list:
+                child = yield cls.internalize(parent, mapping)
+                results.append(child)
+        returnValue(results)
+
+
+    @classmethod
+    @inlineCallbacks
+    def loadAllObjectsWithNames(cls, parent, names):
+        mapping_list = yield parent._txn.store().conduit.send_loadallobjectswithnames(parent, None, names)
+
+        results = []
+        if mapping_list:
+            for mapping in mapping_list:
+                child = yield cls.internalize(parent, mapping)
+                results.append(child)
+        returnValue(results)
+
+
+    @classmethod
+    @inlineCallbacks
+    def objectWith(cls, parent, name=None, uid=None, resourceID=None):
+        mapping = yield parent._txn.store().conduit.send_objectwith(parent, None, name, uid, resourceID)
+
+        if mapping:
+            child = yield cls.internalize(parent, mapping)
+            returnValue(child)
+        else:
+            returnValue(None)
+
+
+    @classmethod
+    @inlineCallbacks
+    def create(cls, parent, name, component, options=None):
+        mapping = yield parent._txn.store().conduit.send_create(parent, None, name, str(component), options=options)
+
+        if mapping:
+            child = yield cls.internalize(parent, mapping)
+            returnValue(child)
+        else:
+            returnValue(None)
+
+
+    @inlineCallbacks
+    def setComponent(self, component, **kwargs):
+        self._componentChanged = yield self._txn.store().conduit.send_setcomponent(self.parentCollection(), self, str(component), **kwargs)
+        self._cachedComponent = None
+        returnValue(self._componentChanged)
+
+
+    @inlineCallbacks
+    def component(self):
+        if self._cachedComponent is None:
+            text = yield self._txn.store().conduit.send_component(self.parentCollection(), self)
+            self._cachedComponent = self._componentClass.fromString(text)
+
+        returnValue(self._cachedComponent)
+
+
+    @inlineCallbacks
+    def remove(self):
+        yield self._txn.store().conduit.send_remove(self.parentCollection(), self)

Deleted: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_legacy.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_legacy.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_legacy.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,886 +0,0 @@
-# -*- test-case-name: twistedcaldav.test.test_sharing,twistedcaldav.test.test_calendarquery -*-
-##
-# Copyright (c) 2010-2013 Apple Inc. All 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.
-##
-
-
-"""
-PostgreSQL data store.
-"""
-
-import StringIO
-
-
-from twisted.python import hashlib
-from twisted.internet.defer import succeed, inlineCallbacks, returnValue
-
-from twistedcaldav.config import config
-from twistedcaldav.dateops import normalizeForIndex, pyCalendarTodatetime
-from twistedcaldav.memcachepool import CachePoolUserMixIn
-from twistedcaldav.query import \
-    calendarqueryfilter, calendarquery, addressbookquery, expression, \
-    addressbookqueryfilter
-from twistedcaldav.query.sqlgenerator import sqlgenerator
-
-from txdav.caldav.icalendarstore import TimeRangeLowerLimit, TimeRangeUpperLimit
-from txdav.common.icommondatastore import IndexedSearchException, \
-    ReservationError, NoSuchObjectResourceError
-
-from txdav.common.datastore.sql_tables import schema
-from twext.enterprise.dal.syntax import Parameter, Select
-from twext.python.clsprop import classproperty
-from twext.python.log import Logger
-
-from pycalendar.datetime import DateTime
-from pycalendar.duration import Duration
-
-log = Logger()
-
-indexfbtype_to_icalfbtype = {
-    0: '?',
-    1: 'F',
-    2: 'B',
-    3: 'U',
-    4: 'T',
-}
-
-class MemcachedUIDReserver(CachePoolUserMixIn):
-    log = Logger()
-
-    def __init__(self, index, cachePool=None):
-        self.index = index
-        self._cachePool = cachePool
-
-
-    def _key(self, uid):
-        return 'reservation:%s' % (
-            hashlib.md5('%s:%s' % (uid,
-                                   self.index.resource._resourceID)).hexdigest())
-
-
-    def reserveUID(self, uid):
-        self.log.debug("Reserving UID %r @ %r" % (
-                uid,
-                self.index.resource))
-
-        def _handleFalse(result):
-            if result is False:
-                raise ReservationError(
-                    "UID %s already reserved for calendar collection %s."
-                    % (uid, self.index.resource._name)
-                    )
-
-        d = self.getCachePool().add(self._key(uid),
-                                    'reserved',
-                                    expireTime=config.UIDReservationTimeOut)
-        d.addCallback(_handleFalse)
-        return d
-
-
-    def unreserveUID(self, uid):
-        self.log.debug("Unreserving UID %r @ %r" % (
-                uid,
-                self.index.resource))
-
-        def _handleFalse(result):
-            if result is False:
-                raise ReservationError(
-                    "UID %s is not reserved for calendar collection %s."
-                    % (uid, self.index.resource._resourceID)
-                    )
-
-        d = self.getCachePool().delete(self._key(uid))
-        d.addCallback(_handleFalse)
-        return d
-
-
-    def isReservedUID(self, uid):
-        self.log.debug("Is reserved UID %r @ %r" % (
-                uid,
-                self.index.resource))
-
-        def _checkValue((flags, value)):
-            if value is None:
-                return False
-            else:
-                return True
-
-        d = self.getCachePool().get(self._key(uid))
-        d.addCallback(_checkValue)
-        return d
-
-
-
-class DummyUIDReserver(object):
-    log = Logger()
-
-    def __init__(self, index):
-        self.index = index
-        self.reservations = set()
-
-
-    def _key(self, uid):
-        return 'reservation:%s' % (
-            hashlib.md5('%s:%s' % (uid,
-                                   self.index.resource._resourceID)).hexdigest())
-
-
-    def reserveUID(self, uid):
-        self.log.debug("Reserving UID %r @ %r" % (
-                uid,
-                self.index.resource))
-
-        key = self._key(uid)
-        if key in self.reservations:
-            raise ReservationError(
-                "UID %s already reserved for calendar collection %s."
-                % (uid, self.index.resource._name)
-                )
-        self.reservations.add(key)
-        return succeed(None)
-
-
-    def unreserveUID(self, uid):
-        self.log.debug("Unreserving UID %r @ %r" % (
-                uid,
-                self.index.resource))
-
-        key = self._key(uid)
-        if key in self.reservations:
-            self.reservations.remove(key)
-        return succeed(None)
-
-
-    def isReservedUID(self, uid):
-        self.log.debug("Is reserved UID %r @ %r" % (
-                uid,
-                self.index.resource))
-        key = self._key(uid)
-        return succeed(key in self.reservations)
-
-
-
-class RealSQLBehaviorMixin(object):
-    """
-    Class attributes for 'real' SQL behavior; avoid idiosyncracies of SQLite,
-    use standard SQL constructions, and depend on the full schema in
-    sql_schema/current.sql rather than the partial one in twistedcaldav which depends
-    on the placement of the database in the filesystem for some information.
-    """
-
-    ISOP = " = "
-    STARTSWITHOP = ENDSWITHOP = CONTAINSOP = " LIKE "
-    NOTSTARTSWITHOP = NOTENDSWITHOP = NOTCONTAINSOP = " NOT LIKE "
-
-    def containsArgument(self, arg):
-        return "%%%s%%" % (arg,)
-
-
-    def startswithArgument(self, arg):
-        return "%s%%" % (arg,)
-
-
-    def endswithArgument(self, arg):
-        return "%%%s" % (arg,)
-
-
-
-class CalDAVSQLBehaviorMixin(RealSQLBehaviorMixin):
-    """
-    Query generator for CalDAV indexed searches.
-    """
-
-    FIELDS = {
-        "TYPE": "CALENDAR_OBJECT.ICALENDAR_TYPE",
-        "UID": "CALENDAR_OBJECT.ICALENDAR_UID",
-    }
-    RESOURCEDB = "CALENDAR_OBJECT"
-    TIMESPANDB = "TIME_RANGE"
-
-    TIMESPANTEST = "((TIME_RANGE.FLOATING = FALSE AND TIME_RANGE.START_DATE < %s AND TIME_RANGE.END_DATE > %s) OR (TIME_RANGE.FLOATING = TRUE AND TIME_RANGE.START_DATE < %s AND TIME_RANGE.END_DATE > %s))"
-    TIMESPANTEST_NOEND = "((TIME_RANGE.FLOATING = FALSE AND TIME_RANGE.END_DATE > %s) OR (TIME_RANGE.FLOATING = TRUE AND TIME_RANGE.END_DATE > %s))"
-    TIMESPANTEST_NOSTART = "((TIME_RANGE.FLOATING = FALSE AND TIME_RANGE.START_DATE < %s) OR (TIME_RANGE.FLOATING = TRUE AND TIME_RANGE.START_DATE < %s))"
-    TIMESPANTEST_TAIL_PIECE = " AND TIME_RANGE.CALENDAR_OBJECT_RESOURCE_ID = CALENDAR_OBJECT.RESOURCE_ID AND TIME_RANGE.CALENDAR_RESOURCE_ID = %s"
-    TIMESPANTEST_JOIN_ON_PIECE = "TIME_RANGE.INSTANCE_ID = TRANSPARENCY.TIME_RANGE_INSTANCE_ID AND TRANSPARENCY.USER_ID = %s"
-
-    def generate(self):
-        """
-        Generate the actual SQL 'where ...' expression from the passed in
-        expression tree.
-
-        @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.
-        """
-
-        # Init state
-        self.sout = StringIO.StringIO()
-        self.arguments = []
-        self.substitutions = []
-        self.usedtimespan = False
-
-        # For SQL data DB we need to restrict the query to just the targeted calendar resource-id if provided
-        if self.calendarid:
-
-            test = expression.isExpression("CALENDAR_OBJECT.CALENDAR_RESOURCE_ID", str(self.calendarid), True)
-
-            # Since timerange expression already have the calendar resource-id test in them, do not
-            # add the additional term to those. When the additional term is added, add it as the first
-            # component in the AND expression to hopefully get the DB to use its index first
-
-            # Top-level timerange expression already has calendar resource-id restriction in it
-            if isinstance(self.expression, expression.timerangeExpression):
-                pass
-
-            # Top-level OR - check each component
-            elif isinstance(self.expression, expression.orExpression):
-
-                def _hasTopLevelTimerange(testexpr):
-                    if isinstance(testexpr, expression.timerangeExpression):
-                        return True
-                    elif isinstance(testexpr, expression.andExpression):
-                        return any([isinstance(expr, expression.timerangeExpression) for expr in testexpr.expressions])
-                    else:
-                        return False
-
-                hasTimerange = any([_hasTopLevelTimerange(expr) for expr in self.expression.expressions])
-
-                if hasTimerange:
-                    # timerange expression forces a join on calendarid
-                    pass
-                else:
-                    # AND the whole thing with calendarid
-                    self.expression = test.andWith(self.expression)
-
-            # Top-level AND - only add additional expression if timerange not present
-            elif isinstance(self.expression, expression.andExpression):
-                hasTimerange = any([isinstance(expr, expression.timerangeExpression) for expr in self.expression.expressions])
-                if not hasTimerange:
-                    # AND the whole thing
-                    self.expression = test.andWith(self.expression)
-
-            # Just AND the entire thing
-            else:
-                self.expression = test.andWith(self.expression)
-
-        # Generate ' where ...' partial statement
-        self.generateExpression(self.expression)
-
-        # Prefix with ' from ...' partial statement
-        select = self.FROM + self.RESOURCEDB
-        if self.usedtimespan:
-
-            # Free busy needs transparency join
-            if self.freebusy:
-                self.frontArgument(self.userid)
-                select += ", %s LEFT OUTER JOIN %s ON (%s)" % (
-                    self.TIMESPANDB,
-                    self.TRANSPARENCYDB,
-                    self.TIMESPANTEST_JOIN_ON_PIECE
-                )
-            else:
-                select += ", %s" % (
-                    self.TIMESPANDB,
-                )
-        select += self.WHERE
-        if self.usedtimespan:
-            select += "("
-        select += self.sout.getvalue()
-        if self.usedtimespan:
-            if self.calendarid:
-                self.setArgument(self.calendarid)
-            select += ")%s" % (self.TIMESPANTEST_TAIL_PIECE,)
-
-        select = select % tuple(self.substitutions)
-
-        return select, self.arguments
-
-
-
-class FormatParamStyleMixin(object):
-    """
-    Mixin for overriding methods on sqlgenerator that generate arguments
-    according to format/pyformat rules rather than the base class's 'numeric'
-    rules.
-    """
-
-    def addArgument(self, arg):
-        self.arguments.append(arg)
-        self.substitutions.append("%s")
-        self.sout.write("%s")
-
-
-    def setArgument(self, arg):
-        self.arguments.append(arg)
-        self.substitutions.append("%s")
-
-
-    def frontArgument(self, arg):
-        self.arguments.insert(0, arg)
-        self.substitutions.insert(0, "%s")
-
-
-
-class postgresqlgenerator(FormatParamStyleMixin, CalDAVSQLBehaviorMixin,
-                          sqlgenerator):
-    """
-    Query generator for PostgreSQL indexed searches.
-    """
-
-
-
-def fixbools(sqltext):
-    return sqltext.replace("TRUE", "1").replace("FALSE", "0")
-
-
-
-class oraclesqlgenerator(CalDAVSQLBehaviorMixin, sqlgenerator):
-    """
-    Query generator for Oracle indexed searches.
-    """
-    TIMESPANTEST = fixbools(CalDAVSQLBehaviorMixin.TIMESPANTEST)
-    TIMESPANTEST_NOEND = fixbools(CalDAVSQLBehaviorMixin.TIMESPANTEST_NOEND)
-    TIMESPANTEST_NOSTART = fixbools(CalDAVSQLBehaviorMixin.TIMESPANTEST_NOSTART)
-    TIMESPANTEST_TAIL_PIECE = fixbools(
-        CalDAVSQLBehaviorMixin.TIMESPANTEST_TAIL_PIECE)
-    TIMESPANTEST_JOIN_ON_PIECE = fixbools(
-        CalDAVSQLBehaviorMixin.TIMESPANTEST_JOIN_ON_PIECE)
-
-
-
-class LegacyIndexHelper(object):
-    log = Logger()
-
-    @inlineCallbacks
-    def isAllowedUID(self, uid, *names):
-        """
-        Checks to see whether to allow an operation which would add the
-        specified UID to the index.  Specifically, the operation may not
-        violate the constraint that UIDs must be unique.
-        @param uid: the UID to check
-        @param names: the names of resources being replaced or deleted by the
-            operation; UIDs associated with these resources are not checked.
-        @return: True if the UID is not in the index and is not reserved,
-            False otherwise.
-        """
-        rname = yield self.resourceNameForUID(uid)
-        returnValue(rname is None or rname in names)
-
-
-    def reserveUID(self, uid):
-        return self.reserver.reserveUID(uid)
-
-
-    def unreserveUID(self, uid):
-        return self.reserver.unreserveUID(uid)
-
-
-    def isReservedUID(self, uid):
-        return self.reserver.isReservedUID(uid)
-
-
-
-class PostgresLegacyIndexEmulator(LegacyIndexHelper):
-    """
-    Emulator for L{twistedcaldv.index.Index} and
-    L{twistedcaldv.index.IndexSchedule}.
-    """
-
-    def __init__(self, calendar):
-        self.resource = self.calendar = calendar
-        if (
-            hasattr(config, "Memcached") and
-            config.Memcached.Pools.Default.ClientEnabled
-        ):
-            self.reserver = MemcachedUIDReserver(self)
-        else:
-            # This is only used with unit tests
-            self.reserver = DummyUIDReserver(self)
-
-    _objectSchema = schema.CALENDAR_OBJECT
-
-    @property
-    def _txn(self):
-        return self.calendar._txn
-
-
-    @inlineCallbacks
-    def isAllowedUID(self, uid, *names):
-        """
-        Checks to see whether to allow an operation which would add the
-        specified UID to the index.  Specifically, the operation may not
-        violate the constraint that UIDs must be unique.
-        @param uid: the UID to check
-        @param names: the names of resources being replaced or deleted by the
-            operation; UIDs associated with these resources are not checked.
-        @return: True if the UID is not in the index and is not reserved,
-            False otherwise.
-        """
-        rname = yield self.resourceNameForUID(uid)
-        returnValue(rname is None or rname in names)
-
-
-    @inlineCallbacks
-    def resourceUIDForName(self, name):
-        uid = yield self.calendar.resourceUIDForName(name)
-        returnValue(uid)
-
-
-    @inlineCallbacks
-    def resourceNameForUID(self, uid):
-        name = yield self.calendar.resourceNameForUID(uid)
-        returnValue(name)
-
-
-    @classproperty
-    def _notExpandedWithinQuery(cls): #@NoSelf
-        """
-        DAL query to satisfy L{PostgresLegacyIndexEmulator.notExpandedBeyond}.
-        """
-        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.calendar._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.calendar.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 indexedSearch(self, filter, useruid='', fbtype=False):
-        """
-        Finds resources matching the given qualifiers.
-
-        @param filter: the L{Filter} for the calendar-query to execute.
-
-        @return: a L{Deferred} which fires with an iterable of tuples for each
-            resource matching the given C{qualifiers}. The tuples are C{(name,
-            uid, type)}, where C{name} is the resource name, C{uid} is the
-            resource UID, and C{type} is the resource iCalendar component type.
-        """
-        # Detect which style of parameter-generation we're using.  Naming is a
-        # little off here, because the reason we're using the numeric one is
-        # that it happens to be used by the oracle binding that we're using,
-        # whereas the postgres binding happens to use the 'pyformat' (e.g. %s)
-        # parameter style.
-        if self.calendar._txn.paramstyle == 'numeric':
-            generator = oraclesqlgenerator
-        else:
-            generator = postgresqlgenerator
-        # Make sure we have a proper Filter element and get the partial SQL
-        # statement to use.
-        if isinstance(filter, calendarqueryfilter.Filter):
-            qualifiers = calendarquery.sqlcalendarquery(
-                filter, self.calendar._resourceID, useruid, fbtype,
-                generator=generator
-            )
-            if qualifiers 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)
-
-            else:
-                # We cannot handle this filter in an indexed search
-                raise IndexedSearchException()
-        else:
-            qualifiers = None
-
-        # Perform the search
-        if qualifiers is None:
-            rowiter = yield self.bruteForceSearch()
-        else:
-            if fbtype:
-                # For a free-busy time-range query we return all instances
-                rowiter = yield self._txn.execSQL(
-                    """
-                    select DISTINCT
-                        CALENDAR_OBJECT.RESOURCE_NAME,
-                        CALENDAR_OBJECT.ICALENDAR_UID,
-                        CALENDAR_OBJECT.ICALENDAR_TYPE,
-                        CALENDAR_OBJECT.ORGANIZER,
-                        TIME_RANGE.FLOATING, TIME_RANGE.START_DATE,
-                        TIME_RANGE.END_DATE, TIME_RANGE.FBTYPE,
-                        TIME_RANGE.TRANSPARENT, TRANSPARENCY.TRANSPARENT
-                    """ +
-                    qualifiers[0],
-                    qualifiers[1]
-                )
-            else:
-                rowiter = yield self._txn.execSQL(
-                    """
-                    select
-                        DISTINCT CALENDAR_OBJECT.RESOURCE_NAME,
-                        CALENDAR_OBJECT.ICALENDAR_UID,
-                        CALENDAR_OBJECT.ICALENDAR_TYPE
-                    """ +
-                    qualifiers[0],
-                    qualifiers[1]
-                )
-
-        # 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)
-
-
-    @classproperty
-    def _bruteForceQuery(cls): #@NoSelf
-        """
-        DAL query for all C{CALENDAR_OBJECT} rows in the calendar represented by
-        this index.
-        """
-        obj = cls._objectSchema
-        return Select(
-            [obj.RESOURCE_NAME, obj.ICALENDAR_UID, obj.ICALENDAR_TYPE],
-            From=obj, Where=obj.PARENT_RESOURCE_ID == Parameter("resourceID")
-        )
-
-
-    def bruteForceSearch(self):
-        return self._bruteForceQuery.on(
-            self._txn, resourceID=self.resource._resourceID)
-
-
-    @inlineCallbacks
-    def resourcesExist(self, names):
-        returnValue(list(set(names).intersection(
-            set((yield self.calendar.listCalendarObjects())))))
-
-
-    @classproperty
-    def _resourceExistsQuery(cls): #@NoSelf
-        """
-        DAL query to determine whether a calendar object exists in the
-        collection represented by this index.
-        """
-        obj = cls._objectSchema
-        return Select(
-            [obj.RESOURCE_NAME], From=obj,
-            Where=(obj.RESOURCE_NAME == Parameter("name"))
-            .And(obj.PARENT_RESOURCE_ID == Parameter("resourceID"))
-        )
-
-
-    @inlineCallbacks
-    def resourceExists(self, name):
-        returnValue((bool(
-            (yield self._resourceExistsQuery.on(
-                self._txn, name=name, resourceID=self.resource._resourceID))
-        )))
-
-
-
-class PostgresLegacyInboxIndexEmulator(PostgresLegacyIndexEmulator):
-    """
-    UIDs need not be unique in the 'inbox' calendar, so override those
-    behaviors intended to ensure that.
-    """
-
-    def isAllowedUID(self):
-        return succeed(True)
-
-
-    def reserveUID(self, uid):
-        return succeed(None)
-
-
-    def unreserveUID(self, uid):
-        return succeed(None)
-
-
-    def isReservedUID(self, uid):
-        return succeed(False)
-
-
-
-# CARDDAV
-
-class CardDAVSQLBehaviorMixin(RealSQLBehaviorMixin):
-    """
-    Query generator for CardDAV indexed searches.
-    """
-
-    FIELDS = {
-        "UID": "ADDRESSBOOK_OBJECT.VCARD_UID",
-    }
-    RESOURCEDB = "ADDRESSBOOK_OBJECT"
-
-    def generate(self):
-        """
-        Generate the actual SQL 'where ...' expression from the passed in
-        expression tree.
-
-        @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.
-        """
-
-        # Init state
-        self.sout = StringIO.StringIO()
-        self.arguments = []
-        self.substitutions = []
-
-        # For SQL data DB we need to restrict the query to just the targeted calendar resource-id if provided
-        if self.calendarid:
-
-            # AND the whole thing
-            test = expression.isExpression("ADDRESSBOOK_OBJECT.ADDRESSBOOK_HOME_RESOURCE_ID", str(self.calendarid), True)
-            self.expression = test.andWith(self.expression)
-
-        # Generate ' where ...' partial statement
-        self.sout.write(self.WHERE)
-        self.generateExpression(self.expression)
-
-        # Prefix with ' from ...' partial statement
-        select = self.FROM + self.RESOURCEDB
-        select += self.sout.getvalue()
-
-        select = select % tuple(self.substitutions)
-
-        return select, self.arguments
-
-
-
-class postgresqladbkgenerator(FormatParamStyleMixin, CardDAVSQLBehaviorMixin, sqlgenerator):
-    """
-    Query generator for PostgreSQL indexed searches.
-    """
-
-
-
-class oraclesqladbkgenerator(CardDAVSQLBehaviorMixin, sqlgenerator):
-    """
-    Query generator for Oracle indexed searches.
-    """
-
-
-
-class PostgresLegacyABIndexEmulator(LegacyIndexHelper):
-    """
-    Emulator for L{twistedcaldv.index.Index} and
-    L{twistedcaldv.index.IndexSchedule}.
-    """
-
-    _objectSchema = schema.ADDRESSBOOK_OBJECT
-
-    def __init__(self, addressbook):
-        self.resource = self.addressbook = addressbook
-        if (
-            hasattr(config, "Memcached") and
-            config.Memcached.Pools.Default.ClientEnabled
-        ):
-            self.reserver = MemcachedUIDReserver(self)
-        else:
-            # This is only used with unit tests
-            self.reserver = DummyUIDReserver(self)
-
-
-    @property
-    def _txn(self):
-        return self.addressbook._txn
-
-
-    @inlineCallbacks
-    def resourceUIDForName(self, name):
-        obj = yield self.addressbook.addressbookObjectWithName(name)
-        if obj is None:
-            returnValue(None)
-        returnValue(obj.uid())
-
-
-    @inlineCallbacks
-    def resourceNameForUID(self, uid):
-        obj = yield self.addressbook.addressbookObjectWithUID(uid)
-        if obj is None:
-            returnValue(None)
-        returnValue(obj.name())
-
-
-    def searchValid(self, filter):
-        if isinstance(filter, addressbookqueryfilter.Filter):
-            qualifiers = addressbookquery.sqladdressbookquery(filter)
-        else:
-            qualifiers = None
-
-        return qualifiers is not None
-
-
-    @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, type)}, where
-            C{name} is the resource name, C{uid} is the resource UID, and
-            C{type} is the resource iCalendar component type.x
-        """
-        if self.addressbook._txn.paramstyle == 'numeric':
-            generator = oraclesqladbkgenerator
-        else:
-            generator = postgresqladbkgenerator
-        # Make sure we have a proper Filter element and get the partial SQL statement to use.
-        if isinstance(filter, addressbookqueryfilter.Filter):
-            qualifiers = addressbookquery.sqladdressbookquery(
-                filter, self.addressbook._resourceID, generator=generator)
-        else:
-            qualifiers = None
-        if qualifiers is not None:
-            rowiter = yield self._txn.execSQL(
-                "select DISTINCT ADDRESSBOOK_OBJECT.RESOURCE_NAME, ADDRESSBOOK_OBJECT.VCARD_UID" +
-                qualifiers[0],
-                qualifiers[1]
-            )
-        else:
-            rowiter = yield Select(
-                [self._objectSchema.RESOURCE_NAME,
-                 self._objectSchema.VCARD_UID],
-                From=self._objectSchema,
-                Where=self._objectSchema.ADDRESSBOOK_HOME_RESOURCE_ID ==
-                self.addressbook._resourceID
-            ).on(self.addressbook._txn)
-
-        returnValue(list(rowiter))
-
-
-    def indexedSearch(self, filter, useruid='', fbtype=False):
-        """
-        Always raise L{IndexedSearchException}, since these indexes are not
-        fully implemented yet.
-        """
-        raise IndexedSearchException()
-
-
-    @inlineCallbacks
-    def resourcesExist(self, names):
-        returnValue(list(set(names).intersection(
-            set((yield self.addressbook.listAddressBookObjects())))))

Modified: 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-oracle-dialect.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/current-oracle-dialect.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -18,9 +18,17 @@
 create table CALENDAR_HOME (
     "RESOURCE_ID" integer primary key,
     "OWNER_UID" nvarchar2(255) unique,
+    "STATUS" integer default 0 not null,
     "DATAVERSION" integer default 0 not null
 );
 
+create table HOME_STATUS (
+    "ID" integer primary key,
+    "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into HOME_STATUS (DESCRIPTION, ID) values ('normal', 0);
+insert into HOME_STATUS (DESCRIPTION, ID) values ('external', 1);
 create table CALENDAR (
     "RESOURCE_ID" integer primary key
 );
@@ -50,6 +58,7 @@
 create table NOTIFICATION_HOME (
     "RESOURCE_ID" integer primary key,
     "OWNER_UID" nvarchar2(255) unique,
+    "STATUS" integer default 0 not null,
     "DATAVERSION" integer default 0 not null
 );
 
@@ -68,6 +77,7 @@
 create table CALENDAR_BIND (
     "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
     "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+    "EXTERNAL_ID" integer default null,
     "CALENDAR_RESOURCE_NAME" nvarchar2(255),
     "BIND_MODE" integer not null,
     "BIND_STATUS" integer not null,
@@ -210,6 +220,7 @@
     "RESOURCE_ID" integer primary key,
     "ADDRESSBOOK_PROPERTY_STORE_ID" integer not null,
     "OWNER_UID" nvarchar2(255) unique,
+    "STATUS" integer default 0 not null,
     "DATAVERSION" integer default 0 not null
 );
 
@@ -223,6 +234,7 @@
 create table SHARED_ADDRESSBOOK_BIND (
     "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
     "OWNER_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+    "EXTERNAL_ID" integer default null,
     "ADDRESSBOOK_RESOURCE_NAME" nvarchar2(255),
     "BIND_MODE" integer not null,
     "BIND_STATUS" integer not null,
@@ -275,6 +287,7 @@
 create table SHARED_GROUP_BIND (
     "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
     "GROUP_RESOURCE_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    "EXTERNAL_ID" integer default null,
     "GROUP_ADDRESSBOOK_NAME" nvarchar2(255),
     "BIND_MODE" integer not null,
     "BIND_STATUS" integer not null,
@@ -446,6 +459,10 @@
     CALENDAR_HOME_RESOURCE_ID
 );
 
+create index ATTACHMENT_DROPBOX_ID_5073cf23 on ATTACHMENT (
+    DROPBOX_ID
+);
+
 create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
     CALENDAR_OBJECT_RESOURCE_ID
 );

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/current.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/current.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -53,10 +53,22 @@
 
 create table CALENDAR_HOME (
   RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  OWNER_UID        varchar(255) not null unique,                                 -- implicit index
+  OWNER_UID        varchar(255) not null unique,                                -- implicit index
+  STATUS           integer      default 0 not null,                             -- enum HOME_STATUS
   DATAVERSION      integer      default 0 not null
 );
 
+-- Enumeration of statuses
+
+create table HOME_STATUS (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into HOME_STATUS values (0, 'normal' );
+insert into HOME_STATUS values (1, 'external');
+
+
 --------------
 -- Calendar --
 --------------
@@ -65,6 +77,7 @@
   RESOURCE_ID integer   primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
 );
 
+
 ----------------------------
 -- Calendar Home Metadata --
 ----------------------------
@@ -91,6 +104,7 @@
 create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
 	CALENDAR_HOME_METADATA(DEFAULT_POLLS);
 
+
 -----------------------
 -- Calendar Metadata --
 -----------------------
@@ -110,6 +124,7 @@
 create table NOTIFICATION_HOME (
   RESOURCE_ID integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
   OWNER_UID   varchar(255) not null unique,                                -- implicit index
+  STATUS      integer      default 0 not null,                             -- enum HOME_STATUS
   DATAVERSION integer      default 0 not null
 );
 
@@ -139,6 +154,7 @@
 create table CALENDAR_BIND (
   CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
   CALENDAR_RESOURCE_ID      integer      not null references CALENDAR on delete cascade,
+  EXTERNAL_ID			    integer      default null,
   CALENDAR_RESOURCE_NAME    varchar(255) not null,
   BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
   BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
@@ -345,6 +361,9 @@
 create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
   ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
 
+create index ATTACHMENT_DROPBOX_ID on
+  ATTACHMENT(DROPBOX_ID);
+
 -- Many-to-many relationship between attachments and calendar objects
 create table ATTACHMENT_CALENDAR_OBJECT (
   ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
@@ -380,6 +399,7 @@
   RESOURCE_ID      				integer			primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
   ADDRESSBOOK_PROPERTY_STORE_ID	integer      	default nextval('RESOURCE_ID_SEQ') not null, 	-- implicit index
   OWNER_UID        				varchar(255) 	not null unique,                                -- implicit index
+  STATUS           				integer      	default 0 not null,                             -- enum HOME_STATUS
   DATAVERSION      				integer      	default 0 not null
 );
 
@@ -405,6 +425,7 @@
 create table SHARED_ADDRESSBOOK_BIND (
   ADDRESSBOOK_HOME_RESOURCE_ID			integer			not null references ADDRESSBOOK_HOME,
   OWNER_HOME_RESOURCE_ID    			integer      	not null references ADDRESSBOOK_HOME on delete cascade,
+  EXTERNAL_ID			                integer         default null,
   ADDRESSBOOK_RESOURCE_NAME    			varchar(255) 	not null,
   BIND_MODE                    			integer      	not null,	-- enum CALENDAR_BIND_MODE
   BIND_STATUS                  			integer      	not null,	-- enum CALENDAR_BIND_STATUS
@@ -504,6 +525,7 @@
 create table SHARED_GROUP_BIND (	
   ADDRESSBOOK_HOME_RESOURCE_ID 		integer      not null references ADDRESSBOOK_HOME,
   GROUP_RESOURCE_ID      			integer      not null references ADDRESSBOOK_OBJECT on delete cascade,
+  EXTERNAL_ID			            integer      default null,
   GROUP_ADDRESSBOOK_NAME			varchar(255) not null,
   BIND_MODE                    		integer      not null, -- enum CALENDAR_BIND_MODE
   BIND_STATUS                  		integer      not null, -- enum CALENDAR_BIND_STATUS

Modified: 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/v27.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v27.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -30,7 +30,6 @@
     "QUOTA_USED_BYTES" integer default 0 not null,
     "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
     "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
-    "DEFAULT_POLLS" integer default null references CALENDAR on delete set null,
     "ALARM_VEVENT_TIMED" nclob default null,
     "ALARM_VEVENT_ALLDAY" nclob default null,
     "ALARM_VTODO_TIMED" nclob default null,
@@ -377,10 +376,6 @@
     DEFAULT_TASKS
 );
 
-create index CALENDAR_HOME_METADAT_910264ce on CALENDAR_HOME_METADATA (
-    DEFAULT_POLLS
-);
-
 create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
     NOTIFICATION_HOME_RESOURCE_ID
 );
@@ -423,6 +418,10 @@
     CALENDAR_HOME_RESOURCE_ID
 );
 
+create index ATTACHMENT_DROPBOX_ID_5073cf23 on ATTACHMENT (
+    DROPBOX_ID
+);
+
 create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
     CALENDAR_OBJECT_RESOURCE_ID
 );

Modified: 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/v28.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v28.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -30,7 +30,6 @@
     "QUOTA_USED_BYTES" integer default 0 not null,
     "DEFAULT_EVENTS" integer default null references CALENDAR on delete set null,
     "DEFAULT_TASKS" integer default null references CALENDAR on delete set null,
-    "DEFAULT_POLLS" integer default null references CALENDAR on delete set null,
     "ALARM_VEVENT_TIMED" nclob default null,
     "ALARM_VEVENT_ALLDAY" nclob default null,
     "ALARM_VTODO_TIMED" nclob default null,
@@ -378,10 +377,6 @@
     DEFAULT_TASKS
 );
 
-create index CALENDAR_HOME_METADAT_910264ce on CALENDAR_HOME_METADATA (
-    DEFAULT_POLLS
-);
-
 create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
     NOTIFICATION_HOME_RESOURCE_ID
 );
@@ -424,6 +419,10 @@
     CALENDAR_HOME_RESOURCE_ID
 );
 
+create index ATTACHMENT_DROPBOX_ID_5073cf23 on ATTACHMENT (
+    DROPBOX_ID
+);
+
 create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
     CALENDAR_OBJECT_RESOURCE_ID
 );

Modified: 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/v29.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v29.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -49,16 +49,15 @@
 
 create table NOTIFICATION_HOME (
     "RESOURCE_ID" integer primary key,
-    "OWNER_UID" nvarchar2(255) unique,
-    "DATAVERSION" integer default 0 not null
+    "OWNER_UID" nvarchar2(255) unique
 );
 
 create table NOTIFICATION (
     "RESOURCE_ID" integer primary key,
     "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME,
     "NOTIFICATION_UID" nvarchar2(255),
-    "NOTIFICATION_TYPE" nvarchar2(255),
-    "NOTIFICATION_DATA" nclob,
+    "XML_TYPE" nvarchar2(255),
+    "XML_DATA" nclob,
     "MD5" nchar(32),
     "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
     "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
@@ -92,7 +91,6 @@
 insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('read', 1);
 insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('write', 2);
 insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('direct', 3);
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('indirect', 4);
 create table CALENDAR_BIND_STATUS (
     "ID" integer primary key,
     "DESCRIPTION" nvarchar2(16) unique
@@ -102,7 +100,6 @@
 insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('accepted', 1);
 insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('declined', 2);
 insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invalid', 3);
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('deleted', 4);
 create table CALENDAR_TRANSP (
     "ID" integer primary key,
     "DESCRIPTION" nvarchar2(16) unique
@@ -373,7 +370,6 @@
 insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '29');
 insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '5');
 insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '2');
-insert into CALENDARSERVER (NAME, VALUE) values ('NOTIFICATION-DATAVERSION', '1');
 create index CALENDAR_HOME_METADAT_3cb9049e on CALENDAR_HOME_METADATA (
     DEFAULT_EVENTS
 );
@@ -428,6 +424,10 @@
     CALENDAR_HOME_RESOURCE_ID
 );
 
+create index ATTACHMENT_DROPBOX_ID_5073cf23 on ATTACHMENT (
+    DROPBOX_ID
+);
+
 create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
     CALENDAR_OBJECT_RESOURCE_ID
 );

Modified: 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/v30.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v30.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -256,12 +256,10 @@
 insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('resource', 2);
 insert into ADDRESSBOOK_OBJECT_KIND (DESCRIPTION, ID) values ('location', 3);
 create table ABO_MEMBERS (
-    "GROUP_ID" integer not null,
+    "GROUP_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
     "ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
-    "MEMBER_ID" integer not null,
-    "REVISION" integer not null,
-    "REMOVED" integer default 0 not null, 
-    primary key("GROUP_ID", "MEMBER_ID", "REVISION")
+    "MEMBER_ID" integer not null references ADDRESSBOOK_OBJECT, 
+    primary key("GROUP_ID", "MEMBER_ID")
 );
 
 create table ABO_FOREIGN_MEMBERS (
@@ -296,7 +294,6 @@
     "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
     "OWNER_HOME_RESOURCE_ID" integer references ADDRESSBOOK_HOME,
     "ADDRESSBOOK_NAME" nvarchar2(255) default null,
-    "OBJECT_RESOURCE_ID" integer default 0,
     "RESOURCE_NAME" nvarchar2(255),
     "REVISION" integer not null,
     "DELETED" integer not null
@@ -431,6 +428,10 @@
     CALENDAR_HOME_RESOURCE_ID
 );
 
+create index ATTACHMENT_DROPBOX_ID_5073cf23 on ATTACHMENT (
+    DROPBOX_ID
+);
+
 create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
     CALENDAR_OBJECT_RESOURCE_ID
 );

Modified: 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/v31.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v31.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -431,6 +431,10 @@
     CALENDAR_HOME_RESOURCE_ID
 );
 
+create index ATTACHMENT_DROPBOX_ID_5073cf23 on ATTACHMENT (
+    DROPBOX_ID
+);
+
 create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
     CALENDAR_OBJECT_RESOURCE_ID
 );

Modified: 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/oracle-dialect/v32.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/oracle-dialect/v32.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -18,9 +18,17 @@
 create table CALENDAR_HOME (
     "RESOURCE_ID" integer primary key,
     "OWNER_UID" nvarchar2(255) unique,
+    "STATUS" integer default 0 not null,
     "DATAVERSION" integer default 0 not null
 );
 
+create table HOME_STATUS (
+    "ID" integer primary key,
+    "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into HOME_STATUS (DESCRIPTION, ID) values ('normal', 0);
+insert into HOME_STATUS (DESCRIPTION, ID) values ('external', 1);
 create table CALENDAR (
     "RESOURCE_ID" integer primary key
 );
@@ -50,6 +58,7 @@
 create table NOTIFICATION_HOME (
     "RESOURCE_ID" integer primary key,
     "OWNER_UID" nvarchar2(255) unique,
+    "STATUS" integer default 0 not null,
     "DATAVERSION" integer default 0 not null
 );
 
@@ -68,6 +77,7 @@
 create table CALENDAR_BIND (
     "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
     "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+    "EXTERNAL_ID" integer default null,
     "CALENDAR_RESOURCE_NAME" nvarchar2(255),
     "BIND_MODE" integer not null,
     "BIND_STATUS" integer not null,
@@ -210,6 +220,7 @@
     "RESOURCE_ID" integer primary key,
     "ADDRESSBOOK_PROPERTY_STORE_ID" integer not null,
     "OWNER_UID" nvarchar2(255) unique,
+    "STATUS" integer default 0 not null,
     "DATAVERSION" integer default 0 not null
 );
 
@@ -223,6 +234,7 @@
 create table SHARED_ADDRESSBOOK_BIND (
     "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
     "OWNER_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
+    "EXTERNAL_ID" integer default null,
     "ADDRESSBOOK_RESOURCE_NAME" nvarchar2(255),
     "BIND_MODE" integer not null,
     "BIND_STATUS" integer not null,
@@ -274,6 +286,7 @@
 create table SHARED_GROUP_BIND (
     "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
     "GROUP_RESOURCE_ID" integer not null references ADDRESSBOOK_OBJECT on delete cascade,
+    "EXTERNAL_ID" integer default null,
     "GROUP_ADDRESSBOOK_NAME" nvarchar2(255),
     "BIND_MODE" integer not null,
     "BIND_STATUS" integer not null,
@@ -431,6 +444,10 @@
     CALENDAR_HOME_RESOURCE_ID
 );
 
+create index ATTACHMENT_DROPBOX_ID_5073cf23 on ATTACHMENT (
+    DROPBOX_ID
+);
+
 create index ATTACHMENT_CALENDAR_O_81508484 on ATTACHMENT_CALENDAR_OBJECT (
     CALENDAR_OBJECT_RESOURCE_ID
 );

Modified: 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/v10.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v10.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v11.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v11.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v11.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v12.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v12.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v12.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v13.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v13.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v13.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v14.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v14.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v14.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v15.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v15.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v15.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v16.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v16.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v16.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v17.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v17.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v17.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v18.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v18.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v18.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v19.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v19.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v19.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v20.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v20.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v20.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v21.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v21.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v21.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v22.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v22.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v22.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v23.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v23.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v23.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v24.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v24.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v25.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v25.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v26.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v26.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v26.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v27.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v27.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v27.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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.
@@ -74,7 +74,6 @@
   QUOTA_USED_BYTES         integer     default 0 not null,
   DEFAULT_EVENTS           integer     default null references CALENDAR on delete set null,
   DEFAULT_TASKS            integer     default null references CALENDAR on delete set null,
-  DEFAULT_POLLS            integer     default null references CALENDAR on delete set null,
   ALARM_VEVENT_TIMED       text        default null,
   ALARM_VEVENT_ALLDAY      text        default null,
   ALARM_VTODO_TIMED        text        default null,
@@ -88,8 +87,6 @@
 	CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
 create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
 	CALENDAR_HOME_METADATA(DEFAULT_TASKS);
-create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
-	CALENDAR_HOME_METADATA(DEFAULT_POLLS);
 
 -----------------------
 -- Calendar Metadata --
@@ -342,6 +339,9 @@
 create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
   ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
 
+create index ATTACHMENT_DROPBOX_ID on
+  ATTACHMENT(DROPBOX_ID);
+
 -- Many-to-many relationship between attachments and calendar objects
 create table ATTACHMENT_CALENDAR_OBJECT (
   ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,

Modified: 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/v28.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v28.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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.
@@ -74,7 +74,6 @@
   QUOTA_USED_BYTES         integer     default 0 not null,
   DEFAULT_EVENTS           integer     default null references CALENDAR on delete set null,
   DEFAULT_TASKS            integer     default null references CALENDAR on delete set null,
-  DEFAULT_POLLS            integer     default null references CALENDAR on delete set null,
   ALARM_VEVENT_TIMED       text        default null,
   ALARM_VEVENT_ALLDAY      text        default null,
   ALARM_VTODO_TIMED        text        default null,
@@ -88,8 +87,6 @@
 	CALENDAR_HOME_METADATA(DEFAULT_EVENTS);
 create index CALENDAR_HOME_METADATA_DEFAULT_TASKS on
 	CALENDAR_HOME_METADATA(DEFAULT_TASKS);
-create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
-	CALENDAR_HOME_METADATA(DEFAULT_POLLS);
 
 -----------------------
 -- Calendar Metadata --
@@ -342,6 +339,9 @@
 create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
   ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
 
+create index ATTACHMENT_DROPBOX_ID on
+  ATTACHMENT(DROPBOX_ID);
+
 -- Many-to-many relationship between attachments and calendar objects
 create table ATTACHMENT_CALENDAR_OBJECT (
   ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,

Modified: 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/v29.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v29.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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.
@@ -109,16 +109,15 @@
 
 create table NOTIFICATION_HOME (
   RESOURCE_ID integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  OWNER_UID   varchar(255) not null unique,                                -- implicit index
-  DATAVERSION integer      default 0 not null
+  OWNER_UID   varchar(255) not null unique                                 -- implicit index
 );
 
 create table NOTIFICATION (
   RESOURCE_ID                   integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
   NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME,
   NOTIFICATION_UID              varchar(255) not null,
-  NOTIFICATION_TYPE             varchar(255) not null,
-  NOTIFICATION_DATA             text         not null,
+  XML_TYPE                      varchar(255) not null,
+  XML_DATA                      text         not null,
   MD5                           char(32)     not null,
   CREATED                       timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   MODIFIED                      timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
@@ -169,7 +168,6 @@
 insert into CALENDAR_BIND_MODE values (1, 'read' );
 insert into CALENDAR_BIND_MODE values (2, 'write');
 insert into CALENDAR_BIND_MODE values (3, 'direct');
-insert into CALENDAR_BIND_MODE values (4, 'indirect');
 
 -- Enumeration of statuses
 
@@ -182,7 +180,6 @@
 insert into CALENDAR_BIND_STATUS values (1, 'accepted');
 insert into CALENDAR_BIND_STATUS values (2, 'declined');
 insert into CALENDAR_BIND_STATUS values (3, 'invalid');
-insert into CALENDAR_BIND_STATUS values (4, 'deleted');
 
 
 -- Enumeration of transparency
@@ -345,6 +342,9 @@
 create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
   ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
 
+create index ATTACHMENT_DROPBOX_ID on
+  ATTACHMENT(DROPBOX_ID);
+
 -- Many-to-many relationship between attachments and calendar objects
 create table ATTACHMENT_CALENDAR_OBJECT (
   ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
@@ -705,4 +705,3 @@
 insert into CALENDARSERVER values ('VERSION', '29');
 insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '5');
 insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '2');
-insert into CALENDARSERVER values ('NOTIFICATION-DATAVERSION', '1');

Modified: 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/v3.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v3.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v30.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v30.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v30.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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.
@@ -345,6 +345,9 @@
 create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
   ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
 
+create index ATTACHMENT_DROPBOX_ID on
+  ATTACHMENT(DROPBOX_ID);
+
 -- Many-to-many relationship between attachments and calendar objects
 create table ATTACHMENT_CALENDAR_OBJECT (
   ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
@@ -454,24 +457,16 @@
 insert into ADDRESSBOOK_OBJECT_KIND values (3, 'location');
 
 
-----------------------------------
--- Revisions, forward reference --
-----------------------------------
-
-create sequence REVISION_SEQ;
-
 ---------------------------------
 -- Address Book Object Members --
 ---------------------------------
 
 create table ABO_MEMBERS (
-    GROUP_ID              integer      not null, -- references ADDRESSBOOK_OBJECT on delete cascade,	-- AddressBook Object's (kind=='group') RESOURCE_ID
+    GROUP_ID              integer      not null references ADDRESSBOOK_OBJECT on delete cascade,	-- AddressBook Object's (kind=='group') RESOURCE_ID
  	ADDRESSBOOK_ID		  integer      not null references ADDRESSBOOK_HOME on delete cascade,
-    MEMBER_ID             integer      not null, -- references ADDRESSBOOK_OBJECT,						-- member AddressBook Object's RESOURCE_ID
-  	REVISION              integer      default nextval('REVISION_SEQ') not null,
-  	REMOVED               boolean      default false not null,
+    MEMBER_ID             integer      not null references ADDRESSBOOK_OBJECT,						-- member AddressBook Object's RESOURCE_ID
 
-    primary key (GROUP_ID, MEMBER_ID, REVISION) -- implicit index
+    primary key (GROUP_ID, MEMBER_ID) -- implicit index
 );
 
 create index ABO_MEMBERS_ADDRESSBOOK_ID on
@@ -510,7 +505,7 @@
   MESSAGE                      		text,                  -- FIXME: xml?
 
   primary key (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_RESOURCE_ID), -- implicit index
-  unique (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_ADDRESSBOOK_NAME)  -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, GROUP_ADDRESSBOOK_NAME)     -- implicit index
 );
 
 create index SHARED_GROUP_BIND_RESOURCE_ID on
@@ -521,7 +516,7 @@
 -- Revisions --
 ---------------
 
--- create sequence REVISION_SEQ;
+create sequence REVISION_SEQ;
 
 
 -------------------------------
@@ -555,7 +550,6 @@
   ADDRESSBOOK_HOME_RESOURCE_ID 			integer			not null references ADDRESSBOOK_HOME,
   OWNER_HOME_RESOURCE_ID    			integer     	references ADDRESSBOOK_HOME,
   ADDRESSBOOK_NAME             			varchar(255) 	default null,
-  OBJECT_RESOURCE_ID					integer			default 0,
   RESOURCE_NAME                			varchar(255),
   REVISION                     			integer     	default nextval('REVISION_SEQ') not null,
   DELETED                      			boolean      	not null

Modified: 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/v31.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v31.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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.
@@ -345,6 +345,9 @@
 create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
   ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
 
+create index ATTACHMENT_DROPBOX_ID on
+  ATTACHMENT(DROPBOX_ID);
+
 -- Many-to-many relationship between attachments and calendar objects
 create table ATTACHMENT_CALENDAR_OBJECT (
   ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,

Modified: 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/v32.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v32.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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.
@@ -53,10 +53,22 @@
 
 create table CALENDAR_HOME (
   RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  OWNER_UID        varchar(255) not null unique,                                 -- implicit index
+  OWNER_UID        varchar(255) not null unique,                                -- implicit index
+  STATUS           integer      default 0 not null,                             -- enum HOME_STATUS
   DATAVERSION      integer      default 0 not null
 );
 
+-- Enumeration of statuses
+
+create table HOME_STATUS (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into HOME_STATUS values (0, 'normal' );
+insert into HOME_STATUS values (1, 'external');
+
+
 --------------
 -- Calendar --
 --------------
@@ -65,6 +77,7 @@
   RESOURCE_ID integer   primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
 );
 
+
 ----------------------------
 -- Calendar Home Metadata --
 ----------------------------
@@ -91,6 +104,7 @@
 create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
 	CALENDAR_HOME_METADATA(DEFAULT_POLLS);
 
+
 -----------------------
 -- Calendar Metadata --
 -----------------------
@@ -110,6 +124,7 @@
 create table NOTIFICATION_HOME (
   RESOURCE_ID integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
   OWNER_UID   varchar(255) not null unique,                                -- implicit index
+  STATUS      integer      default 0 not null,                             -- enum HOME_STATUS
   DATAVERSION integer      default 0 not null
 );
 
@@ -139,6 +154,7 @@
 create table CALENDAR_BIND (
   CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
   CALENDAR_RESOURCE_ID      integer      not null references CALENDAR on delete cascade,
+  EXTERNAL_ID			    integer      default null,
   CALENDAR_RESOURCE_NAME    varchar(255) not null,
   BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
   BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
@@ -345,6 +361,9 @@
 create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
   ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
 
+create index ATTACHMENT_DROPBOX_ID on
+  ATTACHMENT(DROPBOX_ID);
+
 -- Many-to-many relationship between attachments and calendar objects
 create table ATTACHMENT_CALENDAR_OBJECT (
   ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
@@ -380,6 +399,7 @@
   RESOURCE_ID      				integer			primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
   ADDRESSBOOK_PROPERTY_STORE_ID	integer      	default nextval('RESOURCE_ID_SEQ') not null, 	-- implicit index
   OWNER_UID        				varchar(255) 	not null unique,                                -- implicit index
+  STATUS           				integer      	default 0 not null,                             -- enum HOME_STATUS
   DATAVERSION      				integer      	default 0 not null
 );
 
@@ -405,6 +425,7 @@
 create table SHARED_ADDRESSBOOK_BIND (
   ADDRESSBOOK_HOME_RESOURCE_ID			integer			not null references ADDRESSBOOK_HOME,
   OWNER_HOME_RESOURCE_ID    			integer      	not null references ADDRESSBOOK_HOME on delete cascade,
+  EXTERNAL_ID			                integer         default null,
   ADDRESSBOOK_RESOURCE_NAME    			varchar(255) 	not null,
   BIND_MODE                    			integer      	not null,	-- enum CALENDAR_BIND_MODE
   BIND_STATUS                  			integer      	not null,	-- enum CALENDAR_BIND_STATUS
@@ -503,6 +524,7 @@
 create table SHARED_GROUP_BIND (	
   ADDRESSBOOK_HOME_RESOURCE_ID 		integer      not null references ADDRESSBOOK_HOME,
   GROUP_RESOURCE_ID      			integer      not null references ADDRESSBOOK_OBJECT on delete cascade,
+  EXTERNAL_ID			            integer      default null,
   GROUP_ADDRESSBOOK_NAME			varchar(255) not null,
   BIND_MODE                    		integer      not null, -- enum CALENDAR_BIND_MODE
   BIND_STATUS                  		integer      not null, -- enum CALENDAR_BIND_STATUS

Modified: 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/v4.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v4.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v5.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v5.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v5.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v6.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v6.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v6.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v7.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v7.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v7.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v8.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v8.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v8.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/common/datastore/sql_schema/old/postgres-dialect/v9.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v9.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/old/postgres-dialect/v9.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 -- -*- test-case-name: txdav.caldav.datastore.test.test_sql,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/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_10_to_11.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_10_to_11.sql	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/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_11_to_12.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_11_to_12.sql	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/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_12_to_13.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_12_to_13.sql	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/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_13_to_14.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_13_to_14.sql	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/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_14_to_15.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_14_to_15.sql	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/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_15_to_16.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_15_to_16.sql	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/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_16_to_17.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_16_to_17.sql	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/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_17_to_18.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_17_to_18.sql	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/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_18_to_19.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql	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/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_19_to_20.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_19_to_20.sql	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/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_20_to_21.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_20_to_21.sql	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/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_21_to_22.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_21_to_22.sql	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/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_22_to_23.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_22_to_23.sql	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/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_23_to_24.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_23_to_24.sql	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/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_24_to_25.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql	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/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_25_to_26.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_25_to_26.sql	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/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_26_to_27.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_26_to_27.sql	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.
@@ -18,13 +18,10 @@
 -- Upgrade database schema from VERSION 26 to 27 --
 ---------------------------------------------------
 
--- Calendar home related updates
+-- New index
 
-alter table CALENDAR_HOME_METADATA
- add ("DEFAULT_POLLS" integer default null references CALENDAR on delete set null);
-
-create index CALENDAR_HOME_METADAT_910264ce on CALENDAR_HOME_METADATA (
-    DEFAULT_POLLS
+create index ATTACHMENT_DROPBOX_ID_5073cf23 on ATTACHMENT (
+    DROPBOX_ID
 );
 
 

Modified: 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_27_to_28.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_27_to_28.sql	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/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_28_to_29.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_28_to_29.sql	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.
@@ -18,21 +18,16 @@
 -- Upgrade database schema from VERSION 28 to 29 --
 ---------------------------------------------------
 
--- Sharing notification related updates
+-- Calendar home related updates
 
-alter table NOTIFICATION_HOME
- add ("DATAVERSION" integer default 0 not null);
+alter table CALENDAR_HOME_METADATA
+ add ("DEFAULT_POLLS" integer default null references CALENDAR on delete set null);
 
-alter table NOTIFICATION
-  rename column XML_TYPE to NOTIFICATION_TYPE;
-alter table NOTIFICATION
-  rename column XML_DATA to NOTIFICATION_DATA;
+create index CALENDAR_HOME_METADAT_910264ce on CALENDAR_HOME_METADATA (
+    DEFAULT_POLLS
+);
 
-  -- Sharing enumeration updates
-insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('indirect', 4);
 
-insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('deleted', 4);
-
 -- Now update the version
+-- No data upgrades
 update CALENDARSERVER set VALUE = '29' where NAME = 'VERSION';
-insert into CALENDARSERVER (NAME, VALUE) values ('NOTIFICATION-DATAVERSION', '1');

Modified: 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_29_to_30.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_29_to_30.sql	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.
@@ -18,35 +18,21 @@
 -- Upgrade database schema from VERSION 29 to 30 --
 ---------------------------------------------------
 
-----------------------------------------
--- Change Address Book Object Members --
-----------------------------------------
+-- Sharing notification related updates
 
-begin
-for i in (select constraint_name from user_cons_columns where column_name = 'MEMBER_ID' or column_name = 'GROUP_ID')
-loop
-execute immediate 'alter table abo_members drop constraint' || i.constraint_name;
-end loop;
-end;
+alter table NOTIFICATION_HOME
+ add ("DATAVERSION" integer default 0 not null);
 
-alter table ABO_MEMBERS
-	add ("REVISION" integer default nextval('REVISION_SEQ') not null);
-alter table ABO_MEMBERS
-	add ("REMOVED" boolean default false not null);
-alter table ABO_MEMBERS
-	 drop primary key;
-alter table ABO_MEMBERS
-	 add primary key ("GROUP_ID", "MEMBER_ID", "REVISION");
+alter table NOTIFICATION
+  rename column XML_TYPE to NOTIFICATION_TYPE;
+alter table NOTIFICATION
+  rename column XML_DATA to NOTIFICATION_DATA;
 
-------------------------------------------
--- Change Address Book Object Revisions --
-------------------------------------------
-	
-alter table ADDRESSBOOK_OBJECT_REVISIONS
-	add ("OBJECT_RESOURCE_ID" integer default 0);
+  -- Sharing enumeration updates
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('indirect', 4);
 
---------------------
--- Update version --
---------------------
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('deleted', 4);
 
+-- Now update the version
 update CALENDARSERVER set VALUE = '30' where NAME = 'VERSION';
+insert into CALENDARSERVER (NAME, VALUE) values ('NOTIFICATION-DATAVERSION', '1');

Modified: 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_30_to_31.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_30_to_31.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1 +1,52 @@
+----
+-- 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.
+-- 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.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 30 to 31 --
+---------------------------------------------------
+
+----------------------------------------
+-- Change Address Book Object Members --
+----------------------------------------
+
+begin
+for i in (select constraint_name from user_cons_columns where column_name = 'MEMBER_ID' or column_name = 'GROUP_ID')
+loop
+execute immediate 'alter table abo_members drop constraint' || i.constraint_name;
+end loop;
+end;
+
+alter table ABO_MEMBERS
+	add ("REVISION" integer not null);
+alter table ABO_MEMBERS
+	add ("REMOVED" integer default 0 not null);
+alter table ABO_MEMBERS
+	 drop primary key;
+alter table ABO_MEMBERS
+	 add primary key ("GROUP_ID", "MEMBER_ID", "REVISION");
+
+------------------------------------------
+-- Change Address Book Object Revisions --
+------------------------------------------
+	
+alter table ADDRESSBOOK_OBJECT_REVISIONS
+	add ("OBJECT_RESOURCE_ID" integer default 0);
+
+--------------------
+-- Update version --
+--------------------
+
 update CALENDARSERVER set VALUE = '31' where NAME = 'VERSION';

Modified: 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_31_to_32.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_31_to_32.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1 +1,53 @@
+----
+-- 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.
+-- 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.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 31 to 32 --
+---------------------------------------------------
+
+-- Home related updates
+
+alter table CALENDAR_HOME
+ add ("STATUS" integer default 0 not null);
+
+alter table NOTIFICATION_HOME
+ add ("STATUS" integer default 0 not null);
+
+alter table ADDRESSBOOK_HOME
+ add ("STATUS" integer default 0 not null);
+
+create table HOME_STATUS (
+    "ID" integer primary key,
+    "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into HOME_STATUS (DESCRIPTION, ID) values ('normal', 0);
+insert into HOME_STATUS (DESCRIPTION, ID) values ('external', 1);
+
+-- Bind changes
+alter table CALENDAR_BIND
+ add ("EXTERNAL_ID" integer default null);
+
+alter table SHARED_ADDRESSBOOK_BIND
+ add ("EXTERNAL_ID" integer default null);
+
+alter table SHARED_GROUP_BIND
+ add ("EXTERNAL_ID" integer default null);
+
+
+-- Now update the version
+-- No data upgrades
 update CALENDARSERVER set VALUE = '32' where NAME = 'VERSION';

Modified: 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_3_to_4.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_3_to_4.sql	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/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_4_to_5.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_4_to_5.sql	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/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_5_to_6.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_5_to_6.sql	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/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_6_to_7.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_6_to_7.sql	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/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_7_to_8.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_7_to_8.sql	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/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_8_to_9.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_8_to_9.sql	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/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_9_to_10.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_9_to_10.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_9_to_10.sql	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/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_10_to_11.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_10_to_11.sql	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/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_11_to_12.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_11_to_12.sql	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/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_12_to_13.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_12_to_13.sql	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/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_13_to_14.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_13_to_14.sql	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/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_14_to_15.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_14_to_15.sql	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/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_15_to_16.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_15_to_16.sql	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/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_16_to_17.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_16_to_17.sql	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/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_17_to_18.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_17_to_18.sql	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/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_18_to_19.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql	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/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_19_to_20.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_19_to_20.sql	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/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_20_to_21.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_20_to_21.sql	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/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_21_to_22.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_21_to_22.sql	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/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_22_to_23.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_22_to_23.sql	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/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_23_to_24.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_23_to_24.sql	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/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_24_to_25.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql	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/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_25_to_26.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_25_to_26.sql	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/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_26_to_27.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_26_to_27.sql	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.
@@ -18,13 +18,11 @@
 -- Upgrade database schema from VERSION 26 to 27 --
 ---------------------------------------------------
 
--- Calendar home related updates
+-- New index
 
-alter table CALENDAR_HOME_METADATA
- add column DEFAULT_POLLS integer default null references CALENDAR on delete set null;
+create index ATTACHMENT_DROPBOX_ID on
+  ATTACHMENT(DROPBOX_ID);
 
-create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
-	CALENDAR_HOME_METADATA(DEFAULT_POLLS);
 
 -- Now update the version
 -- No data upgrades

Modified: 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_27_to_28.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_27_to_28.sql	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/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_28_to_29.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_28_to_29.sql	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.
@@ -18,21 +18,14 @@
 -- Upgrade database schema from VERSION 28 to 29 --
 ---------------------------------------------------
 
--- Sharing notification related updates
+-- Calendar home related updates
 
-alter table NOTIFICATION_HOME
-  add column DATAVERSION integer default 0 not null;
+alter table CALENDAR_HOME_METADATA
+ add column DEFAULT_POLLS integer default null references CALENDAR on delete set null;
 
-alter table NOTIFICATION
-  rename column XML_TYPE to NOTIFICATION_TYPE;
-alter table NOTIFICATION
-  rename column XML_DATA to NOTIFICATION_DATA;
+create index CALENDAR_HOME_METADATA_DEFAULT_POLLS on
+	CALENDAR_HOME_METADATA(DEFAULT_POLLS);
 
--- Sharing enumeration updates
-insert into CALENDAR_BIND_MODE values (4, 'indirect');
-
-insert into CALENDAR_BIND_STATUS values (4, 'deleted');
-
 -- Now update the version
+-- No data upgrades
 update CALENDARSERVER set VALUE = '29' where NAME = 'VERSION';
-insert into CALENDARSERVER values ('NOTIFICATION-DATAVERSION', '1');

Modified: 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_29_to_30.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_29_to_30.sql	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.
@@ -18,27 +18,21 @@
 -- Upgrade database schema from VERSION 29 to 30 --
 ---------------------------------------------------
 
-----------------------------------------
--- Change Address Book Object Members --
-----------------------------------------
+-- Sharing notification related updates
 
-alter table ABO_MEMBERS
-	drop constraint	abo_members_member_id_fkey,
-	drop constraint	abo_members_group_id_fkey,
-	add column	REVISION		integer      default nextval('REVISION_SEQ') not null,
-	add column	REMOVED         boolean      default false not null,
-	drop constraint abo_members_pkey,
-	add constraint abo_members_pkey primary key(GROUP_ID, MEMBER_ID, REVISION);
+alter table NOTIFICATION_HOME
+  add column DATAVERSION integer default 0 not null;
 
-------------------------------------------
--- Change Address Book Object Revisions --
-------------------------------------------
-	
-alter table ADDRESSBOOK_OBJECT_REVISIONS
-	add column OBJECT_RESOURCE_ID integer default 0;
-	
---------------------
--- Update version --
---------------------
+alter table NOTIFICATION
+  rename column XML_TYPE to NOTIFICATION_TYPE;
+alter table NOTIFICATION
+  rename column XML_DATA to NOTIFICATION_DATA;
 
+-- Sharing enumeration updates
+insert into CALENDAR_BIND_MODE values (4, 'indirect');
+
+insert into CALENDAR_BIND_STATUS values (4, 'deleted');
+
+-- Now update the version
 update CALENDARSERVER set VALUE = '30' where NAME = 'VERSION';
+insert into CALENDARSERVER values ('NOTIFICATION-DATAVERSION', '1');

Modified: 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_30_to_31.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_30_to_31.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1 +1,44 @@
+----
+-- 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.
+-- 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.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 30 to 31 --
+---------------------------------------------------
+
+----------------------------------------
+-- Change Address Book Object Members --
+----------------------------------------
+
+alter table ABO_MEMBERS
+	drop constraint	abo_members_member_id_fkey,
+	drop constraint	abo_members_group_id_fkey,
+	add column	REVISION		integer      default nextval('REVISION_SEQ') not null,
+	add column	REMOVED         boolean      default false not null,
+	drop constraint abo_members_pkey,
+	add constraint abo_members_pkey primary key(GROUP_ID, MEMBER_ID, REVISION);
+
+------------------------------------------
+-- Change Address Book Object Revisions --
+------------------------------------------
+	
+alter table ADDRESSBOOK_OBJECT_REVISIONS
+	add column OBJECT_RESOURCE_ID integer default 0;
+	
+--------------------
+-- Update version --
+--------------------
+
 update CALENDARSERVER set VALUE = '31' where NAME = 'VERSION';

Modified: 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_31_to_32.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_31_to_32.sql	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1 +1,55 @@
+----
+-- 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.
+-- 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.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 31 to 32 --
+---------------------------------------------------
+
+-- Home related updates
+
+alter table CALENDAR_HOME
+ add column STATUS integer default 0 not null;
+
+alter table NOTIFICATION_HOME
+ add column STATUS integer default 0 not null;
+
+alter table ADDRESSBOOK_HOME
+ add column STATUS integer default 0 not null;
+
+-- Enumeration of statuses
+
+create table HOME_STATUS (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into HOME_STATUS values (0, 'normal' );
+insert into HOME_STATUS values (1, 'external');
+
+-- Bind changes
+alter table CALENDAR_BIND
+ add column EXTERNAL_ID integer default null;
+
+alter table SHARED_ADDRESSBOOK_BIND
+ add column EXTERNAL_ID integer default null;
+
+alter table SHARED_GROUP_BIND
+ add column EXTERNAL_ID integer default null;
+
+
+-- Now update the version
+-- No data upgrades
 update CALENDARSERVER set VALUE = '32' where NAME = 'VERSION';

Modified: 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_3_to_4.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_3_to_4.sql	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/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_4_to_5.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_4_to_5.sql	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/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_5_to_6.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_5_to_6.sql	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/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_6_to_7.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_6_to_7.sql	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/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_7_to_8.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_7_to_8.sql	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/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_8_to_9.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_8_to_9.sql	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/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_9_to_10.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_9_to_10.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_9_to_10.sql	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/common/datastore/sql_schema/upgrades/upgrade_template.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/upgrade_template.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_schema/upgrades/upgrade_template.sql	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/common/datastore/sql_tables.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_tables.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/sql_tables.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.test.test_sql_tables -*-
 ##
-# 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.
@@ -133,6 +133,15 @@
 
 # Various constants
 
+_homeStatus = _schemaConstants(
+    schema.HOME_STATUS.DESCRIPTION,
+    schema.HOME_STATUS.ID
+)
+
+
+_HOME_STATUS_NORMAL = _homeStatus('normal')
+_HOME_STATUS_EXTERNAL = _homeStatus('external')
+
 _bindStatus = _schemaConstants(
     schema.CALENDAR_BIND_STATUS.DESCRIPTION,
     schema.CALENDAR_BIND_STATUS.ID

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/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/common/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/test_sql.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/test_sql.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.
@@ -19,21 +19,28 @@
 """
 
 from twext.enterprise.dal.syntax import Select
-from txdav.xml import element as davxml
+from twext.enterprise.dal.syntax import Insert
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.internet.task import Clock
 from twisted.trial.unittest import TestCase
 from twisted.internet.defer import Deferred
 
+from txdav.caldav.datastore.test.util import buildDirectoryRecord
 from txdav.common.datastore.sql import log, CommonStoreTransactionMonitor, \
     CommonHome, CommonHomeChild, ECALENDARTYPE
 from txdav.common.datastore.sql_tables import schema
 from txdav.common.datastore.test.util import CommonCommonTests, buildStore
 from txdav.common.icommondatastore import AllRetriesFailed
-from twext.enterprise.dal.syntax import Insert
 from txdav.common.datastore.sql import fixUUIDNormalization
+from txdav.xml import element as davxml
 
+from uuid import UUID
+
+exampleUID = UUID("a" * 32)
+denormalizedUID = str(exampleUID)
+normalizedUID = denormalizedUID.upper()
+
 class CommonSQLStoreTests(CommonCommonTests, TestCase):
     """
     Tests for shared functionality in L{txdav.common.datastore.sql}.
@@ -46,6 +53,9 @@
         """
         yield super(CommonSQLStoreTests, self).setUp()
         self._sqlStore = yield buildStore(self, self.notifierFactory)
+        self._sqlStore.directoryService().addRecord(buildDirectoryRecord(denormalizedUID))
+        self._sqlStore.directoryService().addRecord(buildDirectoryRecord(normalizedUID))
+        self._sqlStore.directoryService().addRecord(buildDirectoryRecord("uid"))
 
 
     def storeUnderTest(self):
@@ -118,10 +128,12 @@
         self.patch(log, "error", counter)
 
         txn = self.transactionUnderTest()
+        self.assertFalse(txn.timedout)
 
         c.advance(2)
         self.assertNotEqual(ctr[0], 0)
         self.assertTrue(txn._sqlTxn._completed)
+        self.assertTrue(txn.timedout)
 
 
     def test_logWaitsAndTxnTimeout(self):
@@ -308,31 +320,31 @@
         token = yield homeChild.syncToken()
         yield homeChild._changeRevision("insert", "C")
         changed = yield homeChild.resourceNamesSinceToken(token)
-        self.assertEqual(changed, (["C"], [],))
+        self.assertEqual(changed, (["C"], [], [],))
 
         # update test
         token = yield homeChild.syncToken()
         yield homeChild._changeRevision("update", "C")
         changed = yield homeChild.resourceNamesSinceToken(token)
-        self.assertEqual(changed, (["C"], [],))
+        self.assertEqual(changed, (["C"], [], [],))
 
         # delete test
         token = yield homeChild.syncToken()
         yield homeChild._changeRevision("delete", "C")
         changed = yield homeChild.resourceNamesSinceToken(token)
-        self.assertEqual(changed, ([], ["C"],))
+        self.assertEqual(changed, ([], ["C"], [],))
 
         # missing update test
         token = yield homeChild.syncToken()
         yield homeChild._changeRevision("update", "D")
         changed = yield homeChild.resourceNamesSinceToken(token)
-        self.assertEqual(changed, (["D"], [],))
+        self.assertEqual(changed, (["D"], [], [],))
 
         # missing delete test
         token = yield homeChild.syncToken()
         yield homeChild._changeRevision("delete", "E")
         changed = yield homeChild.resourceNamesSinceToken(token)
-        self.assertEqual(changed, ([], [],))
+        self.assertEqual(changed, ([], [], [],))
 
         yield txn.abort()
 
@@ -421,10 +433,3 @@
         yield fixUUIDNormalization(self.storeUnderTest())
         self.assertEqual((yield self.allHomeUIDs(schema.ADDRESSBOOK_HOME)),
                          [[normalizedUID]])
-
-
-
-from uuid import UUID
-exampleUID = UUID("a" * 32)
-denormalizedUID = str(exampleUID)
-normalizedUID = denormalizedUID.upper()

Modified: 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_schema_files.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/test_sql_schema_files.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/common/datastore/test/test_sql_tables.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/test_sql_tables.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/test_sql_tables.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.
@@ -387,7 +387,7 @@
         realsql = dedent(
         '''
         ----
-        -- 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/common/datastore/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/test/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/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.
@@ -112,12 +112,14 @@
     def recordWithUID(self, uid):
         return self.records.get(uid)
 
+
     def recordWithGUID(self, guid):
         for record in self.records.itervalues():
             if record.guid == guid:
                 return record
         return None
 
+
     def addRecord(self, record):
         self.records[record.uid] = record
 
@@ -127,32 +129,70 @@
 
     implements(IStoreDirectoryRecord)
 
-    def __init__(self, uid, shortNames, fullName, extras={}):
+    def __init__(self, uid, shortNames, fullName, thisServer=True, server=None, extras={}):
         self.uid = uid
         self.guid = uid
         self.shortNames = shortNames
         self.fullName = fullName
         self.displayName = self.fullName if self.fullName else self.shortNames[0]
+        self._thisServer = thisServer
+        self._server = server
         self.extras = extras
 
 
+    def thisServer(self):
+        return self._thisServer
 
+
+    def server(self):
+        return self._server
+
+
+
+def buildDirectory(homes=None):
+
+    directory = TestStoreDirectoryService()
+
+    # User accounts
+    for ctr in range(1, 100):
+        directory.addRecord(TestStoreDirectoryRecord(
+            "user%02d" % (ctr,),
+            ("user%02d" % (ctr,),),
+            "User %02d" % (ctr,),
+        ))
+
+    homes = set(homes) if homes is not None else set()
+    for uid in homes:
+        directory.addRecord(buildDirectoryRecord(uid))
+
+    return directory
+
+
+
+def buildDirectoryRecord(uid):
+    return TestStoreDirectoryRecord(
+        uid,
+        (uid,),
+        uid.capitalize(),
+    )
+
+
+
 class SQLStoreBuilder(object):
     """
     Test-fixture-builder which can construct a PostgresStore.
     """
-    sharedService = None
-    currentTestID = None
+    def __init__(self, secondary=False):
+        self.sharedService = None
+        self.currentTestID = None
+        self.sharedDBPath = "_test_sql_db" + str(os.getpid()) + ("-2" if secondary else "")
 
-    SHARED_DB_PATH = "_test_sql_db" + str(os.getpid())
 
-
-    @classmethod
-    def createService(cls, serviceFactory):
+    def createService(self, serviceFactory):
         """
         Create a L{PostgresService} to use for building a store.
         """
-        dbRoot = CachingFilePath(cls.SHARED_DB_PATH)
+        dbRoot = CachingFilePath(self.sharedDBPath)
         return PostgresService(
             dbRoot, serviceFactory, current_sql_schema, resetSchema=True,
             databaseName="caldav",
@@ -168,17 +208,15 @@
         )
 
 
-    @classmethod
-    def childStore(cls):
+    def childStore(self):
         """
         Create a store suitable for use in a child process, that is hooked up
         to the store that a parent test process is managing.
         """
         disableMemcacheForTest(TestCase())
         staticQuota = 3000
-        attachmentRoot = (CachingFilePath(cls.SHARED_DB_PATH)
-                          .child("attachments"))
-        stubsvc = cls.createService(lambda cf: Service())
+        attachmentRoot = (CachingFilePath(self.sharedDBPath).child("attachments"))
+        stubsvc = self.createService(lambda cf: Service())
 
         cp = ConnectionPool(stubsvc.produceConnection, maxConnections=1)
         # Attach the service to the running reactor.
@@ -194,17 +232,17 @@
         return cds
 
 
-    def buildStore(self, testCase, notifierFactory, directoryService=None):
+    def buildStore(self, testCase, notifierFactory, directoryService=None, homes=None):
         """
         Do the necessary work to build a store for a particular test case.
 
         @return: a L{Deferred} which fires with an L{IDataStore}.
         """
         disableMemcacheForTest(testCase)
-        dbRoot = CachingFilePath(self.SHARED_DB_PATH)
+        dbRoot = CachingFilePath(self.sharedDBPath)
         attachmentRoot = dbRoot.child("attachments")
         if directoryService is None:
-            directoryService = TestStoreDirectoryService()
+            directoryService = buildDirectory(homes=homes)
         if self.sharedService is None:
             ready = Deferred()
             def getReady(connectionFactory, storageService):
@@ -251,8 +289,7 @@
         attachmentRoot.createDirectory()
 
         currentTestID = testCase.id()
-        cp = ConnectionPool(self.sharedService.produceConnection,
-                            maxConnections=5)
+        cp = ConnectionPool(self.sharedService.produceConnection, maxConnections=5)
         quota = deriveQuota(testCase)
         store = CommonDataStore(
             cp.connection,
@@ -314,6 +351,7 @@
 
 theStoreBuilder = SQLStoreBuilder()
 buildStore = theStoreBuilder.buildStore
+cleanStore = theStoreBuilder.cleanStore
 
 
 _notSet = object()
@@ -685,13 +723,13 @@
 
 
     @inlineCallbacks
-    def homeUnderTest(self, txn=None, name="home1"):
+    def homeUnderTest(self, txn=None, name="home1", create=False):
         """
         Get the calendar home detailed by C{requirements['home1']}.
         """
         if txn is None:
             txn = self.transactionUnderTest()
-        returnValue((yield txn.calendarHomeWithUID(name)))
+        returnValue((yield txn.calendarHomeWithUID(name, create=create)))
 
 
     @inlineCallbacks

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/__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/txdav/common/datastore/upgrade/file/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/file/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/file/__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/txdav/common/datastore/upgrade/migrate.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/migrate.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/migrate.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.upgrade.test.test_migrate -*-
 ##
-# 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/common/datastore/upgrade/sql/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/__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/txdav/common/datastore/upgrade/sql/others/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/__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/common/datastore/upgrade/sql/others/attachment_migration.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/attachment_migration.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/attachment_migration.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/common/datastore/upgrade/sql/others/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/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/common/datastore/upgrade/sql/others/test/test_attachment_migration.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/test/test_attachment_migration.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/others/test/test_attachment_migration.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/datastore/upgrade/sql/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/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/txdav/common/datastore/upgrade/sql/test/fake_schema1/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema1/current.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema1/current.sql	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/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_schema1/upgrades/fake_dialect/upgrade_from_3_to_4.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema1/upgrades/fake_dialect/upgrade_from_3_to_4.sql	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/common/datastore/upgrade/sql/test/fake_schema2/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema2/current.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema2/current.sql	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/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_4.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema2/upgrades/fake_dialect/upgrade_from_3_to_4.sql	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/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_3_to_5.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema2/upgrades/fake_dialect/upgrade_from_3_to_5.sql	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/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_schema2/upgrades/fake_dialect/upgrade_from_4_to_5.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema2/upgrades/fake_dialect/upgrade_from_4_to_5.sql	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/common/datastore/upgrade/sql/test/fake_schema3/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema3/current.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema3/current.sql	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/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_3_to_4.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema3/upgrades/fake_dialect/upgrade_from_3_to_4.sql	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/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/fake_schema3/upgrades/fake_dialect/upgrade_from_4_to_5.sql	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/fake_schema3/upgrades/fake_dialect/upgrade_from_4_to_5.sql	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/common/datastore/upgrade/sql/test/test_upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/test_upgrade.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/test/test_upgrade.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/datastore/upgrade/sql/upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrade.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrade.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.upgrade.sql.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/common/datastore/upgrade/sql/upgrades/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/__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/txdav/common/datastore/upgrade/sql/upgrades/addressbook_upgrade_from_1_to_2.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/addressbook_upgrade_from_1_to_2.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/addressbook_upgrade_from_1_to_2.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.upgrade.sql.test -*-
 # #
-# 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/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_1_to_2.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_1_to_2.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.upgrade.sql.test -*-
 ##
-# 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/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_2_to_3.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_2_to_3.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.upgrade.sql.test -*-
 ##
-# 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/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_3_to_4.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_3_to_4.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.upgrade.sql.test -*-
 ##
-# 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/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.upgrade.sql.test -*-
 ##
-# 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/common/datastore/upgrade/sql/upgrades/notification_upgrade_from_0_to_1.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/notification_upgrade_from_0_to_1.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/notification_upgrade_from_0_to_1.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txdav.common.datastore.upgrade.sql.test -*-
 ##
-# 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/common/datastore/upgrade/sql/upgrades/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/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/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_notification_upgrade_from_0_to_1.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/test/test_notification_upgrade_from_0_to_1.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/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_3_to_4.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.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/datastore/upgrade/sql/upgrades/test/test_upgrade_from_4_to_5.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_4_to_5.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_4_to_5.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/datastore/upgrade/sql/upgrades/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/sql/upgrades/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.
@@ -19,7 +19,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from txdav.base.propertystore.base import PropertyName
 from txdav.base.propertystore.sql import PropertyStore
-from txdav.common.datastore.sql_tables import schema
+from txdav.common.datastore.sql_tables import schema, _HOME_STATUS_EXTERNAL
 from twisted.python.failure import Failure
 
 log = Logger()
@@ -134,7 +134,7 @@
 
 
 @inlineCallbacks
-def doToEachHomeNotAtVersion(store, homeSchema, version, doIt, logStr, filterOwnerUID=None):
+def doToEachHomeNotAtVersion(store, homeSchema, version, doIt, logStr, filterOwnerUID=None, processExternal=False):
     """
     Do something to each home whose version column indicates it is older
     than the specified version. Do this in batches as there may be a lot of work to do. Also,
@@ -161,7 +161,7 @@
         txn = store.newTransaction("updateDataVersion")
         try:
             rows = yield Select(
-                [homeSchema.RESOURCE_ID, homeSchema.OWNER_UID, ],
+                [homeSchema.RESOURCE_ID, homeSchema.OWNER_UID, homeSchema.STATUS, ],
                 From=homeSchema,
                 Where=where,
                 OrderBy=homeSchema.OWNER_UID,
@@ -173,9 +173,10 @@
                 logUpgradeStatus("End {}".format(logStr), count, total)
                 returnValue(None)
 
-            # Apply to the home
-            homeResourceID, _ignore_owner_uid = rows[0]
-            yield doIt(txn, homeResourceID)
+            # Apply to the home if not external
+            homeResourceID, _ignore_owner_uid, homeStatus = rows[0]
+            if homeStatus != _HOME_STATUS_EXTERNAL or processExternal:
+                yield doIt(txn, homeResourceID)
 
             # Update the home to the current version
             yield Update(

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/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/txdav/common/datastore/upgrade/test/test_migrate.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/test/test_migrate.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/upgrade/test/test_migrate.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.
@@ -143,7 +143,17 @@
             self.filesPath, {"push": StubNotifierFactory()}, TestStoreDirectoryService(), True, True
         )
         self.sqlStore = yield theStoreBuilder.buildStore(
-            self, StubNotifierFactory()
+            self,
+            StubNotifierFactory(),
+            homes=(
+                "home1",
+                "home2",
+                "home3",
+                "home_defaults",
+                "home_no_splits",
+                "home_splits",
+                "home_splits_shared",
+            )
         )
         self.upgrader = UpgradeToDatabaseStep(self.fileStore, self.sqlStore)
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/work/test/test_revision_cleanup.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/work/test/test_revision_cleanup.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/datastore/work/test/test_revision_cleanup.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -315,10 +315,11 @@
         otherAB = yield self.addressbookUnderTest(home="user02", name="user01")
         self.assertNotEqual(otherAB._bindRevision, 0)
 
-        changed, deleted = yield otherAB.resourceNamesSinceRevision(otherAB._bindRevision)
+        changed, deleted, invalid = yield otherAB.resourceNamesSinceRevision(otherAB._bindRevision)
         print("test_addressbookMembersRevisions changed=%s deleted=%s" % (changed, deleted,))
         self.assertEqual(changed, ["group1.vcf"])
         self.assertEqual(len(deleted), 0)
+        self.assertEqual(len(invalid), 0)
 
         otherHome = yield self.addressbookHomeUnderTest(name="user02")
         for depth, result in (
@@ -327,10 +328,11 @@
             ("infinity", ['user01/',
                           'user01/group1.vcf']
              )):
-            changed, deleted = yield otherAB.viewerHome().resourceNamesSinceRevision(otherAB._bindRevision, depth)
+            changed, deleted, invalid = yield otherAB.viewerHome().resourceNamesSinceRevision(otherAB._bindRevision, depth)
             print("test_addressbookMembersRevisions depth=%s, changed=%s deleted=%s" % (depth, changed, deleted,))
             self.assertEqual(set(changed), set(result))
             self.assertEqual(len(deleted), 0)
+            self.assertEqual(len(invalid), 0)
 
         yield self.commit()
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/icommondatastore.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/icommondatastore.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/icommondatastore.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.
@@ -51,6 +51,13 @@
 
 
 
+class RecordNotAllowedError(CommonStoreError):
+    """
+    User not allowed.
+    """
+
+
+
 class NameNotAllowedError(CommonStoreError):
     """
     Attempt to create an object with a name that is not allowed.
@@ -205,6 +212,29 @@
     """
 
 
+
+class ShareNotAllowed(CommonStoreError):
+    """
+    An operation on a shared resource is not allowed.
+    """
+
+
+
+class ExternalShareFailed(CommonStoreError):
+    """
+    An external sharee operation failed.
+    """
+
+
+
+class NonExistentExternalShare(CommonStoreError):
+    """
+    An external sharee operation failed because the share does not exist on the
+    other pod. The caller of the external request receiving this exception should
+    remove the local external share to "heal" this mismatch.
+    """
+
+
 # Indexing / sync tokens
 
 

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/idirectoryservice.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/idirectoryservice.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/idirectoryservice.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.
@@ -26,6 +26,20 @@
     "IStoreDirectoryRecord",
 ]
 
+class IStoreDirectoryError(Exception):
+    """
+    Base class for directory related errors.
+    """
+
+
+
+class DirectoryRecordNotFoundError(Exception):
+    """
+    Directory record not found.
+    """
+
+
+
 class IStoreDirectoryService(Interface):
     """
     Directory Service for looking up users.
@@ -48,6 +62,7 @@
         """
 
 
+
 class IStoreDirectoryRecord(Interface):
     """
     Directory record object
@@ -62,3 +77,27 @@
     fullName = Attribute("Full name for the entity associated with the record: C{str}")
 
     displayName = Attribute("Display name for entity associated with the record: C{str}")
+
+    def serverURI(): #@NoSelf
+        """
+        Return the URI for the record's server "pod".
+
+        @return: a URI.
+        @rtype: C{str}
+        """
+
+    def server(): #@NoSelf
+        """
+        Return the L{txdav.caldav.datastore.scheduling.localservers.Server} for the record's server "pod".
+
+        @return: a pod server record.
+        @rtype: L{txdav.caldav.datastore.scheduling.localservers.Server}
+        """
+
+    def thisServer(): #@NoSelf
+        """
+        Indicates whether the record is hosted on this server "pod".
+
+        @return: C{True} if hosted by this service.
+        @rtype: C{bool}
+        """

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/inotifications.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/inotifications.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/common/inotifications.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/idav.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/idav.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/idav.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/xml/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 # See LICENSE for details.
 
 ##
-# 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/txdav/xml/base.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/base.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/base.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.
 # Copyright (c) 2007 Twisted Matrix Laboratories.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/element.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/element.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/element.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/txdav/xml/extensions.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/extensions.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/extensions.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 # See LICENSE for details.
 
 ##
-# 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/txdav/xml/parser.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser.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/txdav/xml/parser_base.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser_base.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser_base.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/txdav/xml/parser_etree.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser_etree.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser_etree.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2012-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/txdav/xml/parser_sax.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser_sax.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/parser_sax.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/txdav/xml/rfc2518.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc2518.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc2518.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/txdav/xml/rfc3253.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc3253.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc3253.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/txdav/xml/rfc3744.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc3744.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc3744.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/txdav/xml/rfc4331.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc4331.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc4331.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.
 #
 # 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/txdav/xml/rfc5397.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc5397.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc5397.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/txdav/xml/rfc5842.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc5842.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc5842.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.
 #
 # 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/txdav/xml/rfc5995.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc5995.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc5995.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/txdav/xml/rfc6578.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc6578.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/rfc6578.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/txdav/xml/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/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/txdav/xml/test/test_base.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_base.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_base.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.
 # Copyright (c) 2009 Twisted Matrix Laboratories.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_xml.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_xml.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_xml.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 # See LICENSE for details.
 
 ##
-# 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/txdav/xml/test/test_xml_rfc3744.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_xml_rfc3744.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txdav/xml/test/test_xml_rfc3744.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/txweb2/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 
 ##
 # Copyright (c) 2009 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/auth/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/auth/basic.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/basic.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/basic.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_httpauth -*-
 ##
 # Copyright (c) 2006-2009 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/auth/digest.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/digest.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/digest.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_httpauth -*-
 ##
 # Copyright (c) 2006-2009 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/auth/interfaces.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/interfaces.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/interfaces.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 ##
 # Copyright (c) 2004-2007 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/auth/wrapper.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/wrapper.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/auth/wrapper.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_httpauth -*-
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/channel/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/channel/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/channel/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_cgi,twext.web2.test.test_http -*-
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/channel/http.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/channel/http.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/channel/http.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_http -*-
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2008-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2008-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/txweb2/client/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/client/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/client/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_client -*-
 ##
 # Copyright (c) 2004 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/client/http.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/client/http.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/client/http.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_client -*-
 ##
 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/client/interfaces.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/client/interfaces.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/client/interfaces.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_client -*-
 ##
 # Copyright (c) 2007 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/dav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/__init__.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 
 ##
 # Copyright (c) 2009 Twisted Matrix Laboratories.
-# 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/txweb2/dav/auth.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/auth.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/auth.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/txweb2/dav/fileop.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/fileop.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/fileop.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/txweb2/dav/http.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/http.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/http.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/txweb2/dav/idav.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/idav.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/idav.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/txweb2/dav/method/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/__init__.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/txweb2/dav/method/acl.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/acl.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/acl.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_lock -*-
 ##
-# 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/txweb2/dav/method/copymove.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/copymove.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/copymove.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_copy,twext.web2.dav.test.test_move -*-
 ##
-# 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/txweb2/dav/method/delete.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/delete.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/delete.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_delete -*-
 ##
-# 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/txweb2/dav/method/delete_common.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/delete_common.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/delete_common.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_delete -*-
 ##
-# 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/txweb2/dav/method/get.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/get.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/get.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_lock -*-
 ##
-# 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/txweb2/dav/method/lock.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/lock.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/lock.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_lock -*-
 ##
-# 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/txweb2/dav/method/mkcol.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/mkcol.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/mkcol.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_mkcol -*-
 ##
-# 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/txweb2/dav/method/propfind.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/propfind.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/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/txweb2/dav/method/proppatch.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/proppatch.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/proppatch.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_prop.PROP.test_PROPPATCH -*-
 ##
-# 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/txweb2/dav/method/put.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/put.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/put.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_put -*-
 ##
-# 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/txweb2/dav/method/put_common.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/put_common.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/put_common.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/txweb2/dav/method/report.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_report -*-
 ##
-# 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/txweb2/dav/method/report_acl_principal_prop_set.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_acl_principal_prop_set.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_acl_principal_prop_set.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_report_expand -*-
 ##
-# Copyright (c) 2006-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2006-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/txweb2/dav/method/report_expand.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_expand.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_expand.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_report_expand -*-
 ##
-# 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/txweb2/dav/method/report_principal_match.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_principal_match.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_principal_match.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_report_expand -*-
 ##
-# Copyright (c) 2006-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2006-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/txweb2/dav/method/report_principal_property_search.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_principal_property_search.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_principal_property_search.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_report_expand -*-
 ##
-# Copyright (c) 2006-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2006-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/txweb2/dav/method/report_principal_search_property_set.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_principal_search_property_set.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/method/report_principal_search_property_set.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_report_expand -*-
 ##
-# Copyright (c) 2006-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2006-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/txweb2/dav/noneprops.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/noneprops.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/noneprops.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/txweb2/dav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_resource -*-
 ##
-# 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/txweb2/dav/static.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/static.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/static.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.dav.test.test_static -*-
 ##
-# 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/txweb2/dav/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/__init__.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/__init__.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/txweb2/dav/test/test_acl.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_acl.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_acl.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/txweb2/dav/test/test_auth.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_auth.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_auth.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2012-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2012-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/txweb2/dav/test/test_copy.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_copy.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_copy.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/txweb2/dav/test/test_delete.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_delete.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_delete.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/txweb2/dav/test/test_http.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_http.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_http.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/txweb2/dav/test/test_lock.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_lock.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_lock.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/txweb2/dav/test/test_mkcol.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_mkcol.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_mkcol.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/txweb2/dav/test/test_move.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_move.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_move.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/txweb2/dav/test/test_options.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_options.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_options.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/txweb2/dav/test/test_pipeline.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_pipeline.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_pipeline.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/txweb2/dav/test/test_prop.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_prop.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_prop.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/txweb2/dav/test/test_put.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_put.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_put.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/txweb2/dav/test/test_quota.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_quota.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_quota.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/txweb2/dav/test/test_report.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_report.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_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/txweb2/dav/test/test_report_expand.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_report_expand.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_report_expand.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/txweb2/dav/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_resource.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/txweb2/dav/test/test_static.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_static.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_static.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/txweb2/dav/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/test_util.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/txweb2/dav/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/test/util.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/txweb2/dav/util.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/util.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/util.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.test.test_util -*-
 ##
-# 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/txweb2/dav/xattrprops.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/xattrprops.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/dav/xattrprops.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -2,7 +2,7 @@
 # See LICENSE for details.
 
 ##
-# 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/txweb2/error.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/error.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/error.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_log -*-
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/fileupload.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/fileupload.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/fileupload.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/http.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/http.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/http.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_http -*-
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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
@@ -558,7 +558,7 @@
     """
     def __init__(self, code, jobj):
         """
-        @param xml_responses: an iterable of davxml.Response objects.
+        @param jobj: a Python object that can be serialized to JSON.
         """
         Response.__init__(self, code, stream=json.dumps(jobj))
         self.headers.setHeader("content-type", http_headers.MimeType("application", "json"))

Modified: CalendarServer/branches/users/gaya/cleanrevisions/txweb2/http_headers.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/http_headers.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/http_headers.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_http_headers -*-
 ##
 # Copyright (c) 2008 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/iweb.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/iweb.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/iweb.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test -*-
 ##
 # Copyright (c) 2001-2008 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/log.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/log.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/log.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_log -*-
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/metafd.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/metafd.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/metafd.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,6 +1,6 @@
 # -*- test-case-name: txweb2.test.test_metafd -*-
 ##
-# 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/txweb2/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/resource.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/resource.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_server,twext.web2.test.test_resource -*-
 ##
 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/responsecode.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/responsecode.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/responsecode.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test -*-
 ##
 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/server.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/server.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/server.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_server -*-
 ##
 # Copyright (c) 2001-2008 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/static.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/static.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/static.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_static -*-
 ##
 # Copyright (c) 2001-2008 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/stream.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/stream.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/stream.py	2014-01-12 19:10:08 UTC (rev 12322)
@@ -1,7 +1,7 @@
 # -*- test-case-name: txweb2.test.test_stream -*-
 ##
 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
-# Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2010-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/txweb2/test/test_metafd.py
===================================================================
--- CalendarServer/branches/users/gaya/cleanrevisions/txweb2/test/test_metafd.py	2014-01-12 03:19:13 UTC (rev 12321)
+++ CalendarServer/branches/users/gaya/cleanrevisions/txweb2/test/test_metafd.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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/516bded1/attachment.html>


More information about the calendarserver-changes mailing list