[CalendarServer-changes] [3731] CalendarServer/branches/users/sagen/migration-3709/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Tue Feb 24 15:43:45 PST 2009
Revision: 3731
http://trac.macosforge.org/projects/calendarserver/changeset/3731
Author: sagen at apple.com
Date: 2009-02-24 15:43:44 -0800 (Tue, 24 Feb 2009)
Log Message:
-----------
Added new methods for creating a file/folder hierarchy in a temporary directory, including file contents and xattrs, and also verifying a hierarchy. Added test to use these.
Modified Paths:
--------------
CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/test/test_upgrade.py
CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/test/util.py
CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/upgrade.py
Modified: CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/test/test_upgrade.py
===================================================================
--- CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/test/test_upgrade.py 2009-02-24 22:52:50 UTC (rev 3730)
+++ CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/test/test_upgrade.py 2009-02-24 23:43:44 UTC (rev 3731)
@@ -28,12 +28,15 @@
class ProxyDBUpgradeTests(TestCase):
- def setUpInitialStates(self):
-
+ def setUpXMLDirectory(self):
xmlFile = os.path.join(os.path.dirname(os.path.dirname(__file__)),
"directory", "test", "accounts.xml")
config.DirectoryService.params.xmlFile = xmlFile
-
+
+
+ def setUpInitialStates(self):
+ self.setUpXMLDirectory()
+
self.setUpOldDocRoot()
self.setUpOldDocRootWithoutDB()
self.setUpNewDocRoot()
@@ -55,7 +58,6 @@
os.mkdir(os.path.join(principals, "locations"))
os.mkdir(os.path.join(principals, "resources"))
os.mkdir(os.path.join(principals, "sudoers"))
- os.mkdir(os.path.join(self.olddocroot, "calendars"))
proxyDB = CalendarUserProxyDatabase(principals)
proxyDB._db()
@@ -64,6 +66,7 @@
os.path.join(principals, CalendarUserProxyDatabase.dbOldFilename),
)
+
def setUpOldDocRootWithoutDB(self):
# Set up doc root
@@ -248,3 +251,172 @@
newValue = zlib.decompress(newValue)
self.assertEquals(newValue, expected)
+
+ #
+ # Shortname not in directory, raise an UpgradeError
+ #
+
+ value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/users/nonexistent/calendar</href>\r\n</calendar-free-busy-set>\r\n"
+ self.assertRaises(UpgradeError, updateFreeBusySet, value, directory)
+
+ def test_calendarsUpgrade(self):
+
+ self.setUpXMLDirectory()
+ directory = getDirectory()
+
+ fbAttr = "WebDAV:{urn:ietf:params:xml:ns:caldav}calendar-free-busy-set"
+
+ before = {
+ "calendars" :
+ {
+ "users" :
+ {
+ "wsanchez" :
+ {
+ "calendar" :
+ {
+ "1E238CA1-3C95-4468-B8CD-C8A399F78C72.ics" :
+ {
+ "@contents" : event01_before,
+ },
+ },
+ "inbox" :
+ {
+ "@xattrs" :
+ {
+ fbAttr : cPickle.dumps(davxml.WebDAVDocument.fromString("<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/users/wsanchez/calendar</href>\r\n</calendar-free-busy-set>\r\n").root_element),
+ },
+ },
+ },
+ },
+ },
+ }
+
+ after = {
+ ".calendarserver_version" :
+ {
+ "@contents" : "1",
+ },
+ "calendars" :
+ {
+ "__uids__" :
+ {
+ "64" :
+ {
+ "23" :
+ {
+ "6423F94A-6B76-4A3A-815B-D52CFD77935D" :
+ {
+ "calendar" :
+ {
+ "1E238CA1-3C95-4468-B8CD-C8A399F78C72.ics" :
+ {
+ "@contents" : event01_after,
+ },
+ },
+ "inbox" :
+ {
+ "@xattrs" :
+ {
+ fbAttr : zlib.compress("<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n <href xmlns='DAV:'>/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/calendar/</href>\r\n</calendar-free-busy-set>\r\n"),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ root = self.createHierarchy(before)
+
+ config.DocumentRoot = root
+ config.DataRoot = root
+
+ upgradeData(config)
+ self.assertTrue(self.compareHierarchy(root, after))
+
+
+event01_before = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 3.0//EN
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:US/Pacific
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0800
+TZOFFSETTO:-0700
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+TZNAME:PDT
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0800
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+TZNAME:PST
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+SEQUENCE:2
+TRANSP:OPAQUE
+UID:1E238CA1-3C95-4468-B8CD-C8A399F78C71
+DTSTART;TZID=US/Pacific:20090203T120000
+ORGANIZER;CN="Cyrus":mailto:cdaboo at example.com
+DTSTAMP:20090203T181924Z
+SUMMARY:New Event
+DESCRIPTION:This has \\" Bad Quotes \\" in it
+ATTENDEE;CN="Wilfredo";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:mailto:wsanchez
+ @example.com
+ATTENDEE;CN="Cyrus";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED;ROLE=REQ-PARTICI
+ PANT:mailto:cdaboo at example.com
+CREATED:20090203T181910Z
+DTEND;TZID=US/Pacific:20090203T130000
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+event01_after = """BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//Apple Inc.//iCal 3.0//EN
+BEGIN:VTIMEZONE
+TZID:US/Pacific
+BEGIN:STANDARD
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+TZNAME:PST
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0800
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+TZNAME:PDT
+TZOFFSETFROM:-0800
+TZOFFSETTO:-0700
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:1E238CA1-3C95-4468-B8CD-C8A399F78C71
+DTSTART;TZID=US/Pacific:20090203T120000
+DTEND;TZID=US/Pacific:20090203T130000
+ATTENDEE;CN=Wilfredo Sanchez;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED;X-CALENDA
+ RSERVER-EMAIL=wsanchez at example.com:urn:uuid:6423F94A-6B76-4A3A-815B-D52CFD
+ 77935D
+ATTENDEE;CN=Cyrus Daboo;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED;ROLE=REQ-PARTI
+ CIPANT;X-CALENDARSERVER-EMAIL=cdaboo at example.com:urn:uuid:5A985493-EE2C-46
+ 65-94CF-4DFEA3A89500
+CREATED:20090203T181910Z
+DESCRIPTION:This has " Bad Quotes " in it
+DTSTAMP:20090203T181924Z
+ORGANIZER;CN=Cyrus Daboo;X-CALENDARSERVER-EMAIL=cdaboo at example.com:urn:uui
+ d:5A985493-EE2C-4665-94CF-4DFEA3A89500
+SEQUENCE:2
+SUMMARY:New Event
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
Modified: CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/test/util.py 2009-02-24 22:52:50 UTC (rev 3730)
+++ CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/test/util.py 2009-02-24 23:43:44 UTC (rev 3731)
@@ -14,7 +14,10 @@
# limitations under the License.
##
+from __future__ import with_statement
+
import os
+import xattr
from twisted.python.failure import Failure
from twisted.internet.defer import succeed, fail
@@ -38,6 +41,75 @@
config.Memcached.ClientEnabled = False
config.Memcached.ServerEnabled = False
+ def createHierarchy(self, structure):
+ root = self.mktemp()
+ os.mkdir(root)
+
+ def createChildren(parent, subStructure):
+ for childName, childStructure in subStructure.iteritems():
+
+ if childName.startswith("@"):
+ continue
+
+ childPath = os.path.join(parent, childName)
+ if childStructure.has_key("@contents"):
+ # This is a file
+ with open(childPath, "w") as child:
+ child.write(childStructure["@contents"])
+
+ else:
+ # This is a directory
+ os.mkdir(childPath)
+ createChildren(childPath, childStructure)
+
+ if childStructure.has_key("@xattrs"):
+ xattrs = childStructure["@xattrs"]
+ for attr, value in xattrs.iteritems():
+ xattr.setxattr(childPath, attr, value)
+
+ createChildren(root, structure)
+ return root
+
+ def compareHierarchy(self, root, structure):
+
+ def compareChildren(parent, subStructure):
+
+ for childName, childStructure in subStructure.iteritems():
+
+ if childName.startswith("@"):
+ continue
+
+ childPath = os.path.join(parent, childName)
+
+ if not os.path.exists(childPath):
+ return False
+
+ if childStructure.has_key("@contents"):
+ # This is a file
+ with open(childPath) as child:
+ contents = child.read()
+ if contents != childStructure["@contents"]:
+ return False
+
+ else:
+ # This is a directory
+ if not compareChildren(childPath, childStructure):
+ return False
+
+ if childStructure.has_key("@xattrs"):
+ xattrs = childStructure["@xattrs"]
+ for attr, value in xattrs.iteritems():
+ try:
+ if xattr.getxattr(childPath, attr) != value:
+ return False
+ except:
+ return False
+
+ return True
+
+ return compareChildren(root, structure)
+
+
class InMemoryPropertyStore(object):
def __init__(self):
class _FauxPath(object):
Modified: CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/upgrade.py
===================================================================
--- CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/upgrade.py 2009-02-24 22:52:50 UTC (rev 3730)
+++ CalendarServer/branches/users/sagen/migration-3709/twistedcaldav/upgrade.py 2009-02-24 23:43:44 UTC (rev 3731)
@@ -103,19 +103,19 @@
try:
data, fixed = fixBadQuotes(data)
if fixed:
- log.info("Fixing bad quotes in %s" % (oldRes,))
+ log.info("Fixing bad quotes in %s" % (resPath,))
except Exception, e:
log.error("Error while fixing bad quotes in %s: %s" %
- (oldRes, e))
+ (resPath, e))
raise
try:
data, fixed = normalizeCUAddrs(data, directory)
if fixed:
- log.info("Normalized CUAddrs in %s" % (oldRes,))
+ log.info("Normalized CUAddrs in %s" % (resPath,))
except Exception, e:
log.error("Error while normalizing %s: %s" %
- (oldRes, e))
+ (resPath, e))
raise
# Write to a new file, then rename it over the old one
@@ -198,8 +198,11 @@
% (oldHome, newHome)
)
+ os.makedirs(os.path.dirname(newHome.rstrip("/")))
+ os.rename(oldHome, newHome)
+
directory = getDirectory()
docRoot = config.DocumentRoot
@@ -270,16 +273,13 @@
-# Each method in this array will upgrade from one version to the next;
-# the index of each method within the array corresponds to the on-disk
-# version number that it upgrades from. For example, if the on-disk
-# .version file contains a "3", but there are 6 methods in this array,
-# methods 3 through 5 (using 0-based array indexing) will be executed in
-# order.
+# The on-disk version number (which defaults to zero if .calendarserver_version
+# doesn't exist), is compared with each of the numbers in the upgradeMethods
+# array. If it is less than the number, the associated method is called.
+
upgradeMethods = [
- upgrade_to_1,
+ (1, upgrade_to_1),
]
-# MOR: Change the above to an array of tuples
def upgradeData(config):
@@ -290,8 +290,6 @@
versionFilePath = os.path.join(docRoot, ".calendarserver_version")
- newestVersion = len(upgradeMethods)
-
onDiskVersion = 0
if os.path.exists(versionFilePath):
try:
@@ -304,11 +302,12 @@
log.error("Invalid version number in %s; skipping migration" %
(versionFilePath,))
- for upgradeVersion in range(onDiskVersion, newestVersion):
- log.info("Upgrading to version %d" % (upgradeVersion+1,))
- upgradeMethods[upgradeVersion](config)
- with open(versionFilePath, "w") as verFile:
- verFile.write(str(upgradeVersion+1))
+ for version, method in upgradeMethods:
+ if onDiskVersion < version:
+ log.info("Upgrading to version %d" % (version,))
+ method(config)
+ with open(versionFilePath, "w") as verFile:
+ verFile.write(str(version))
class UpgradeError(RuntimeError):
@@ -357,7 +356,7 @@
except UnpicklingError:
log.err("Invalid xattr property value for: %s" % attr)
# MOR: continue on?
- return
+ return None
fbset = set()
didUpdate = False
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090224/df4ac80c/attachment-0001.html>
More information about the calendarserver-changes
mailing list