Revision: 4115 http://trac.macosforge.org/projects/calendarserver/changeset/4115 Author: cdaboo@apple.com Date: 2009-04-30 09:40:38 -0700 (Thu, 30 Apr 2009) Log Message: ----------- Properly handle removal of a cancelled override with no master. Modified Paths: -------------- CalendarServer/trunk/run CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py Modified: CalendarServer/trunk/run =================================================================== --- CalendarServer/trunk/run 2009-04-30 16:36:15 UTC (rev 4114) +++ CalendarServer/trunk/run 2009-04-30 16:40:38 UTC (rev 4115) @@ -727,7 +727,7 @@ caldavtester="${top}/CalDAVTester"; -svn_get "CalDAVTester" "${caldavtester}" "${svn_uri_base}/CalDAVTester/trunk" 4088; +svn_get "CalDAVTester" "${caldavtester}" "${svn_uri_base}/CalDAVTester/trunk" 4114; # # PyFlakes Modified: CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py =================================================================== --- CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py 2009-04-30 16:36:15 UTC (rev 4114) +++ CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py 2009-04-30 16:40:38 UTC (rev 4115) @@ -268,9 +268,10 @@ master = component # Normalize each master by adding any STATUS:CANCELLED components as EXDATEs - exdates = set() + exdates = None if master: # Get all EXDATEs in UTC + exdates = set() for exdate in master.properties("EXDATE"): exdates.update([normalizeToUTC(value) for value in exdate.value()]) @@ -288,7 +289,7 @@ component = map1[key] if component.propertyValue("STATUS") != "CANCELLED": # Attendee may decline by EXDATE'ing an instance - we need to handle that - if rid in exdates2: + if exdates2 is None or rid in exdates2: # Mark Attendee as DECLINED in the server instance if self._attendeeDecline(self.newCalendar.overriddenComponent(rid)): changeCausesReply = True @@ -297,7 +298,7 @@ log.debug("attendeeMerge: Missing uncancelled component from first calendar: %s" % (key,)) return False, False, (), None else: - if rid not in exdates2: + if exdates2 is not None and rid not in exdates2: log.debug("attendeeMerge: Missing EXDATE for cancelled components from first calendar: %s" % (key,)) return False, False, (), None else: @@ -315,7 +316,7 @@ _ignore_name, _ignore_uid, rid = key component2 = map2[key] if component2.propertyValue("STATUS") == "CANCELLED": - if rid not in exdates1: + if exdates1 is None or rid not in exdates1: log.debug("attendeeMerge: Cancelled component not found in first calendar (or no EXDATE): %s" % (key,)) return False, False, (), None else: Modified: CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py =================================================================== --- CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py 2009-04-30 16:36:15 UTC (rev 4114) +++ CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py 2009-04-30 16:40:38 UTC (rev 4115) @@ -1838,6 +1838,70 @@ END:VCALENDAR """) ), + ( + "#1.5 Two components, no master, one removal", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080601T120000Z +DTSTART:20080601T120000Z +DTEND:20080601T130000Z +ORGANIZER;CN="User 01":mailto:user1@example.com +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +END:VEVENT +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""", + "mailto:user2@example.com", + (True, True, ("20080601T120000Z",), """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080601T120000Z +DTSTART:20080601T120000Z +DTEND:20080601T130000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=DECLINED:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""") + ), ) for description, calendar1, calendar2, attendee, result in data: @@ -1979,6 +2043,203 @@ END:VCALENDAR """) ), + ( + "#1.3 Removed CANCELLED no master", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +DTSTART:20080604T120000Z +DTEND:20080604T130000Z +RECURRENCE-ID:20080604T120000Z +ORGANIZER;CN="User 01":mailto:user1@example.com +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2@example.com +STATUS:CANCELLED +END:VEVENT +BEGIN:VEVENT +UID:12345-67890 +DTSTART:20080605T120000Z +DTEND:20080605T130000Z +RECURRENCE-ID:20080605T120000Z +ORGANIZER;CN="User 01":mailto:user1@example.com +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2@example.com +END:VEVENT +END:VCALENDAR +""", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +DTSTART:20080605T120000Z +DTEND:20080605T130000Z +RECURRENCE-ID:20080605T120000Z +ORGANIZER;CN="User 01":mailto:user1@example.com +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2@example.com +END:VEVENT +END:VCALENDAR +""", + "mailto:user2@example.com", + (True, False, (), """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080605T120000Z +DTSTART:20080605T120000Z +DTEND:20080605T130000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""") + ), + ( + "#1.4 Two components, no master, cancelled removed", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080601T120000Z +DTSTART:20080601T120000Z +DTEND:20080601T130000Z +ORGANIZER;CN="User 01":mailto:user1@example.com +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +STATUS:CANCELLED +END:VEVENT +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""", + "mailto:user2@example.com", + (True, False, (), """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""") + ), + ( + "#1.5 Add cancelled component, no master", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080601T120000Z +DTSTART:20080601T120000Z +DTEND:20080601T130000Z +ORGANIZER;CN="User 01":mailto:user1@example.com +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +STATUS:CANCELLED +END:VEVENT +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""", + "mailto:user2@example.com", + (False, False, (), None,) + ), + ( + "#1.6 Add uncancelled component, no master", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""", + """BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080601T120000Z +DTSTART:20080601T120000Z +DTEND:20080601T130000Z +ORGANIZER;CN="User 01":mailto:user1@example.com +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +END:VEVENT +BEGIN:VEVENT +UID:12345-67890 +RECURRENCE-ID:20080604T120000Z +DTSTART:20080604T130000Z +DTEND:20080604T140000Z +ATTENDEE:mailto:user1@example.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com +ORGANIZER;CN=User 01:mailto:user1@example.com +END:VEVENT +END:VCALENDAR +""", + "mailto:user2@example.com", + (False, False, (), None,) + ), ) for description, calendar1, calendar2, attendee, result in data: