[Checkins] SVN: Products.ZopeVersionControl/tags/0.3.4/ Import new
quasi-release, 0.3.4.
Tres Seaver
tseaver at palladion.com
Mon Feb 5 11:18:43 EST 2007
Log message for revision 72373:
Import new quasi-release, 0.3.4.
Changed:
A Products.ZopeVersionControl/tags/0.3.4/
A Products.ZopeVersionControl/tags/0.3.4/CHANGES.txt
A Products.ZopeVersionControl/tags/0.3.4/EventLog.py
A Products.ZopeVersionControl/tags/0.3.4/IVersionControl.py
A Products.ZopeVersionControl/tags/0.3.4/Repository.py
A Products.ZopeVersionControl/tags/0.3.4/SequenceWrapper.py
A Products.ZopeVersionControl/tags/0.3.4/Utility.py
A Products.ZopeVersionControl/tags/0.3.4/Version.py
A Products.ZopeVersionControl/tags/0.3.4/VersionHistory.py
A Products.ZopeVersionControl/tags/0.3.4/VersionSupport.py
A Products.ZopeVersionControl/tags/0.3.4/ZopeRepository.py
A Products.ZopeVersionControl/tags/0.3.4/ZopeVersion.py
A Products.ZopeVersionControl/tags/0.3.4/ZopeVersionHistory.py
A Products.ZopeVersionControl/tags/0.3.4/__init__.py
A Products.ZopeVersionControl/tags/0.3.4/dtml/
A Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryAddForm.dtml
A Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryManageMain.dtml
A Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryProperties.dtml
A Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlLog.dtml
A Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlMain.dtml
A Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryManageMain.dtml
A Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryProperties.dtml
A Products.ZopeVersionControl/tags/0.3.4/dtml/VersionManageMain.dtml
A Products.ZopeVersionControl/tags/0.3.4/dtml/VersionProperties.dtml
A Products.ZopeVersionControl/tags/0.3.4/help/
A Products.ZopeVersionControl/tags/0.3.4/help/Repository-Add.stx
A Products.ZopeVersionControl/tags/0.3.4/help/Repository-Manage.stx
A Products.ZopeVersionControl/tags/0.3.4/help/Repository-Properties.stx
A Products.ZopeVersionControl/tags/0.3.4/help/Version-Manage.stx
A Products.ZopeVersionControl/tags/0.3.4/help/Version-Properties.stx
A Products.ZopeVersionControl/tags/0.3.4/help/VersionControl.stx
A Products.ZopeVersionControl/tags/0.3.4/help/VersionHistory-Manage.stx
A Products.ZopeVersionControl/tags/0.3.4/help/VersionHistory-Properties.stx
A Products.ZopeVersionControl/tags/0.3.4/issues.txt
A Products.ZopeVersionControl/tags/0.3.4/nonversioned.py
A Products.ZopeVersionControl/tags/0.3.4/tests/
A Products.ZopeVersionControl/tags/0.3.4/tests/__init__.py
A Products.ZopeVersionControl/tags/0.3.4/tests/common.py
A Products.ZopeVersionControl/tags/0.3.4/tests/testReferenceVersioning.py
A Products.ZopeVersionControl/tags/0.3.4/tests/testVersionControl.py
A Products.ZopeVersionControl/tags/0.3.4/tests/test_all.py
A Products.ZopeVersionControl/tags/0.3.4/version.txt
A Products.ZopeVersionControl/tags/0.3.4/www/
A Products.ZopeVersionControl/tags/0.3.4/www/Repository.gif
A Products.ZopeVersionControl/tags/0.3.4/www/Version.gif
A Products.ZopeVersionControl/tags/0.3.4/www/VersionHistory.gif
-=-
Added: Products.ZopeVersionControl/tags/0.3.4/CHANGES.txt
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/CHANGES.txt 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/CHANGES.txt 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,49 @@
+ZopeVersionControl Product Changelog
+
+ ZopeVersionControl 0.3.4 (2007/02/05)
+
+ - Add omitted 'tests/common.py' module.
+
+ ZopeVersionControl 0.3.3 (2006/09/20)
+
+ - __init__.py, nonversioned.py: Fixed compatibility with Zope 2.8
+ and new-style objects (http://www.zope.org/Collectors/Zope/2137)
+
+ ZopeVersionControl 0.3.2 (2006/06/02)
+
+ - ZopeRepository.py: make ZR addable via GenericSetup toolset
+ (http://www.zope.org/Collectors/CMF/438).
+
+ - Utility.py: Import cleanup, including compatibility with ZODB 3.3+
+ location of 'refrencesf'.
+
+ ZopeVersionControl 0.3.1 (2004/05/03)
+
+ - IVersionControl.py: Added a module-scope alias for the benefit
+ of older software which depended on the old name.
+
+ - Hardened unit tests against the absence of the References product.
+
+ ZopeVersionControl 0.3 (2004/04/20)
+
+ - Refined the pattern for maintaining parts of objects independently
+ of version control. This is a generalization of the mechanism for
+ versioning container items. IVersionedContainer is now named
+ INonVersionedData and has more descriptive method names.
+
+ - 'updateResource' and 'uncheckoutResource' now retain the identity
+ of the object being versioned. That is, they never replace an
+ object with a new object, but instead change the state of an
+ existing object.
+
+ 'updateResource' and 'uncheckoutResource' used to replace the
+ object in its container, but this strategy had two flaws:
+
+ 1. It required ZopeVersionControl to use the ObjectManager API.
+ Version control should not require versionable objects to be
+ contained in ObjectManagers.
+
+ 2. It assumes that versionable objects are simply wrapped using
+ acquisition. References (symlink-like objects) break this
+ assumption.
+
Property changes on: Products.ZopeVersionControl/tags/0.3.4/CHANGES.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/EventLog.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/EventLog.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/EventLog.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,72 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+from Globals import InitializeClass, Persistent
+from AccessControl import ClassSecurityInfo
+from BTrees.IOBTree import IOBTree
+from Utility import _findUserId
+import sys, time
+
+
+class EventLog(Persistent):
+ """An EventLog encapsulates a collection of log entries."""
+
+ def __init__(self):
+ self._data = IOBTree()
+
+ security = ClassSecurityInfo()
+
+ security.declarePrivate('addEntry')
+ def addEntry(self, entry):
+ """Add a new log entry."""
+ if len(self._data):
+ key = self._data.minKey() - 1
+ else:
+ key = sys.maxint
+ self._data[key] = entry
+
+ security.declarePrivate('getEntries')
+ def getEntries(self):
+ """Return a sequence of log entries."""
+ return self._data.values()
+
+ def __len__(self):
+ return len(self._data)
+
+ def __nonzero__(self):
+ return len(self._data) > 0
+
+InitializeClass(EventLog)
+
+
+class LogEntry(Persistent):
+ """A LogEntry contains audit information about a version control
+ operation. Actions that cause audit records to be created include
+ checkout and checkin. Log entry information can be read (but
+ not changed) by restricted code."""
+
+ # These action constants represent the possible auditable actions.
+ ACTION_CHECKOUT = 0
+ ACTION_CHECKIN = 1
+ ACTION_UNCHECKOUT = 2
+ ACTION_UPDATE = 3
+
+ def __init__(self, version_id, action, path=None, message=''):
+ self.timestamp = time.time()
+ self.version_id = version_id
+ self.action = action
+ self.message = message
+ self.user_id = _findUserId()
+ self.path = path
+
+InitializeClass(LogEntry)
Property changes on: Products.ZopeVersionControl/tags/0.3.4/EventLog.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/IVersionControl.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/IVersionControl.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/IVersionControl.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,269 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.7 $'[11:-2]
+
+from Interface import Interface
+
+
+class IVersionControl(Interface):
+ """The version control interface serves as the main API for version
+ control operations. The interface hides most of the details of
+ version data storage and retrieval.
+
+ In Zope 3, the version control interface will probably be implemented
+ by a version control service. In the meantime, it may be implemented
+ directly by repository implementations (or other things, like CMF
+ tools).
+
+ The goal of this version of the version control interface is to
+ support simple linear versioning with support for labelled versions.
+ Future versions or extensions of this interface will likely support
+ more advanced version control features such as concurrent lines of
+ descent (activities) and collection versioning."""
+
+ def isAVersionableResource(object):
+ """
+ Returns true if the given object is a versionable resource.
+
+ Permission: public
+ """
+
+ def isUnderVersionControl(object):
+ """
+ Returns true if the given object is under version control.
+
+ Permission: public
+ """
+
+ def isResourceUpToDate(object, require_branch=0):
+ """
+ Returns true if a resource is based on the latest version. Note
+ that the latest version is in the context of any activity (branch).
+
+ If the require_branch flag is true, this method returns false if
+ the resource is updated to a particular version, label, or date.
+ Useful for determining whether a call to checkoutResource()
+ will succeed.
+
+ Permission: public
+ """
+
+ def isResourceChanged(object):
+ """
+ Return true if the state of a resource has changed in a transaction
+ *after* the version bookkeeping was saved. Note that this method is
+ not appropriate for detecting changes within a transaction!
+
+ Permission: public
+ """
+
+ def getVersionInfo(object):
+ """
+ Return the VersionInfo associated with the given object. The
+ VersionInfo object contains version control bookkeeping information.
+ If the object is not under version control, a VersionControlError
+ will be raised.
+
+ Permission: public
+ """
+
+ def applyVersionControl(object, message=None):
+ """
+ Place the given object under version control. A VersionControlError
+ will be raised if the object is already under version control.
+
+ After being placed under version control, the resource is logically
+ in the 'checked-in' state.
+
+ If no message is passed the 'Initial checkin.' message string is
+ written as the message log entry.
+
+ Permission: Use version control
+ """
+
+ def checkoutResource(object):
+ """
+ Put the given version-controlled object into the 'checked-out'
+ state, allowing changes to be made to the object. If the object is
+ not under version control or the object is already checked out, a
+ VersionControlError will be raised.
+
+ Permission: Use version control
+ """
+
+ def checkinResource(object, message=''):
+ """
+ Check-in (create a new version) of the given object, updating the
+ state and bookkeeping information of the given object. The optional
+ message should describe the changes being committed. If the object
+ is not under version control or is already in the checked-in state,
+ a VersionControlError will be raised.
+
+ Permission: Use version control
+ """
+
+ def uncheckoutResource(object):
+ """
+ Discard changes to the given object made since the last checkout.
+ If the object is not under version control or is not checked out,
+ a VersionControlError will be raised.
+ """
+
+ def updateResource(object, selector=None):
+ """
+ Update the state of the given object to that of a specific version
+ of the object. The object must be in the checked-in state to be
+ updated. The selector must be a string (version id, activity id,
+ label or date) that is used to select a version from the version
+ history.
+
+ Permission: Use version control
+ """
+
+ def labelResource(object, label, force=None):
+ """
+ Associate the given resource with a label. If force is true, then
+ any existing association with the given label will be removed and
+ replaced with the new association. If force is false and there is
+ an existing association with the given label, a VersionControlError
+ will be raised.
+
+ Permission: Use version control
+ """
+
+ def getVersionOfResource(history_id, selector):
+ """
+ Given a version history id and a version selector, return the
+ object as of that version. Note that the returned object has no
+ acquisition context. The selector must be a string (version id,
+ activity id, label or date) that is used to select a version
+ from the version history.
+
+ Permission: Use version control
+ """
+
+ def getVersionIds(object):
+ """
+ Return a sequence of the (string) version ids corresponding to the
+ available versions of an object. This should be used by UI elements
+ to populate version selection widgets, etc.
+
+ Permission: Use version control
+ """
+
+ def getLabelsForResource(object):
+ """
+ Return a sequence of the (string) labels corresponding to the
+ versions of the given object that have been associated with a
+ label. This should be used by UI elements to populate version
+ selection widgets, etc.
+
+ Permission: Use version control
+ """
+
+ def getLogEntries(object):
+ """
+ Return a sequence of LogEntry objects (most recent first) that
+ are associated with a version-controlled object.
+
+ Permission: Use version control
+ """
+
+class IVersionInfo(Interface):
+ """The IVersionInfo interface provides access to version control
+ bookkeeping information. The fields provided by this interface
+ are:
+
+ timestamp - a float (time.time() format) value indicating the
+ time that the bookkeeping information was created.
+
+ history_id - the id of the version history related to the version
+ controlled resource.
+
+ version_id - the version id that the version controlled resource
+ is based upon.
+
+ status - an enumerated value indicating the status of the version
+ controlled resource. This value is one of the VersionInfo class
+ constants CHECKED_IN or CHECKED_OUT.
+
+ sticky - sticky tag information used internally by the version
+ control implementation.
+
+ user_id - the id of the effective user at the time the bookkeeping
+ information was created.
+ """
+
+class ILogEntry(Interface):
+ """The ILogEntry interface provides access to the information in an
+ audit log entry. The fields provided by this interface are:
+
+ timestamp - a float (time.time() format) value indicating the
+ time that the log entry was created.
+
+ version_id - the version id of the version controlled resource
+ related to the log entry.
+
+ action - an enumerated value indicating the action that was taken.
+ This value is one of the LogEntry class constants ACTION_CHECKOUT,
+ ACTION_CHECKIN, ACTION_UNCHECKOUT, ACTION_UPDATE.
+
+ message - a string message provided by the user at the time of the
+ action. This string may be empty.
+
+ user_id - the id of the user causing the audited action.
+
+ path - the path to the object upon which the action was taken.
+
+ """
+
+
+class INonVersionedData(Interface):
+ """Controls what parts of an object fall outside version control.
+
+ Containerish objects implement this interface to allow the items they
+ contain to be versioned independently of the container.
+ """
+
+ def listNonVersionedObjects():
+ """Returns a list of subobjects that should not be pickled.
+
+ The objects in the list must not be wrapped, because only the
+ identity of the objects will be considered. The version
+ repository uses this method to avoid cloning subobjects that
+ will soon be removed by removeNonVersionedData.
+ """
+
+ def removeNonVersionedData():
+ """Removes the non-versioned data from this object.
+
+ The version repository uses this method before storing an
+ object in the version repository.
+ """
+
+ def getNonVersionedData():
+ """Returns an opaque object containing the non-versioned data.
+
+ The version repository uses this method before reverting an
+ object to a revision.
+ """
+
+ def restoreNonVersionedData(dict):
+ """Restores non-versioned data to this object.
+
+ The version repository uses this method after reverting an
+ object to a revision.
+ """
+
+IVersionedContainer = INonVersionedData
Property changes on: Products.ZopeVersionControl/tags/0.3.4/IVersionControl.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/Repository.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/Repository.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/Repository.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,488 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.14 $'[11:-2]
+
+import time
+from random import randint
+
+from Acquisition import Implicit, aq_parent, aq_inner
+from ZopeVersionHistory import ZopeVersionHistory
+from Globals import InitializeClass, Persistent
+from AccessControl import ClassSecurityInfo
+from Utility import use_vc_permission, _findPath
+from Utility import isAVersionableResource, VersionControlError, VersionInfo
+from DateTime.DateTime import DateTime
+from BTrees.OOBTree import OOBTree
+from BTrees.OIBTree import OIBTree
+
+from EventLog import LogEntry
+import Utility
+from nonversioned import getNonVersionedData, restoreNonVersionedData
+
+
+class Repository(Implicit, Persistent):
+ """The repository implementation manages the actual data of versions
+ and version histories. It does not handle user interface issues."""
+
+ def __init__(self):
+ # These keep track of symbolic label and branch names that
+ # have been used to ensure that they don't collide.
+ self._branches = OIBTree()
+ self._branches['mainline'] = 1
+ self._labels = OIBTree()
+
+ self._histories = OOBTree()
+ self._created = time.time()
+
+ security = ClassSecurityInfo()
+
+ security.declarePrivate('createVersionHistory')
+ def createVersionHistory(self, object):
+ """Internal: create a new version history for a resource."""
+ # When one creates the first version in a version history, neither
+ # the version or version history yet have a _p_jar, which causes
+ # copy operations to fail. To work around that, we share our _p_jar.
+ history_id = None
+ while history_id is None or self._histories.has_key(history_id):
+ history_id = str(randint(1, 9999999999))
+ history = ZopeVersionHistory(history_id, object)
+ self._histories[history_id] = history
+ return history.__of__(self)
+
+ security.declarePrivate('getVersionHistory')
+ def getVersionHistory(self, history_id):
+ """Internal: return a version history given a version history id."""
+ return self._histories[history_id].__of__(self)
+
+ security.declarePrivate('replaceState')
+ def replaceState(self, obj, new_state):
+ """Internal: replace the state of a persistent object.
+ """
+ non_versioned = getNonVersionedData(obj)
+ # XXX There ought to be some way to do this more cleanly.
+ # This fills the __dict__ of the old object with new state.
+ # The other way to achieve the desired effect is to replace
+ # the object in its container, but this method preserves the
+ # identity of the object.
+ if obj.__class__ is not new_state.__class__:
+ raise VersionControlError(
+ "The class of the versioned object has changed. %s != %s"
+ % (repr(obj.__class__, new_state.__class__)))
+ obj._p_changed = 1
+ for key in obj.__dict__.keys():
+ if not new_state.__dict__.has_key(key):
+ del obj.__dict__[key]
+ for key, value in new_state.__dict__.items():
+ obj.__dict__[key] = value
+ if non_versioned:
+ # Restore the non-versioned data into the new state.
+ restoreNonVersionedData(obj, non_versioned)
+ return obj
+
+ #####################################################################
+ # This is the implementation of the public version control interface.
+ #####################################################################
+
+ security.declarePublic('isAVersionableResource')
+ def isAVersionableResource(self, obj):
+ # For now, an object must be persistent (have its own db record)
+ # in order to be considered a versionable resource.
+ return isAVersionableResource(obj)
+
+ security.declarePublic('isUnderVersionControl')
+ def isUnderVersionControl(self, object):
+ return hasattr(object, '__vc_info__')
+
+ security.declarePublic('isResourceUpToDate')
+ def isResourceUpToDate(self, object, require_branch=0):
+ info = self.getVersionInfo(object)
+ history = self.getVersionHistory(info.history_id)
+ branch = 'mainline'
+ if info.sticky:
+ if info.sticky[0] == 'B':
+ branch = info.sticky[1]
+ elif require_branch:
+ # The object is updated to a particular version
+ # rather than a branch. The caller
+ # requires a branch.
+ return 0
+ return history.isLatestVersion(info.version_id, branch)
+
+ security.declarePublic('isResourceChanged')
+ def isResourceChanged(self, object):
+ # Return true if the state of a resource has changed in a transaction
+ # *after* the version bookkeeping was saved. Note that this method is
+ # not appropriate for detecting changes within a transaction!
+ info = self.getVersionInfo(object)
+ itime = getattr(info, '_p_mtime', None)
+ if itime is None:
+ return 0
+ mtime = Utility._findModificationTime(object)
+ if mtime is None:
+ return 0
+ return mtime > itime
+
+ security.declarePublic('getVersionInfo')
+ def getVersionInfo(self, object):
+ info = getattr(object, '__vc_info__', None)
+ if info is not None:
+ return info
+ raise VersionControlError(
+ 'The specified resource is not under version control.'
+ )
+
+ security.declareProtected(use_vc_permission, 'applyVersionControl')
+ def applyVersionControl(self, object, message=None):
+ if self.isUnderVersionControl(object):
+ raise VersionControlError(
+ 'The resource is already under version control.'
+ )
+ if not self.isAVersionableResource(object):
+ raise VersionControlError(
+ 'This resource cannot be put under version control.'
+ )
+
+ # Need to check the parent to see if the container of the object
+ # being put under version control is itself a version-controlled
+ # object. If so, we need to use the branch id of the container.
+ branch = 'mainline'
+ parent = aq_parent(aq_inner(object))
+ p_info = getattr(parent, '__vc_info__', None)
+ if p_info is not None:
+ sticky = p_info.sticky
+ if sticky and sticky[0] == 'B':
+ branch = sticky[1]
+
+ # Create a new version history and initial version object.
+ history = self.createVersionHistory(object)
+ version = history.createVersion(object, branch)
+
+ history_id = history.getId()
+ version_id = version.getId()
+
+ # Add bookkeeping information to the version controlled object.
+ info = VersionInfo(history_id, version_id, VersionInfo.CHECKED_IN)
+ if branch != 'mainline':
+ info.sticky = ('B', branch)
+ object.__vc_info__ = info
+
+ # Save an audit record of the action being performed.
+ history.addLogEntry(version_id,
+ LogEntry.ACTION_CHECKIN,
+ _findPath(object),
+ message is None and 'Initial checkin.' or message
+ )
+ return object
+
+ security.declareProtected(use_vc_permission, 'checkoutResource')
+ def checkoutResource(self, object):
+ info = self.getVersionInfo(object)
+ if info.status != info.CHECKED_IN:
+ raise VersionControlError(
+ 'The selected resource is already checked out.'
+ )
+
+ if info.sticky and info.sticky[0] != 'B':
+ raise VersionControlError(
+ 'The selected resource has been updated to a particular '
+ 'version, label or date. The resource must be updated to '
+ 'the mainline or a branch before it may be checked out.'
+ )
+
+ if not self.isResourceUpToDate(object):
+ raise VersionControlError(
+ 'The selected resource is not up to date!'
+ )
+
+ history = self.getVersionHistory(info.history_id)
+ ob_path = _findPath(object)
+
+ # Save an audit record of the action being performed.
+ history.addLogEntry(info.version_id,
+ LogEntry.ACTION_CHECKOUT,
+ ob_path
+ )
+
+ # Update bookkeeping information.
+ newinfo = info.clone()
+ newinfo.status = newinfo.CHECKED_OUT
+ object.__vc_info__ = newinfo
+ return object
+
+ security.declareProtected(use_vc_permission, 'checkinResource')
+ def checkinResource(self, object, message=''):
+ info = self.getVersionInfo(object)
+ if info.status != info.CHECKED_OUT:
+ raise VersionControlError(
+ 'The selected resource is not checked out.'
+ )
+
+ if info.sticky and info.sticky[0] != 'B':
+ raise VersionControlError(
+ 'The selected resource has been updated to a particular '
+ 'version, label or date. The resource must be updated to '
+ 'the mainline or a branch before it may be checked in.'
+ )
+
+ if not self.isResourceUpToDate(object):
+ raise VersionControlError(
+ 'The selected resource is not up to date!'
+ )
+
+ history = self.getVersionHistory(info.history_id)
+ ob_path = _findPath(object)
+
+ branch = 'mainline'
+ if info.sticky is not None and info.sticky[0] == 'B':
+ branch = info.sticky[1]
+
+ version = history.createVersion(object, branch)
+
+ # Save an audit record of the action being performed.
+ history.addLogEntry(version.getId(),
+ LogEntry.ACTION_CHECKIN,
+ ob_path,
+ message
+ )
+
+ # Update bookkeeping information.
+ newinfo = info.clone()
+ newinfo.version_id = version.getId()
+ newinfo.status = newinfo.CHECKED_IN
+ object.__vc_info__ = newinfo
+ return object
+
+ security.declareProtected(use_vc_permission, 'uncheckoutResource')
+ def uncheckoutResource(self, object):
+ info = self.getVersionInfo(object)
+ if info.status != info.CHECKED_OUT:
+ raise VersionControlError(
+ 'The selected resource is not checked out.'
+ )
+
+ history = self.getVersionHistory(info.history_id)
+ ob_path = _findPath(object)
+
+ version = history.getVersionById(info.version_id)
+ new_obj = version.copyState()
+
+ # Save an audit record of the action being performed.
+ history.addLogEntry(info.version_id,
+ LogEntry.ACTION_UNCHECKOUT,
+ ob_path
+ )
+
+ # Replace the state of the object with a reverted state.
+ new_obj = self.replaceState(object, new_obj)
+
+ # Update bookkeeping information.
+ newinfo = info.clone()
+ newinfo.version_id = version.getId()
+ newinfo.status = newinfo.CHECKED_IN
+ new_obj.__vc_info__ = newinfo
+ return new_obj
+
+ security.declareProtected(use_vc_permission, 'updateResource')
+ def updateResource(self, object, selector=None):
+ info = self.getVersionInfo(object)
+ if info.status != info.CHECKED_IN:
+ raise VersionControlError(
+ 'The selected resource must be checked in to be updated.'
+ )
+
+ history = self.getVersionHistory(info.history_id)
+ version = None
+ sticky = info.sticky
+
+ if not selector:
+ # If selector is null, update to the latest version taking any
+ # sticky attrs into account (branch, date). Note that the sticky
+ # tag could also be a date or version id. We don't bother checking
+ # for those, since in both cases we do nothing (because we'll
+ # always be up to date until the sticky tag changes).
+ if sticky and sticky[0] == 'L':
+ # A label sticky tag, so update to that label (since it is
+ # possible, but unlikely, that the label has been moved).
+ version = history.getVersionByLabel(sticky[1])
+ elif sticky and sticky[0] == 'B':
+ # A branch sticky tag. Update to latest version on branch.
+ version = history.getLatestVersion(selector)
+ else:
+ # Update to mainline, forgetting any date or version id
+ # sticky tag that was previously associated with the object.
+ version = history.getLatestVersion('mainline')
+ sticky = None
+ else:
+ # If the selector is non-null, we find the version specified
+ # and update the sticky tag. Later we'll check the version we
+ # found and decide whether we really need to update the object.
+ if history.hasVersionId(selector):
+ version = history.getVersionById(selector)
+ sticky = ('V', selector)
+
+ elif self._labels.has_key(selector):
+ version = history.getVersionByLabel(selector)
+ sticky = ('L', selector)
+
+ elif self._branches.has_key(selector):
+ version = history.getLatestVersion(selector)
+ if selector == 'mainline':
+ sticky = None
+ else:
+ sticky = ('B', selector)
+ else:
+ try: date = DateTime(selector)
+ except:
+ raise VersionControlError(
+ 'Invalid version selector: %s' % selector
+ )
+ else:
+ timestamp = date.timeTime()
+ sticky = ('D', timestamp)
+ # Fix!
+ branch = history.findBranchId(info.version_id)
+ version = history.getVersionByDate(branch, timestamp)
+
+ # If the state of the resource really needs to be changed, do the
+ # update and make a log entry for the update.
+ version_id = version and version.getId() or info.version_id
+ new_object = object
+ if version and (version_id != info.version_id):
+ new_object = version.copyState()
+ new_object = self.replaceState(object, new_object)
+
+ history.addLogEntry(version_id,
+ LogEntry.ACTION_UPDATE,
+ _findPath(new_object)
+ )
+
+ # Update bookkeeping information.
+ newinfo = info.clone(1)
+ newinfo.version_id = version_id
+ newinfo.status = newinfo.CHECKED_IN
+ if sticky is not None:
+ newinfo.sticky = sticky
+ new_object.__vc_info__ = newinfo
+ return new_object
+
+ security.declareProtected(use_vc_permission, 'labelResource')
+ def labelResource(self, object, label, force=0):
+ info = self.getVersionInfo(object)
+ if info.status != info.CHECKED_IN:
+ raise VersionControlError(
+ 'The selected resource must be checked in to be labeled.'
+ )
+
+ # Make sure that labels and branch ids do not collide.
+ if self._branches.has_key(label) or label == 'mainline':
+ raise VersionControlError(
+ 'The label value given is already in use as an activity id.'
+ )
+ if not self._labels.has_key(label):
+ self._labels[label] = 1
+
+ history = self.getVersionHistory(info.history_id)
+ history.labelVersion(info.version_id, label, force)
+ return object
+
+ security.declareProtected(use_vc_permission, 'makeActivity')
+ def makeActivity(self, object, branch_id):
+ # Note - this is not part of the official version control API yet.
+ # It is here to allow unit testing of the architectural aspects
+ # that are already in place to support activities in the future.
+
+ info = self.getVersionInfo(object)
+ if info.status != info.CHECKED_IN:
+ raise VersionControlError(
+ 'The selected resource must be checked in.'
+ )
+
+ branch_id = branch_id or None
+
+ # Make sure that activity ids and labels do not collide.
+ if self._labels.has_key(branch_id) or branch_id == 'mainline':
+ raise VersionControlError(
+ 'The value given is already in use as a version label.'
+ )
+
+ if not self._branches.has_key(branch_id):
+ self._branches[branch_id] = 1
+
+ history = self.getVersionHistory(info.history_id)
+
+ if history._branches.has_key(branch_id):
+ raise VersionControlError(
+ 'The resource is already associated with the given activity.'
+ )
+
+ history.createBranch(branch_id, info.version_id)
+ return object
+
+ security.declareProtected(use_vc_permission, 'getVersionOfResource')
+ def getVersionOfResource(self, history_id, selector):
+ history = self.getVersionHistory(history_id)
+ sticky = None
+
+ if not selector or selector == 'mainline':
+ version = history.getLatestVersion('mainline')
+ else:
+ if history.hasVersionId(selector):
+ version = history.getVersionById(selector)
+ sticky = ('V', selector)
+
+ elif self._labels.has_key(selector):
+ version = history.getVersionByLabel(selector)
+ sticky = ('L', selector)
+
+ elif self._branches.has_key(selector):
+ version = history.getLatestVersion(selector)
+ sticky = ('B', selector)
+ else:
+ try: date = DateTime(selector)
+ except:
+ raise VersionControlError(
+ 'Invalid version selector: %s' % selector
+ )
+ else:
+ timestamp = date.timeTime()
+ sticky = ('D', timestamp)
+ version = history.getVersionByDate('mainline', timestamp)
+
+ object = version.copyState()
+
+ info = VersionInfo(history_id, version.getId(), VersionInfo.CHECKED_IN)
+ if sticky is not None:
+ info.sticky = sticky
+ object.__vc_info__ = info
+ return object
+
+ security.declareProtected(use_vc_permission, 'getVersionIds')
+ def getVersionIds(self, object):
+ info = self.getVersionInfo(object)
+ history = self.getVersionHistory(info.history_id)
+ return history.getVersionIds()
+
+ security.declareProtected(use_vc_permission, 'getLabelsForResource')
+ def getLabelsForResource(self, object):
+ info = self.getVersionInfo(object)
+ history = self.getVersionHistory(info.history_id)
+ return history.getLabels()
+
+ security.declareProtected(use_vc_permission, 'getLogEntries')
+ def getLogEntries(self, object):
+ info = self.getVersionInfo(object)
+ history = self.getVersionHistory(info.history_id)
+ return history.getLogEntries()
+
+InitializeClass(Repository)
Property changes on: Products.ZopeVersionControl/tags/0.3.4/Repository.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/SequenceWrapper.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/SequenceWrapper.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/SequenceWrapper.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,39 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+from Globals import InitializeClass, Persistent
+from AccessControl import ClassSecurityInfo
+
+
+class SequenceWrapper:
+ """A helper that manages lazy acquisition wrapping."""
+ def __init__(self, parent, items, pairs=None):
+ if pairs is not None:
+ self.pairs = 1
+ self.parent = parent
+ self.items = items
+
+ pairs = None
+
+ def __getitem__(self, key):
+ item = self.items[key]
+ if self.pairs is not None:
+ return (item[0], item[1].__of__(self.parent))
+ return item.__of__(self.parent)
+
+ def __len__(self):
+ return len(self.items)
+
+ def __nonzero__(self):
+ return len(self.items) > 0
+
Property changes on: Products.ZopeVersionControl/tags/0.3.4/SequenceWrapper.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/Utility.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/Utility.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/Utility.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,159 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+import os
+import time
+
+from AccessControl import ClassSecurityInfo
+from AccessControl import getSecurityManager
+from App.Common import package_home
+from DateTime import DateTime
+from Globals import InitializeClass, Persistent
+from ZODB.TimeStamp import TimeStamp
+
+try:
+ from ZODB.serialize import referencesf
+except ImportError: # < Zope 2.8 / ZODB 3.3
+ from ZODB.referencesf import referencesf
+
+_dtmldir = os.path.join( package_home( globals() ), 'dtml' )
+
+use_vc_permission = 'Use version control'
+
+
+def isAVersionableResource(obj):
+ """ True if an object is versionable.
+
+ To qualify, the object must be persistent (have its own db record), and
+ must not have an true attribute named '__non_versionable__'."""
+
+ if getattr(obj, '__non_versionable__', 0):
+ return 0
+ return hasattr(obj, '_p_oid')
+
+class VersionInfo(Persistent):
+ """A VersionInfo object contains bookkeeping information for version
+ controlled objects. The bookkeeping information can be read (but
+ not changed) by restricted code."""
+
+ __allow_access_to_unprotected_subobjects__ = 1
+
+ def __init__(self, history_id, version_id, status):
+ self.timestamp = time.time()
+ self.history_id = history_id
+ self.version_id = version_id
+ self.status = status
+ self.user_id = _findUserId()
+
+ sticky = None
+
+ CHECKED_OUT = 0
+ CHECKED_IN = 1
+
+ def branchName(self):
+ if self.sticky is not None and self.sticky[0] == 'B':
+ return self.sticky[1]
+ return 'mainline'
+
+ def clone(self, clear_sticky=0):
+ info = VersionInfo(self.history_id, self.version_id, self.status)
+ dict = info.__dict__
+ for name, value in self.__dict__.items():
+ dict[name] = value
+ if clear_sticky:
+ if dict.has_key('sticky'):
+ del dict['sticky']
+ info.user_id = _findUserId()
+ info.timestamp = time.time()
+ return info
+
+InitializeClass(VersionInfo)
+
+
+
+class ReadOnlyJar:
+ """A read-only ZODB connection-like object that prevents changes."""
+
+ def __init__(self, base):
+ self.__base__ = base
+
+ _invalidating = []
+
+ def __getattr__(self, name):
+ return getattr(self.__base__, name)
+
+ def commit(*args, **kw):
+ raise VersionWriteError(
+ 'Old versions of objects cannot be modified.'
+ )
+
+ def abort(*args, **kw):
+ pass
+
+
+
+class VersionControlError(Exception):
+ pass
+
+
+
+def _findUserId():
+ user = getSecurityManager().getUser()
+ return user.getUserName()
+
+def _findPath(object):
+ path = object.getPhysicalPath()
+ return '/'.join(path)
+
+def _findModificationTime(object):
+ """Find the last modification time for a version-controlled object.
+ The modification time reflects the latest modification time of
+ the object or any of its persistent subobjects that are not
+ themselves version-controlled objects. Note that this will
+ return None if the object has no modification time."""
+
+ mtime = getattr(object, '_p_mtime', None)
+ if mtime is None:
+ return None
+
+ latest = mtime
+ conn = object._p_jar
+ load = conn._storage.load
+ version = conn._version
+ refs = referencesf
+
+ oids=[object._p_oid]
+ done_oids={}
+ done=done_oids.has_key
+ first = 1
+
+ while oids:
+ oid=oids[0]
+ del oids[0]
+ if done(oid):
+ continue
+ done_oids[oid]=1
+ try: p, serial = load(oid, version)
+ except: pass # invalid reference!
+ else:
+ if first is not None:
+ first = None
+ else:
+ if p.find('U\x0b__vc_info__') == -1:
+ mtime = TimeStamp(serial).timeTime()
+ if mtime > latest:
+ latest = mtime
+ refs(p, oids)
+
+ return latest
+
Property changes on: Products.ZopeVersionControl/tags/0.3.4/Utility.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/Version.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/Version.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/Version.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,116 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.11 $'[11:-2]
+
+import tempfile
+import time
+from cStringIO import StringIO
+from cPickle import Pickler, Unpickler
+
+from Acquisition import Implicit, aq_parent, aq_inner, aq_base
+from Globals import InitializeClass, Persistent
+from AccessControl import ClassSecurityInfo
+from BTrees.OOBTree import OOBTree
+from OFS.SimpleItem import SimpleItem
+
+from Utility import VersionControlError
+from nonversioned import listNonVersionedObjects, removeNonVersionedData
+
+
+def cloneByPickle(obj, ignore_list=()):
+ """Makes a copy of a ZODB object, loading ghosts as needed.
+
+ Ignores specified objects along the way, replacing them with None
+ in the copy.
+ """
+ ignore_dict = {}
+ for o in ignore_list:
+ ignore_dict[id(o)] = o
+
+ def persistent_id(ob, ignore_dict=ignore_dict):
+ if ignore_dict.has_key(id(ob)):
+ return 'ignored'
+ if getattr(ob, '_p_changed', 0) is None:
+ ob._p_changed = 0
+ return None
+
+ def persistent_load(ref):
+ assert ref == 'ignored'
+ # Return a placeholder object that will be replaced by
+ # removeNonVersionedData().
+ placeholder = SimpleItem()
+ placeholder.id = "ignored_subobject"
+ return placeholder
+
+ stream = StringIO()
+ p = Pickler(stream, 1)
+ p.persistent_id = persistent_id
+ p.dump(obj)
+ stream.seek(0)
+ u = Unpickler(stream)
+ u.persistent_load = persistent_load
+ return u.load()
+
+
+class Version(Implicit, Persistent):
+ """A Version is a resource that contains a copy of a particular state
+ (content and dead properties) of a version-controlled resource. A
+ version is created by checking in a checked-out resource. The state
+ of a version of a version-controlled resource never changes."""
+
+ def __init__(self, version_id, obj):
+ self.id = version_id
+ self.date_created = time.time()
+ self._data = None
+
+ # These attributes are set by the createVersion method of the version
+ # history at the time the version is created. The branch is the name
+ # of the branch on which the version was created. The prev attribute
+ # is the version id of the predecessor to this version. The next attr
+ # is a sequence of version ids of the successors to this version.
+ branch = 'mainline'
+ prev = None
+ next = ()
+
+ security = ClassSecurityInfo()
+
+ security.declarePublic('getId')
+ def getId(self):
+ return self.id
+
+ security.declarePrivate('saveState')
+ def saveState(self, obj):
+ """Save the state of object as the state for this version of
+ a version-controlled resource."""
+ self._data = self.stateCopy(obj, self)
+
+ security.declarePrivate('copyState')
+ def copyState(self):
+ """Return an independent deep copy of the state of the version."""
+ data = self.__dict__.get('_data') # Avoid __of__ hooks
+ return self.stateCopy(data, self)
+
+ security.declarePrivate('stateCopy')
+ def stateCopy(self, obj, container):
+ """Get a deep copy of the state of an object.
+
+ Breaks any database identity references.
+ """
+ ignore = listNonVersionedObjects(obj)
+ res = cloneByPickle(aq_base(obj), ignore)
+ removeNonVersionedData(res)
+ return res
+
+
+InitializeClass(Version)
Property changes on: Products.ZopeVersionControl/tags/0.3.4/Version.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/VersionHistory.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/VersionHistory.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/VersionHistory.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,267 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.4 $'[11:-2]
+
+from Globals import InitializeClass, Persistent
+from AccessControl import ClassSecurityInfo
+from EventLog import EventLog, LogEntry
+from Utility import VersionControlError
+from ZopeVersion import ZopeVersion
+from BTrees.IOBTree import IOBTree
+from BTrees.IIBTree import IIBTree
+from BTrees.OOBTree import OOBTree
+from Acquisition import Implicit
+import sys, time
+
+
+class VersionHistory(Implicit, Persistent):
+ """A version history maintains the information about the changes
+ to a particular version-controlled resource over time."""
+
+ def __init__(self, history_id, object):
+ # The _versions mapping maps version ids to version objects. All
+ # of the actual version data is looked up there. The _labels
+ # mapping maps labels to specific version ids. The _branches map
+ # manages BranchInfo objects that maintain branch information.
+ self._eventLog = EventLog()
+ self._versions = OOBTree()
+ self._branches = OOBTree()
+ self._labels = OOBTree()
+ mainline = self.createBranch('mainline', None)
+ self.id = history_id
+
+ security = ClassSecurityInfo()
+
+ security.declarePublic('getId')
+ def getId(self):
+ return self.id
+
+ security.declarePrivate('addLogEntry')
+ def addLogEntry(self, version_id, action, path=None, message=''):
+ """Add a new log entry associated with this version history."""
+ entry = LogEntry(version_id, action, path, message)
+ self._eventLog.addEntry(entry)
+
+ security.declarePrivate('getLogEntries')
+ def getLogEntries(self):
+ """Return a sequence of the log entries for this version history."""
+ return self._eventLog.getEntries()
+
+ security.declarePrivate('getLabels')
+ def getLabels(self):
+ return self._labels.keys()
+
+ security.declarePrivate('labelVersion')
+ def labelVersion(self, version_id, label, force=0):
+ """Associate a particular version in a version history with the
+ given label, removing any existing association with that label
+ if force is true, or raising an error if force is false and
+ an association with the given label already exists."""
+ current = self._labels.get(label)
+ if current is not None:
+ if current == version_id:
+ return
+ if not force:
+ raise VersionControlError(
+ 'The label %s is already associated with a version.' % (
+ label
+ ))
+ del self._labels[label]
+ self._labels[label] = version_id
+
+ security.declarePrivate('createBranch')
+ def createBranch(self, branch_id, version_id):
+ """Create a new branch associated with the given branch_id. The
+ new branch is rooted at the version named by version_id."""
+ if self._branches.has_key(branch_id):
+ raise VersionControlError(
+ 'Activity already exists: %s' % branch_id
+ )
+ branch = BranchInfo(branch_id, version_id)
+ self._branches[branch_id] = branch
+ return branch
+
+ security.declarePrivate('createVersion')
+ def createVersion(self, object, branch_id):
+ """Create a new version in the line of descent named by the given
+ branch_id, returning the newly created version object."""
+ branch = self._branches.get(branch_id)
+ if branch is None:
+ branch = self.createBranch(branch_id, None)
+ if branch.name != 'mainline':
+ version_id = '%s.%d' % (branch.name, len(branch) + 1)
+ else:
+ version_id = '%d' % (len(branch) + 1)
+ version = ZopeVersion(version_id, object)
+
+ # Update the predecessor, successor and branch relationships.
+ # This is something of a hedge against the future. Versions will
+ # always know enough to reconstruct their lineage without the help
+ # of optimized data structures, which will make it easier to change
+ # internals in the future if we need to.
+ latest = branch.latest()
+ if latest is not None:
+ last = self._versions[latest]
+ last.next = last.next + (version_id,)
+ version.prev = latest
+
+ # If the branch is not the mainline, store the branch name in the
+ # version. Versions have 'mainline' as the default class attribute
+ # which is the common case and saves a minor bit of storage space.
+ if branch.name != 'mainline':
+ version.branch = branch.name
+
+ branch.append(version)
+ self._versions[version_id] = version
+ # Call saveState() only after version has been linked into the
+ # database, ensuring it goes into the correct database.
+ version.saveState(object)
+ return version.__of__(self)
+
+ security.declarePrivate('hasVersionId')
+ def hasVersionId(self, version_id):
+ """Return true if history contains a version with the given id."""
+ return self._versions.has_key(version_id)
+
+ security.declarePrivate('isLatestVersion')
+ def isLatestVersion(self, version_id, branch_id):
+ """Return true if version id is the latest in its branch."""
+ branch = self._branches[branch_id]
+ return version_id == branch.latest()
+
+ security.declarePrivate('getLatestVersion')
+ def getLatestVersion(self, branch_id):
+ """Return the latest version object within the given branch, or
+ None if the branch contains no versions."""
+ branch = self._branches[branch_id]
+ version = self._versions[branch.latest()]
+ return version.__of__(self)
+
+ security.declarePrivate('findBranchId')
+ def findBranchId(self, version_id):
+ """Given a version id, return the id of the branch of the version.
+ Note that we cheat, since we can find this out from the id."""
+ parts = version_id.split('.')
+ if len(parts) > 1:
+ return parts[-2]
+ return 'mainline'
+
+ security.declarePrivate('getVersionById')
+ def getVersionById(self, version_id):
+ """Return the version object named by the given version id, or
+ raise a VersionControlError if the version is not found."""
+ version = self._versions.get(version_id)
+ if version is None:
+ raise VersionControlError(
+ 'Unknown version id: %s' % version_id
+ )
+ return version.__of__(self)
+
+ security.declarePrivate('getVersionByLabel')
+ def getVersionByLabel(self, label):
+ """Return the version associated with the given label, or None
+ if no version matches the given label."""
+ version_id = self._labels.get(label)
+ version = self._versions.get(version_id)
+ if version is None:
+ return None
+ return version.__of__(self)
+
+ security.declarePrivate('getVersionByDate')
+ def getVersionByDate(self, branch_id, timestamp):
+ """Return the last version committed in the given branch on or
+ before the given time value. The timestamp should be a float
+ (time.time format) value in UTC."""
+ branch = self._branches[branch_id]
+ tvalue = int(timestamp / 60.0)
+ while 1:
+ # Try to find a version with a commit date <= the given time
+ # using the timestamp index in the branch information.
+ if branch.m_order:
+ try:
+ match = branch.m_date.maxKey(tvalue)
+ match = branch.m_order[branch.m_date[match]]
+ return self._versions[match].__of__(self)
+ except ValueError:
+ pass
+
+ # If we've run out of lineage without finding a version with
+ # a commit date <= the given timestamp, we return None. It is
+ # up to the caller to decide what to do in this situation.
+ if branch.root is None:
+ return None
+
+ # If the branch has a root (a version in another branch), then
+ # we check the root and do it again with the ancestor branch.
+ rootver = self._versions[branch.root]
+ if int(rootver.date_created / 60.0) < tvalue:
+ return rootver.__of__(self)
+ branch = self._branches[rootver.branch]
+
+ security.declarePrivate('getVersionIds')
+ def getVersionIds(self, branch_id=None):
+ """Return a sequence of version ids for the versions in this
+ version history. If a branch_id is given, only version ids
+ from that branch will be returned. Note that the sequence
+ of ids returned does not include the id of the branch root."""
+ if branch_id is not None:
+ return self._branches[branch_id].versionIds()
+ return self._versions.keys()
+
+InitializeClass(VersionHistory)
+
+
+class BranchInfo(Implicit, Persistent):
+ """A utility class to hold branch (line-of-descent) information. It
+ maintains the name of the branch, the version id of the root of
+ the branch and indices to allow for efficient lookups."""
+
+ def __init__(self, name, root):
+ # m_order maintains a newest-first mapping of int -> version id.
+ # m_date maintains a mapping of a packed date (int # of minutes
+ # since the epoch) to a lookup key in m_order. The two structures
+ # are separate because we only support minute precision for date
+ # lookups (and multiple versions could be added in a minute).
+ self.date_created = time.time()
+ self.m_order = IOBTree()
+ self.m_date = IIBTree()
+ self.name = name
+ self.root = root
+
+ def append(self, version):
+ """Append a version to the branch information. Note that this
+ does not store the actual version, but metadata about the
+ version to support ordering and date lookups."""
+ if len(self.m_order):
+ key = self.m_order.minKey() - 1
+ else: key = sys.maxint
+ self.m_order[key] = version.id
+ timestamp = int(version.date_created / 60.0)
+ self.m_date[timestamp] = key
+
+ def versionIds(self):
+ """Return a newest-first sequence of version ids in the branch."""
+ return self.m_order.values()
+
+ def latest(self):
+ """Return the version id of the latest version in the branch."""
+ mapping = self.m_order
+ if not len(mapping):
+ return self.root
+ return mapping[mapping.keys()[0]]
+
+ def __len__(self):
+ return len(self.m_order)
+
+InitializeClass(BranchInfo)
Property changes on: Products.ZopeVersionControl/tags/0.3.4/VersionHistory.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/VersionSupport.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/VersionSupport.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/VersionSupport.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,179 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.4 $'[11:-2]
+
+import ExtensionClass, AccessControl, Acquisition
+from Globals import DTMLFile, InitializeClass
+from Utility import VersionControlError, isAVersionableResource
+from Utility import use_vc_permission
+
+
+class VersionSupport(ExtensionClass.Base):
+ """Mixin class to support version-controllable resources."""
+
+ manage_options=(
+ {'label': 'Version Control', 'action':'versionControlMain',
+ 'help': ('ZopeVersionControl', 'VersionControl.stx'),
+ 'filter': isAVersionableResource,
+ },
+ )
+
+ security = AccessControl.ClassSecurityInfo()
+
+ security.declareProtected('View management screens', 'versionControlMain')
+ versionControlMain = DTMLFile('dtml/VersionControlMain', globals())
+
+ security.declareProtected('View management screens', 'versionControlLog')
+ versionControlLog = DTMLFile('dtml/VersionControlLog', globals())
+
+ security.declarePrivate('haveRepository')
+ def haveRepository(self):
+ try: result = self.getRepository()
+ except VersionControlError:
+ return 0
+ return 1
+
+ security.declarePrivate('getRepository')
+ def getRepository(self):
+ # We currently only allow a single repository in a given context.
+ if hasattr(self, '_v_repository'):
+ return self._v_repository
+ try: items = self.superValues('Repository')
+ except: items = self.aq_inner.aq_parent.superValues('Repository')
+ result = items and items[0] or None
+ if result is None:
+ raise VersionControlError(
+ 'No versioning repository was found.'
+ )
+ self._v_repository = result
+ return result
+
+
+ security.declarePublic('isAVersionableResource')
+ def isAVersionableResource(self, object):
+ return self.getRepository().isAVersionableResource(self)
+
+ security.declarePublic('isUnderVersionControl')
+ def isUnderVersionControl(self):
+ return hasattr(self, '__vc_info__')
+
+ security.declarePublic('isResourceUpToDate')
+ def isResourceUpToDate(self):
+ return self.getRepository().isResourceUpToDate(self)
+
+ security.declarePublic('isResourceChanged')
+ def isResourceChanged(self):
+ return self.getRepository().isResourceChanged(self)
+
+ security.declarePublic('getVersionInfo')
+ def getVersionInfo(self):
+ return self.getRepository().getVersionInfo(self)
+
+ security.declareProtected(use_vc_permission, 'applyVersionControl')
+ def applyVersionControl(self, REQUEST=None):
+ """Place a resource under version control."""
+ repository = self.getRepository()
+ object = repository.applyVersionControl(self)
+ if REQUEST is not None:
+ message="The resource has been placed under version control."
+ return object.versionControlMain(
+ object, REQUEST,
+ manage_tabs_message=message
+ )
+
+ security.declareProtected(use_vc_permission, 'checkoutResource')
+ def checkoutResource(self, REQUEST=None):
+ """Checkout a version-controlled resource."""
+ repository = self.getRepository()
+ object = repository.checkoutResource(self)
+ if REQUEST is not None:
+ message="The resource has been checked out."
+ return object.versionControlMain(
+ object, REQUEST,
+ manage_tabs_message=message
+ )
+
+ security.declareProtected(use_vc_permission, 'checkinResource')
+ def checkinResource(self, message='', REQUEST=None):
+ """Checkout a version-controlled resource."""
+ repository = self.getRepository()
+ object = repository.checkinResource(self, message)
+ version = object.getVersionInfo().version_id
+ if REQUEST is not None:
+ message="The resource has been checked in [version %s]." % version
+ return object.versionControlMain(
+ object, REQUEST,
+ manage_tabs_message=message
+ )
+
+ security.declareProtected(use_vc_permission, 'uncheckoutResource')
+ def uncheckoutResource(self, REQUEST=None):
+ """Uncheckout a version-controlled resource."""
+ repository = self.getRepository()
+ object = repository.uncheckoutResource(self)
+ version = object.getVersionInfo().version_id
+ if REQUEST is not None:
+ message="The resource has been reverted to version %s." % version
+ return object.versionControlMain(
+ object, REQUEST,
+ manage_tabs_message=message
+ )
+
+ security.declareProtected(use_vc_permission, 'updateResource')
+ def updateResource(self, selector, REQUEST=None):
+ """Update a version-controlled resource."""
+ repository = self.getRepository()
+ if selector == 'LATEST_VERSION':
+ selector = None
+ object = repository.updateResource(self, selector)
+ version = object.getVersionInfo().version_id
+ if REQUEST is not None:
+ message="The resource has been updated to version %s." % version
+ return object.versionControlMain(
+ object, REQUEST,
+ manage_tabs_message=message
+ )
+
+ security.declareProtected(use_vc_permission, 'labelResource')
+ def labelResource(self, label, force=0, REQUEST=None):
+ """Label a version-controlled resource."""
+ repository = self.getRepository()
+ object = repository.labelResource(self, label, force)
+ if REQUEST is not None:
+ message="The label has been applied to this resource."
+ return object.versionControlMain(
+ object, REQUEST,
+ manage_tabs_message=message
+ )
+
+ security.declareProtected(use_vc_permission, 'getVersionIds')
+ def getVersionIds(self):
+ return self.getRepository().getVersionIds(self)
+
+ security.declareProtected(use_vc_permission, 'getLabelsForHistory')
+ def getLabelsForHistory(self):
+ return self.getRepository().getLabelsForHistory(self)
+
+ security.declareProtected(use_vc_permission, 'getLabelsForVersion')
+ def getLabelsForVersion(self):
+ return self.getRepository().getLabelsForVersion(self)
+
+ security.declareProtected(use_vc_permission, 'getLogEntries')
+ def getLogEntries(self):
+ return self.getRepository().getLogEntries(self)
+
+
+InitializeClass(VersionSupport)
+
+
Property changes on: Products.ZopeVersionControl/tags/0.3.4/VersionSupport.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/ZopeRepository.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/ZopeRepository.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/ZopeRepository.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,110 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.5 $'[11:-2]
+
+from Globals import DTMLFile, InitializeClass
+from SequenceWrapper import SequenceWrapper
+import OFS, AccessControl
+import Repository
+
+
+class ZopeRepository(
+ Repository.Repository,
+ AccessControl.Role.RoleManager,
+ OFS.SimpleItem.Item,
+ ):
+ """The ZopeRepository class builds on the core Repository implementation
+ to provide the Zope management interface and other product trappings."""
+
+ security = AccessControl.ClassSecurityInfo()
+
+ meta_type = 'Repository'
+
+ manage_options=(
+ ( {'label': 'Contents', 'action':'manage_main',
+ 'help': ('ZopeVersionControl', 'Repository-Manage.stx')},
+ {'label': 'Properties', 'action':'manage_properties_form',
+ 'help': ('ZopeVersionControl', 'Repository-Properties.stx')},
+ ) +
+ AccessControl.Role.RoleManager.manage_options +
+ OFS.SimpleItem.Item.manage_options
+ )
+
+ security.declareProtected('View management screens', 'manage_main')
+ manage_main = DTMLFile('dtml/RepositoryManageMain', globals())
+ manage_main._setName('manage_main')
+ manage = manage_main
+
+ def __init__(self, id=None, title=''):
+ Repository.Repository.__init__(self)
+ if id is not None:
+ self._setId( id )
+ self.title = title
+
+ security.declareProtected(
+ 'View management screens','manage_properties_form'
+ )
+ manage_properties_form = DTMLFile('dtml/RepositoryProperties', globals())
+
+ security.declareProtected('Manage repositories', 'manage_edit')
+ def manage_edit(self, title='', REQUEST=None):
+ """Change object properties."""
+ self.title = title
+ if REQUEST is not None:
+ message="Saved changes."
+ return self.manage_properties_form(
+ self, REQUEST, manage_tabs_message=message
+ )
+
+ def __getitem__(self, name):
+ history = self._histories.get(name)
+ if history is not None:
+ return history.__of__(self)
+ raise KeyError, name
+
+ security.declarePrivate('objectIds')
+ def objectIds(self, spec=None):
+ return SequenceWrapper(self, self._histories.keys())
+
+ security.declarePrivate('objectValues')
+ def objectValues(self, spec=None):
+ return SequenceWrapper(self, self._histories.values())
+
+ security.declarePrivate('objectItems')
+ def objectItems(self, spec=None):
+ return SequenceWrapper(self, self._histories.items(), 1)
+
+InitializeClass(ZopeRepository)
+
+
+
+def addRepository(self, id, title='', REQUEST=None):
+ """Zope object constructor function."""
+ object = ZopeRepository(title=title)
+ object._setId( id )
+ self._setObject(id, object)
+ object = self._getOb(id)
+ if REQUEST is not None:
+ try: url = self.DestinationURL()
+ except: url = REQUEST['URL1']
+ REQUEST.RESPONSE.redirect('%s/manage_main' % url)
+ return
+
+addRepositoryForm = DTMLFile('dtml/RepositoryAddForm', globals())
+
+
+constructors = (
+ ('addRepositoryForm', addRepositoryForm),
+ ('addRepository', addRepository),
+)
Property changes on: Products.ZopeVersionControl/tags/0.3.4/ZopeRepository.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/ZopeVersion.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/ZopeVersion.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/ZopeVersion.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,66 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.6 $'[11:-2]
+
+from Globals import DTMLFile, InitializeClass
+import OFS, AccessControl
+import Version
+
+
+class ZopeVersion(
+ Version.Version,
+ AccessControl.Role.RoleManager,
+ OFS.SimpleItem.Item
+ ):
+ """The ZopeVersion class builds on the core Version class to provide
+ the Zope management interface and other product trappings."""
+
+ security = AccessControl.ClassSecurityInfo()
+ security.setDefaultAccess('deny')
+
+ meta_type = 'Version'
+
+ manage_options=(
+ ( {'label': 'Information', 'action':'manage_main',
+ 'help': ('ZopeVersionControl', 'Version-Manage.stx')},
+ {'label': 'Properties', 'action':'manage_properties_form',
+ 'help': ('ZopeVersionControl', 'Version-Properties.stx')},
+ ) +
+ AccessControl.Role.RoleManager.manage_options +
+ OFS.SimpleItem.Item.manage_options
+ )
+
+ icon='misc_/ZopeVersionControl/Version.gif'
+
+ security.declareProtected('View management screens', 'manage_main')
+ manage_main = DTMLFile('dtml/VersionManageMain', globals())
+ manage_main._setName('manage_main')
+ manage = manage_main
+
+ security.declareProtected(
+ 'View management screens', 'manage_properties_form'
+ )
+ manage_properties_form = DTMLFile('dtml/VersionProperties', globals())
+
+ security.declareProtected('Manage repositories', 'manage_edit')
+ def manage_edit(self, REQUEST=None):
+ """Change object properties."""
+ if REQUEST is not None:
+ message="Saved changes."
+ return self.manage_properties_form(
+ self, REQUEST, manage_tabs_message=message
+
+ )
+
+InitializeClass(ZopeVersion)
Property changes on: Products.ZopeVersionControl/tags/0.3.4/ZopeVersion.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/ZopeVersionHistory.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/ZopeVersionHistory.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/ZopeVersionHistory.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,86 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.2 $'[11:-2]
+
+from Globals import DTMLFile, InitializeClass
+import OFS, AccessControl, Acquisition
+import VersionHistory
+
+class ZopeVersionHistory(
+ VersionHistory.VersionHistory,
+ AccessControl.Role.RoleManager,
+ OFS.SimpleItem.Item,
+ ):
+ """The ZopeVersionHistory build on the core VersionHistory class to
+ provide the Zope management interface and other product trappings."""
+
+ security = AccessControl.ClassSecurityInfo()
+ security.setDefaultAccess('deny')
+
+ meta_type = 'Version History'
+
+ manage_options=(
+ ( {'label': 'Contents', 'action':'manage_main',
+ 'help': ('ZopeVersionControl', 'VersionHistory-Manage.stx')},
+ {'label': 'Properties', 'action':'manage_properties_form',
+ 'help': ('ZopeVersionControl', 'VersionHistory-Properties.stx')},
+ ) +
+ AccessControl.Role.RoleManager.manage_options +
+ OFS.SimpleItem.Item.manage_options
+ )
+
+ icon='misc_/ZopeVersionControl/VersionHistory.gif'
+
+ security.declareProtected('View management screens', 'manage_main')
+ manage_main = DTMLFile('dtml/VersionHistoryManageMain', globals())
+ manage_main._setName('manage_main')
+ manage = manage_main
+
+ security.declareProtected(
+ 'View management screens', 'manage_properties_form'
+ )
+ manage_properties_form = DTMLFile(
+ 'dtml/VersionHistoryProperties', globals()
+ )
+
+ security.declareProtected('Manage repositories', 'manage_edit')
+ def manage_edit(self, REQUEST=None):
+ """Change object properties."""
+ if REQUEST is not None:
+ message="Saved changes."
+ return self.manage_properties_form(
+ self, REQUEST, manage_tabs_message=message
+ )
+
+ def __getitem__(self, name):
+ activity = self._branches.get(name)
+ if activity is not None:
+ return activity.__of__(self)
+ raise KeyError, name
+
+ security.declarePrivate('objectIds')
+ def objectIds(self, spec=None):
+ return self._branches.keys()
+
+ security.declarePrivate('objectValues')
+ def objectValues(self, spec=None):
+ return self._branches.values()
+
+ security.declarePrivate('objectItems')
+ def objectItems(self, spec=None):
+ return self._branches.items()
+
+InitializeClass(ZopeVersionHistory)
+
+
Property changes on: Products.ZopeVersionControl/tags/0.3.4/ZopeVersionHistory.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/__init__.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/__init__.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/__init__.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,70 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.4 $'[11:-2]
+
+import ZopeRepository, OFS, App, Globals
+
+
+def initialize(context):
+
+ context.registerClass(
+ instance_class = ZopeRepository.ZopeRepository,
+ meta_type = 'Repository',
+ permission = 'Add Repositories',
+ constructors = ZopeRepository.constructors,
+ icon = 'www/Repository.gif'
+ )
+
+ context.registerHelp()
+ context.registerHelpTitle('Zope Help')
+
+ registerIcon('VersionHistory.gif')
+ registerIcon('Version.gif')
+
+
+def install_hack():
+ # Hackery - don't try this at home, kids. :) This is temporary for
+ # testing purposes only.
+ from VersionSupport import VersionSupport
+ import OFS.SimpleItem, App.Management
+
+ method = App.Management.Tabs.filtered_manage_options
+ def filtered_manage_options(self, REQUEST=None, method = method,
+ options = VersionSupport.manage_options):
+ result = method(self, REQUEST)
+ for item in result:
+ if item.get('label') == 'Version Control':
+ return result
+ for option in options:
+ result.append(option)
+ return result
+ App.Management.Tabs.filtered_manage_options = filtered_manage_options
+
+ for _class in (OFS.SimpleItem.Item, OFS.SimpleItem.Item_w__name__):
+ dict = _class.__dict__
+ if not hasattr(dict, '__setitem__'):
+ # new-style classes don't need this [>=2.8]
+ continue
+
+ for name, value in VersionSupport.__dict__.items():
+ if name != 'manage_options':
+ dict[name] = value
+
+ Globals.InitializeClass(_class)
+
+
+def registerIcon(filename):
+ setattr(OFS.misc_.misc_.ZopeVersionControl, filename,
+ App.ImageFile.ImageFile('www/%s' % filename, globals())
+ )
Property changes on: Products.ZopeVersionControl/tags/0.3.4/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryAddForm.dtml
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryAddForm.dtml 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryAddForm.dtml 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,48 @@
+<dtml-var manage_page_header>
+
+<dtml-var "manage_form_title(this(), _,
+ form_title='Add Repository',
+ help_product='Versioning',
+ help_topic='Repository-Add.stx'
+ )">
+
+<p class="form-help">
+A versioning repository provides a way to version resources.
+</p>
+
+<form action="addRepository" method="POST">
+<table cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-label">
+ Id
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <input type="text" name="id" size="40" />
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-optional">
+ Title
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <input type="text" name="title" size="40" />
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit" name="submit"
+ value=" Add " />
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<dtml-var manage_page_footer>
Property changes on: Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryAddForm.dtml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryManageMain.dtml
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryManageMain.dtml 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryManageMain.dtml 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,152 @@
+<dtml-var manage_page_header>
+<dtml-with "_(management_view='Contents')">
+<dtml-var manage_tabs>
+</dtml-with>
+
+<script type="text/javascript">
+<!--
+
+isSelected = false;
+
+function toggleSelect() {
+ if (isSelected == false) {
+ for (i = 0; i < document.objectItems.length; i++)
+ document.objectItems.elements[i].checked = true ;
+ isSelected = true;
+ document.objectItems.selectButton.value = "Deselect All";
+ return isSelected;
+ }
+ else {
+ for (i = 0; i < document.objectItems.length; i++)
+ document.objectItems.elements[i].checked = false ;
+ isSelected = false;
+ document.objectItems.selectButton.value = "Select All";
+ return isSelected;
+ }
+}
+
+//-->
+</script>
+
+<dtml-unless skey><dtml-call expr="REQUEST.set('skey', 'id')"></dtml-unless>
+<dtml-unless rkey><dtml-call expr="REQUEST.set('rkey', '')"></dtml-unless>
+<dtml-let object="this()">
+
+<p class="form-text">
+A repository contains version histories for objects under version control.
+</p>
+
+<form action="&dtml-URL1;/" name="objectItems" method="POST">
+<dtml-in objectValues size=20 start=query_start>
+
+<dtml-if sequence-start>
+<dtml-if "_.getitem('sequence-length') > _.getitem('sequence-step-size')">
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-text">
+ Items <dtml-var sequence-step-start-number> - <dtml-var
+ sequence-step-end-number> of <dtml-var sequence-length> in
+ <em><dtml-var "object.getId()"></em>
+ </div>
+ </td>
+ <td align="right" valign="top" nowrap>
+ <div class="form-text">
+<dtml-if previous-sequence-size>
+ << <strong><a href="<dtml-var URL><dtml-var sequence-query
+ >query_start=<dtml-var previous-sequence-start-number>">Prev <dtml-var
+ previous-sequence-size></a></strong>
+</dtml-if>
+<dtml-if next-sequence-size>
+ <strong><a href="<dtml-var URL><dtml-var
+ sequence-query>query_start=<dtml-var
+ next-sequence-start-number>">Next <dtml-var
+ next-sequence-size></a></strong> >></a>
+</dtml-if>
+ </div>
+ </td>
+ </tr>
+</table>
+</dtml-if>
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+<tr class="list-header">
+ <td width="5%" align="left" colspan="2">
+ <div class="list-item">
+
+ </div>
+ </td>
+ <td align="left">
+ <div class="list-item">
+ <strong>Version Histories</strong>
+ </div>
+ </td>
+</tr>
+</dtml-if>
+
+<dtml-with sequence-item>
+<dtml-if sequence-odd>
+<tr class="row-normal">
+<dtml-else>
+<tr class="row-hilite">
+</dtml-if>
+ <td align="left" valign="top" width="16">
+ <input type="checkbox" name="ids:list" value="&dtml-getId;"/>
+ </td>
+ <td align="left" valign="top">
+ <a href="&dtml.url_quote-getId;/manage_workspace">
+ <img src="&dtml-BASEPATH1;/&dtml-icon;" alt="&dtml-meta_type;"
+ title="&dtml-meta_type;" border="0" /></a>
+ </td>
+ <td align="left" valign="top">
+ <div class="list-item">
+ <a href="&dtml.url_quote-getId;/manage_workspace">
+ &dtml-getId;
+ </a>
+ </div>
+ </td>
+</tr>
+</dtml-with>
+
+<dtml-if sequence-end>
+</table>
+<dtml-if "_.getitem('sequence-length') > _.getitem('sequence-step-size')">
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="right" valign="top">
+ <div class="form-text">
+<dtml-if previous-sequence-size>
+ << <strong><a href="<dtml-var URL><dtml-var sequence-query
+ >query_start=<dtml-var previous-sequence-start-number>">Prev <dtml-var
+ previous-sequence-size></a></strong>
+</dtml-if>
+<dtml-if next-sequence-size>
+ <strong><a href="<dtml-var URL><dtml-var
+ sequence-query>query_start=<dtml-var
+ next-sequence-start-number>">Next <dtml-var
+ next-sequence-size></a></strong> >></a>
+</dtml-if>
+ </div>
+ </td>
+ </tr>
+</table>
+</dtml-if>
+</dtml-if>
+
+<dtml-else>
+<table cellspacing="0" cellpadding="2" border="0">
+<tr>
+<td>
+<div class="std-text">
+This repository is currently empty.
+<br /><br />
+</div>
+</td>
+</tr>
+</table>
+
+</dtml-in>
+
+</form>
+
+</dtml-let>
+<dtml-var manage_page_footer>
Property changes on: Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryManageMain.dtml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryProperties.dtml
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryProperties.dtml 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryProperties.dtml 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,33 @@
+<dtml-var manage_page_header>
+<dtml-with "_(management_view='Properties')">
+<dtml-var manage_tabs>
+</dtml-with>
+
+<form action="manage_edit" method="post">
+<table cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-optional">
+ Title
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <input type="text" name="title" size="50"
+ value="<dtml-if title><dtml-var title html_quote></dtml-if>"/>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit" name="submit"
+ value="Save Changes" />
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<dtml-var manage_page_footer>
Property changes on: Products.ZopeVersionControl/tags/0.3.4/dtml/RepositoryProperties.dtml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlLog.dtml
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlLog.dtml 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlLog.dtml 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,88 @@
+<dtml-var manage_page_header>
+<dtml-with "_(management_view='Version Control')">
+<dtml-var manage_tabs>
+</dtml-with>
+
+<dtml-if haveRepository>
+
+<p class="form-text">
+This is a log of the version control actions performed on this resource.
+</p>
+
+<form action="&dtml-URL1;/" method="POST">
+<dtml-in getLogEntries size=20 start=query_start>
+
+<dtml-if sequence-start>
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+ <tr class="list-header">
+ <td align="left" valign="top">
+ <div class="list-nav">
+<dtml-if previous-sequence-size>
+ <a href="<dtml-var URL><dtml-var sequence-query
+ >query_start=<dtml-var
+ previous-sequence-start-number>"
+ onMouseOver="window.status='View later entries'; return true"
+ onMouseOut="window.status=''; return true">< Later entries</a>
+ </a>
+<dtml-else>
+
+</dtml-if>
+ </div>
+ </td>
+ <td align="right" valign="top" nowrap>
+ <div class="list-nav">
+<dtml-if next-sequence-size>
+ <a href="<dtml-var URL><dtml-var sequence-query
+ >query_start=<dtml-var
+ next-sequence-start-number>"
+ onMouseOver="window.status='View earlier entries'; return true"
+ onMouseOut="window.status=''; return true">Earlier entries ></a>
+ </a>
+<dtml-else>
+
+</dtml-if>
+ </div>
+ </td>
+ </tr>
+</table>
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+</dtml-if>
+
+<dtml-with sequence-item>
+<dtml-if sequence-odd>
+<tr class="row-normal">
+<dtml-else>
+<tr class="row-hilite">
+</dtml-if>
+ <td align="left" valign="top" width="16">
+
+ </td>
+ <td align="left" valign="top">
+ <div class="list-item">
+ <dtml-var "ZopeTime(timestamp)" fmt="%Y-%m-%d %H:%M:%S">
+ [<strong><dtml-var user_id></strong>]
+ <strong><dtml-var "{0: 'checkout',
+ 1: 'checkin',
+ 2: 'uncheckout',
+ 3: 'update'}.get(action)"></strong>
+ rev &dtml-version_id; at &dtml-path;
+ <p class="form-text">
+ <em><dtml-if message>&dtml-message;</dtml-if></em>
+ </p>
+ </div>
+ </td>
+</tr>
+</dtml-with>
+</dtml-in>
+
+</table>
+</form>
+
+<dtml-else>
+<p class="form-text">
+No version repository was found in the acquisition path of this
+resource. To use version control, create a repository object.
+</p>
+</dtml-if>
+
+<dtml-var manage_page_footer>
Property changes on: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlLog.dtml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlMain.dtml
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlMain.dtml 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlMain.dtml 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,233 @@
+<dtml-var manage_page_header>
+<dtml-with "_(management_view='Version Control')">
+<dtml-var manage_tabs>
+</dtml-with>
+
+<dtml-if haveRepository>
+
+<dtml-if isUnderVersionControl>
+<!-- object is under version control -->
+
+<p class="form-text">
+This object is under version control. Use the form below to perform
+versioning related operations on the object. You may also view the
+<a href="./versionControlLog">activity log</a> for this versioned resource.
+</p>
+
+<dtml-let info=getVersionInfo>
+
+<form action="&dtml-URL1;" method="post">
+<table cellspacing="0" cellpadding="2" border="0">
+
+<dtml-if "info.status == info.CHECKED_IN">
+ <tr>
+ <td align="left" valign="top" nowrap>
+ <div class="form-label">
+ Current Status
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="form-text">
+ <font color="red">
+ checked in <dtml-if isResourceUpToDate>(up to date)<dtml-else
+ >(not up to date)</dtml-if>
+ </font>
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-label">
+ Version Number
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="form-text">
+ <dtml-var "info.version_id">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit"
+ name="checkoutResource:method"
+ value="Checkout" />
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" valign="top" nowrap>
+ <div class="form-label">
+ <br>
+ Update To...
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <br>
+ <select name="selector">
+ <option value="LATEST_VERSION"> latest version</option>
+ <dtml-in getVersionIds>
+ <option value="<dtml-var sequence-item html_quote>"><dtml-var
+ sequence-item>
+ </dtml-in>
+ </select>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit"
+ name="updateResource:method"
+ value="Update" />
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" valign="top" nowrap>
+ <div class="form-label">
+ <br>
+ Label Version...
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <br>
+ <input class="form-element" type="text"
+ name="label" size="20"/>
+ <input type="hidden" name="force:int" value="1">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit"
+ name="labelResource:method"
+ value="Label" />
+ </div>
+ </td>
+ </tr>
+
+</dtml-if>
+
+<dtml-if "info.status == info.CHECKED_OUT">
+ <tr>
+ <td align="left" valign="top" nowrap>
+ <div class="form-label">
+ Current Status
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="form-text">
+ checked out <dtml-if isResourceChanged>(modified)<dtml-else
+ >(not modified)</dtml-if>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-label">
+ From Version
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <div class="form-text">
+ <dtml-var "info.version_id">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-label">
+ Message
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <textarea name="message" rows="4" cols="40"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit"
+ name="checkinResource:method"
+ value="Checkin" />
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-text">
+ <br>
+ To discard changes to this object and revert to the version that
+ was originally checked out, click the <em>UnCheckout</em> button.
+ </div>
+
+ <div class="form-element">
+ <input class="form-element" type="submit"
+ name="uncheckoutResource:method"
+ value="UnCheckout" />
+ </div>
+ </td>
+ </tr>
+
+
+</dtml-if>
+
+
+
+</table>
+</form>
+</dtml-let>
+
+<dtml-else>
+<!-- The object is not under version control -->
+
+<p class="form-text">
+This object is <strong>not</strong> under version control. To place
+this object under version control, click the "Apply version
+control" button below.
+</p>
+
+<form action="applyVersionControl" method="POST">
+<table cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit" name="submit"
+ value="Apply version control" />
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+</dtml-if>
+
+<dtml-else>
+<p class="form-text">
+No version repository was found in the acquisition path of this
+resource. To use version control, create a repository object.
+</p>
+</dtml-if>
+
+<dtml-var manage_page_footer>
Property changes on: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionControlMain.dtml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryManageMain.dtml
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryManageMain.dtml 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryManageMain.dtml 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,152 @@
+<dtml-var manage_page_header>
+<dtml-with "_(management_view='Contents')">
+<dtml-var manage_tabs>
+</dtml-with>
+
+<script type="text/javascript">
+<!--
+
+isSelected = false;
+
+function toggleSelect() {
+ if (isSelected == false) {
+ for (i = 0; i < document.objectItems.length; i++)
+ document.objectItems.elements[i].checked = true ;
+ isSelected = true;
+ document.objectItems.selectButton.value = "Deselect All";
+ return isSelected;
+ }
+ else {
+ for (i = 0; i < document.objectItems.length; i++)
+ document.objectItems.elements[i].checked = false ;
+ isSelected = false;
+ document.objectItems.selectButton.value = "Select All";
+ return isSelected;
+ }
+}
+
+//-->
+</script>
+
+<dtml-unless skey><dtml-call expr="REQUEST.set('skey', 'id')"></dtml-unless>
+<dtml-unless rkey><dtml-call expr="REQUEST.set('rkey', '')"></dtml-unless>
+<dtml-let object="this()">
+
+<p class="form-text">
+A version history contains all the versions of a particular version
+controlled resource.
+</p>
+
+<form action="&dtml-URL1;/" name="objectItems" method="POST">
+<dtml-in objectValues size=20 start=query_start>
+<dtml-if sequence-start>
+<dtml-if "_.getitem('sequence-length') > _.getitem('sequence-step-size')">
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-text">
+ Items <dtml-var sequence-step-start-number> - <dtml-var
+ sequence-step-end-number> of <dtml-var sequence-length> in
+ <em><dtml-var "object.getId()"></em>
+ </div>
+ </td>
+ <td align="right" valign="top" nowrap>
+ <div class="form-text">
+<dtml-if previous-sequence-size>
+ << <strong><a href="<dtml-var URL><dtml-var sequence-query
+ >query_start=<dtml-var previous-sequence-start-number>">Prev <dtml-var
+ previous-sequence-size></a></strong>
+</dtml-if>
+<dtml-if next-sequence-size>
+ <strong><a href="<dtml-var URL><dtml-var
+ sequence-query>query_start=<dtml-var
+ next-sequence-start-number>">Next <dtml-var
+ next-sequence-size></a></strong> >></a>
+</dtml-if>
+ </div>
+ </td>
+ </tr>
+</table>
+</dtml-if>
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+<tr class="list-header">
+ <td width="5%" align="left" colspan="2">
+ <div class="list-item">
+
+ </div>
+ </td>
+ <td align="left">
+ <div class="list-item">
+ <strong>Versions</strong>
+ </div>
+ </td>
+</tr>
+</dtml-if>
+
+<dtml-with sequence-item>
+<dtml-if sequence-odd>
+<tr class="row-normal">
+<dtml-else>
+<tr class="row-hilite">
+</dtml-if>
+ <td align="left" valign="top" width="16">
+ <input type="checkbox" name="ids:list" value="&dtml-getId;"/>
+ </td>
+ <td align="left" valign="top">
+ <a href="&dtml.url_quote-getId;/manage_workspace">
+ <img src="&dtml-BASEPATH1;/&dtml-icon;" alt="&dtml-meta_type;"
+ title="&dtml-meta_type;" border="0" /></a>
+ </td>
+ <td align="left" valign="top">
+ <div class="list-item">
+ <a href="&dtml.url_quote-getId;/manage_workspace">
+ &dtml-getId;
+ </a>
+ </div>
+ </td>
+</tr>
+</dtml-with>
+
+<dtml-if sequence-end>
+</table>
+<dtml-if "_.getitem('sequence-length') > _.getitem('sequence-step-size')">
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="right" valign="top">
+ <div class="form-text">
+<dtml-if previous-sequence-size>
+ << <strong><a href="<dtml-var URL><dtml-var sequence-query
+ >query_start=<dtml-var previous-sequence-start-number>">Prev <dtml-var
+ previous-sequence-size></a></strong>
+</dtml-if>
+<dtml-if next-sequence-size>
+ <strong><a href="<dtml-var URL><dtml-var
+ sequence-query>query_start=<dtml-var
+ next-sequence-start-number>">Next <dtml-var
+ next-sequence-size></a></strong> >></a>
+</dtml-if>
+ </div>
+ </td>
+ </tr>
+</table>
+</dtml-if>
+</dtml-if>
+
+<dtml-else>
+<table cellspacing="0" cellpadding="2" border="0">
+<tr>
+<td>
+<div class="std-text">
+This repository is currently empty.
+<br /><br />
+</div>
+</td>
+</tr>
+</table>
+
+</dtml-in>
+
+</form>
+
+</dtml-let>
+<dtml-var manage_page_footer>
Property changes on: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryManageMain.dtml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryProperties.dtml
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryProperties.dtml 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryProperties.dtml 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,39 @@
+<dtml-var manage_page_header>
+<dtml-with "_(management_view='Properties')">
+<dtml-var manage_tabs>
+</dtml-with>
+
+<p>
+Properties of this version history.
+</p>
+
+<!--
+<form action="manage_edit" method="post">
+<table cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-optional">
+ Title
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <input type="text" name="title" size="50"
+ value="<dtml-if title><dtml-var title html_quote></dtml-if>"/>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit" name="submit"
+ value="Save Changes" />
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+-->
+
+<dtml-var manage_page_footer>
Property changes on: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionHistoryProperties.dtml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionManageMain.dtml
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/dtml/VersionManageMain.dtml 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/dtml/VersionManageMain.dtml 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,51 @@
+<dtml-var manage_page_header>
+<dtml-with "_(management_view='Information')">
+<dtml-var manage_tabs>
+</dtml-with>
+
+<p class="form-text">
+ A version contains a copy of a particular state of a version
+ controlled resource.
+</p>
+
+<dtml-with meta>
+<form action="&dtml-URL1;/" method="POST">
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+<tr class="list-header">
+ <td width="5%" align="left" colspan="2">
+ <div class="list-item">
+
+ </div>
+ </td>
+ <td align="left">
+ <div class="list-item">
+ <strong>Version Data</strong>
+ </div>
+ </td>
+</tr>
+<tr class="row-hilite">
+ <td align="left" valign="top" width="16">
+ <input type="checkbox" name="ids:list" value="&dtml-getId;"/>
+ </td>
+ <td align="left" valign="top">
+ <dtml-if getItemIcon>
+ <a href="data/manage_workspace">
+ <img src="&dtml-BASEPATH1;/&dtml-getItemIcon;" alt="&dtml-getItemType;"
+ title="&dtml-getItemType;" border="0" /></a>
+ <dtml-else>
+
+ </dtml-if>
+ </td>
+ <td align="left" valign="top">
+ <div class="list-item">
+ <a href="data/manage_workspace">
+ &dtml-getItemId;
+ </a>
+ </div>
+ </td>
+</tr>
+</table>
+</form>
+</dtml-with>
+
+<dtml-var manage_page_footer>
Property changes on: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionManageMain.dtml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionProperties.dtml
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/dtml/VersionProperties.dtml 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/dtml/VersionProperties.dtml 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,33 @@
+<dtml-var manage_page_header>
+<dtml-with "_(management_view='Properties')">
+<dtml-var manage_tabs>
+</dtml-with>
+
+<form action="manage_edit" method="post">
+<table cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-optional">
+ Title
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <input type="text" name="title" size="50"
+ value="<dtml-if title><dtml-var title html_quote></dtml-if>"/>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit" name="submit"
+ value="Save Changes" />
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<dtml-var manage_page_footer>
Property changes on: Products.ZopeVersionControl/tags/0.3.4/dtml/VersionProperties.dtml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/help/Repository-Add.stx
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/help/Repository-Add.stx 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/help/Repository-Add.stx 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1 @@
+Help is not yet implemented for this product.
Added: Products.ZopeVersionControl/tags/0.3.4/help/Repository-Manage.stx
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/help/Repository-Manage.stx 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/help/Repository-Manage.stx 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1 @@
+Help is not yet implemented for this product.
Added: Products.ZopeVersionControl/tags/0.3.4/help/Repository-Properties.stx
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/help/Repository-Properties.stx 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/help/Repository-Properties.stx 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1 @@
+Help is not yet implemented for this product.
Added: Products.ZopeVersionControl/tags/0.3.4/help/Version-Manage.stx
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/help/Version-Manage.stx 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/help/Version-Manage.stx 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1 @@
+Help is not yet implemented for this product.
Added: Products.ZopeVersionControl/tags/0.3.4/help/Version-Properties.stx
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/help/Version-Properties.stx 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/help/Version-Properties.stx 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1 @@
+Help is not yet implemented for this product.
Added: Products.ZopeVersionControl/tags/0.3.4/help/VersionControl.stx
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/help/VersionControl.stx 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/help/VersionControl.stx 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1 @@
+Help is not yet implemented for this product.
Added: Products.ZopeVersionControl/tags/0.3.4/help/VersionHistory-Manage.stx
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/help/VersionHistory-Manage.stx 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/help/VersionHistory-Manage.stx 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1 @@
+Help is not yet implemented for this product.
Added: Products.ZopeVersionControl/tags/0.3.4/help/VersionHistory-Properties.stx
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/help/VersionHistory-Properties.stx 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/help/VersionHistory-Properties.stx 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1 @@
+Help is not yet implemented for this product.
Added: Products.ZopeVersionControl/tags/0.3.4/issues.txt
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/issues.txt 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/issues.txt 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,25 @@
+Current Issues:
+
+ - fix up select by date apis
+
+ - fix up "isAVersionableResource"
+
+ - rethink branch structures
+
+ - The UI (such as it is) for version controlled objects (a.k.a
+ the version control tab) is hacked in a most unsavory way. We
+ need to finish providing a ZMI UI for the basic VC operations
+ and integrate the version control tab in a better way.
+
+ - The ZMI for the Repository, VersionHistory and Version objects is
+ only just started. We should at least have basic UI for these.
+
+ - What happens if a repository goes away or if a version history
+ were to be deleted somehow is still not well thought out. At a
+ minimum, the UI elements should be able to tell if something
+ really bad has happened and tell you (right now you'd probably
+ get a traceback).
+
+ - We'd like to support some way to set the default state policy
+ (checked out by default vs. checked-in by default). This is
+ something that we could add later.
Property changes on: Products.ZopeVersionControl/tags/0.3.4/issues.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/nonversioned.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/nonversioned.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/nonversioned.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,173 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+"""Support for non-versioned data embedded in versioned objects.
+
+$Id$
+"""
+
+from Acquisition import aq_base
+from OFS.ObjectManager import ObjectManager
+
+from IVersionControl import INonVersionedData
+from VersionSupport import isAVersionableResource
+
+
+try:
+ # Optional support for references.
+ from Products.References.Proxy import proxyBase
+ from Products.References.PathReference import PathReference
+except ImportError:
+ isProxyOrReference = None
+else:
+ def isProxyOrReference(obj):
+ if proxyBase(obj) is not aq_base(obj):
+ return 1
+ if isinstance(obj, PathReference):
+ return 1
+ return 0
+
+
+def getNonVersionedDataAdapter(obj):
+ """Returns an INonVersionedData adapter for any object.
+
+ This is a super-simplistic adapter implementation.
+ """
+ base = aq_base(obj)
+ # If the object implements INonVersionedData, let it say
+ # what its items are.
+ if INonVersionedData.isImplementedBy(base):
+ return obj
+ # If the object is an ObjectManager, use the ObjectManager adapter.
+ try:
+ is_obj_mgr = isinstance(base, ObjectManager)
+ except TypeError:
+ # Python 2.1 isinstance() dislikes ExtensionClass instances.
+ # This is an adequate workaround.
+ pass
+ else:
+ if is_obj_mgr:
+ return ObjectManagerNonVersionedDataAdapter(obj)
+ # Otherwise use the standard adapter.
+ return StandardNonVersionedDataAdapter(obj)
+
+
+def listNonVersionedObjects(obj):
+ return getNonVersionedDataAdapter(obj).listNonVersionedObjects()
+
+def getNonVersionedData(obj):
+ return getNonVersionedDataAdapter(obj).getNonVersionedData()
+
+def removeNonVersionedData(obj):
+ getNonVersionedDataAdapter(obj).removeNonVersionedData()
+
+def restoreNonVersionedData(obj, dict):
+ getNonVersionedDataAdapter(obj).restoreNonVersionedData(dict)
+
+
+
+class StandardNonVersionedDataAdapter:
+ """Non-versioned data adapter for arbitrary things.
+ """
+ __implements__ = INonVersionedData
+
+ def __init__(self, obj):
+ self.obj = obj
+ # __vc_ignore__, if set, is a tuple of attribute names to
+ # manage independently of version control.
+ self.attrs = getattr(obj, "__vc_ignore__", ())
+
+ def listNonVersionedObjects(self):
+ # Assume it's OK to clone all of the attributes.
+ # They will be removed later by removeNonVersionedData.
+ return ()
+
+ def removeNonVersionedData(self):
+ for attr in self.attrs:
+ try:
+ delattr(aq_base(self.obj), attr)
+ except (AttributeError, KeyError):
+ pass
+
+ def getNonVersionedData(self):
+ data = {}
+ for attr in self.attrs:
+ if hasattr( aq_base(self.obj), attr ):
+ data[attr] = aq_base(getattr(aq_base(self.obj), attr))
+ return data
+
+ def restoreNonVersionedData(self, data):
+ for attr in self.attrs:
+ if data.has_key(attr):
+ setattr(aq_base(self.obj), attr, data[attr])
+
+
+class ObjectManagerNonVersionedDataAdapter(StandardNonVersionedDataAdapter):
+ """Non-versioned data adapter for object managers.
+ """
+ __implements__ = INonVersionedData
+
+ def listNonVersionedObjects(self):
+ contents = self.getNonVersionedData()['contents']
+ return contents.values()
+
+ def removeNonVersionedData(self):
+ StandardNonVersionedDataAdapter.removeNonVersionedData(self)
+ obj = self.obj
+ removed = {}
+ contents = self.getNonVersionedData()['contents']
+ for name, value in contents.items():
+ obj._delOb(name)
+ removed[name] = 1
+ if obj._objects:
+ obj._objects = tuple([info for info in obj._objects
+ if not removed.has_key(info['id'])])
+
+ def getNonVersionedData(self):
+ contents = {}
+ attributes = StandardNonVersionedDataAdapter.getNonVersionedData(self)
+ for name, value in self.obj.objectItems():
+ if not isAVersionableResource(value):
+ # This object should include the state of subobjects
+ # that won't be versioned independently.
+ continue
+ if isProxyOrReference is not None:
+ if isProxyOrReference(value):
+ # This object should include the state of
+ # subobjects that are references.
+ continue
+ contents[name] = aq_base(value)
+ return {'contents': contents, 'attributes': attributes}
+
+ def restoreNonVersionedData(self, data):
+ StandardNonVersionedDataAdapter.restoreNonVersionedData(
+ self, data['attributes'])
+ # First build "ignore", a dictionary that lists which
+ # items were stored in the repository.
+ # Don't restore over those.
+ obj = self.obj
+ ignore = {}
+ for name in obj.objectIds():
+ ignore[name] = 1
+ # Restore the items of the container.
+ for name, value in data['contents'].items():
+ if not ignore.has_key(name):
+ obj._setOb(name, aq_base(value))
+ if not hasattr(obj, '_tree'):
+ # Avoid generating events, since nothing was ever really
+ # removed or added.
+ obj._objects += ({'meta_type': value.meta_type,
+ 'id': name},)
+ # If there is a _tree attribute, it's very likely
+ # a BTreeFolder2, which doesn't need or want the
+ # _objects attribute.
+ # XXX This is a hackish way to check for BTreeFolder2s.
Property changes on: Products.ZopeVersionControl/tags/0.3.4/nonversioned.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/tests/__init__.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/tests/__init__.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/tests/__init__.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,14 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+__version__='$Revision: 1.2 $'[11:-2]
Property changes on: Products.ZopeVersionControl/tags/0.3.4/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/tests/common.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/tests/common.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/tests/common.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,93 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+""" Unit testing utilities
+
+$Id$
+"""
+try:
+ import transaction
+except ImportError: # Zope < 2.8
+ get_transaction = get_transaction
+else:
+ def get_transaction():
+ return transaction
+
+def common_setUp(self):
+ # Install a hack to make SimpleItem version aware, so that the
+ # tests work. In normal development, you would mix in the
+ # VersionSupport class on an as-needed basis.
+ import cStringIO
+ from AccessControl.SecurityManagement import newSecurityManager
+ from OFS.Application import Application
+ from OFS.DTMLDocument import addDTMLDocument
+ from OFS.Folder import manage_addFolder
+ from Testing.makerequest import makerequest
+
+ import Products.ZopeVersionControl
+ Products.ZopeVersionControl.install_hack()
+
+ from Products.ZopeVersionControl.ZopeRepository import addRepository
+ from ZODB import DB
+ from ZODB.DemoStorage import DemoStorage
+ s = DemoStorage(quota=(1<<20))
+ self.connection = DB( s ).open()
+ try:
+ r = self.connection.root()
+ a = Application()
+ r['Application'] = a
+ self.root = a
+ responseOut = self.responseOut = cStringIO.StringIO()
+ self.app = makerequest( self.root, stdout=responseOut )
+ self.app.acl_users.userFolderAddUser('UnitTester', '123', (), ())
+ manage_addFolder(self.app, 'folder1')
+ self.folder1 = getattr(self.app, 'folder1')
+ manage_addFolder(self.folder1, 'folder2')
+ self.folder2 = getattr(self.folder1, 'folder2')
+ addDTMLDocument(self.folder2, 'document1', file='some text')
+ self.document1 = getattr(self.folder2, 'document1')
+ addDTMLDocument(self.folder2, 'document2', file='some text')
+ self.document2 = getattr(self.folder2, 'document2')
+ addDTMLDocument(self.folder2, 'document_nonversion', file='some?')
+ self.document_nonversion = getattr(self.folder2,
+ 'document_nonversion')
+ self.document_nonversion.__non_versionable__ = 1
+ addRepository(self.folder1, 'repository')
+ self.repository = getattr(self.folder1, 'repository')
+ get_transaction().commit()
+ except:
+ self.connection.close()
+ raise
+ get_transaction().begin()
+ user = self.app.acl_users.getUser('UnitTester')
+ user = user.__of__(self.app.acl_users)
+ newSecurityManager( None, user)
+
+def common_tearDown(self):
+ from AccessControl.SecurityManagement import noSecurityManager
+ noSecurityManager()
+ del self.folder1
+ del self.folder2
+ del self.document1
+ del self.document2
+ get_transaction().abort()
+ self.app._p_jar.sync()
+ self.connection.close()
+ del self.app
+ del self.responseOut
+ del self.root
+ del self.connection
+
+def common_commit(self):
+ if self.do_commits:
+ get_transaction().commit()
+
Property changes on: Products.ZopeVersionControl/tags/0.3.4/tests/common.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/tests/testReferenceVersioning.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/tests/testReferenceVersioning.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/tests/testReferenceVersioning.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,117 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+"""Tests of combining ZopeVersionControl with the References product.
+
+$Id$
+"""
+import unittest
+
+from common import common_setUp
+from common import common_tearDown
+
+has_refs = 1
+try:
+ from Products.References.PathReference import PathReference
+except ImportError:
+ has_refs = 0
+
+class ReferenceVCTests(unittest.TestCase):
+
+ setUp = common_setUp
+ tearDown = common_tearDown
+
+ def testContainerVersioning(self):
+ # Verify that containers and items are versioned independently,
+ # except in the case of references.
+ from OFS.DTMLDocument import addDTMLDocument
+
+ repository = self.repository
+ folder1 = self.app.folder1
+ folder2 = folder1.folder2
+ folder1.testattr = 'container_v1'
+ folder2.testattr = 'item_v1'
+ folder1._setOb("ref", PathReference("ref", folder1.folder2))
+ folder2._true_id = "folder2"
+ self.assertEqual(folder1.ref._true_id, "folder2")
+
+ self.assert_(not repository.isUnderVersionControl(folder1))
+ repository.applyVersionControl(folder1)
+ folder1 = self.app.folder1
+ self.assert_(repository.isUnderVersionControl(folder1))
+ self.assert_(not repository.isUnderVersionControl(folder2))
+ self.assert_(not repository.isUnderVersionControl(folder1.ref))
+ repository.applyVersionControl(folder2)
+ folder2 = folder1.folder2
+ self.assert_(repository.isUnderVersionControl(folder2))
+ self.assert_(not repository.isUnderVersionControl(folder2.document1))
+
+ # Make the first version of folder1 and check it in.
+ repository.checkoutResource(folder1)
+ folder1 = self.app.folder1
+ repository.checkinResource(folder1)
+ folder1 = self.app.folder1
+ folder2 = folder1.folder2
+ info = repository.getVersionInfo(folder1)
+ first_version = info.version_id
+
+ # Change folder1 and check it in again
+ repository.checkoutResource(folder1)
+ folder1 = self.app.folder1
+ folder1.testattr = 'container_v2'
+ addDTMLDocument(folder1, 'document3', file='some more text')
+ folder1.document3._true_id = "document3"
+ repository.checkinResource(folder1)
+ folder1 = self.app.folder1
+ folder2 = folder1.folder2
+
+ # Change ref to point to document3.
+ folder1._delObject("ref")
+ folder1._setOb("ref", PathReference("ref", folder1.document3))
+ self.assertEqual(folder1.ref._true_id, "document3")
+
+ # Change folder2
+ repository.checkoutResource(folder2)
+ folder2 = folder1.folder2
+ folder2.testattr = 'item_v2'
+
+ # Now revert folder1 and verify that folder2 was not reverted.
+ # Also verify that ref now points back to folder2.
+ repository.updateResource(folder1, first_version)
+ folder1 = self.app.folder1
+ folder2 = folder1.folder2
+ self.assertEqual(folder1.testattr, 'container_v1')
+ self.assertEqual(folder2.testattr, 'item_v2')
+ self.assertEqual(folder1.ref._true_id, "folder2")
+
+ # Verify that document3 remains an item of the reverted folder1.
+ self.assert_(hasattr(folder1, 'document3'))
+ self.assert_(str(folder1.document3) == 'some more text')
+
+ # Remove document3 and verify that it doesn't reappear upon revert.
+ folder1._delObject('document3')
+ repository.updateResource(folder1, '')
+ folder1 = self.app.folder1
+ self.assertEqual(folder1.testattr, 'container_v2')
+ self.assertEqual(folder1.folder2.testattr, 'item_v2')
+ self.assert_(not hasattr(folder1, 'document3'))
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ if has_refs:
+ suite.addTest(unittest.makeSuite(ReferenceVCTests))
+ return suite
+
+if __name__ == "__main__":
+ unittest.main(defaultTest='test_suite')
+
Property changes on: Products.ZopeVersionControl/tags/0.3.4/tests/testReferenceVersioning.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/tests/testVersionControl.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/tests/testVersionControl.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/tests/testVersionControl.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,780 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+""" Test the ZVC machinery
+
+$Id$
+"""
+import unittest
+
+from common import get_transaction
+from common import common_setUp
+from common import common_tearDown
+from common import common_commit
+
+class VersionControlTests(unittest.TestCase):
+
+ setUp = common_setUp
+ tearDown = common_tearDown
+ commit = common_commit
+
+ do_commits = 0
+
+ def testIsVersionableResource(self):
+ # Test checking whether an object is a versionable resource.
+ repository = self.repository
+ document = self.document1
+ nonversionable = self.document_nonversion
+ self.failUnless(repository.isAVersionableResource(document))
+ self.failIf(repository.isAVersionableResource(nonversionable))
+ self.failIf(repository.isAVersionableResource('foobar'))
+ self.failIf(repository.isAVersionableResource(self))
+
+
+ def testIsUnderVersionControl(self):
+ # Test checking whether an object is under version control.
+ repository = self.repository
+ document = self.document1
+ self.failIf(repository.isUnderVersionControl(document))
+ repository.applyVersionControl(document)
+ self.commit()
+ self.failUnless(repository.isUnderVersionControl(document))
+
+
+ def testIsResourceUpToDate(self):
+ # Test checking whether a versioned resource is up to date.
+ repository = self.repository
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+ self.failUnless(repository.isResourceUpToDate(document))
+
+ info = repository.getVersionInfo(document)
+ first_version = info.version_id
+
+ document = repository.checkoutResource(document)
+ self.commit()
+ document = repository.checkinResource(document, '')
+ self.commit()
+
+ document = repository.updateResource(document, first_version)
+ self.commit()
+ self.failIf(repository.isResourceUpToDate(document))
+
+ document = repository.updateResource(document, None)
+ self.commit()
+ self.failUnless(repository.isResourceUpToDate(document))
+
+
+ def testIsResourceChanged(self):
+ # Test checking whether a versioned resource has changed.
+ repository = self.repository
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+ if self.do_commits:
+ self.failIf(repository.isResourceChanged(document))
+
+ document = repository.checkoutResource(document)
+ self.commit()
+ if self.do_commits:
+ self.failIf(repository.isResourceChanged(document))
+
+ document.manage_edit('change 1', '')
+ self.commit()
+ if self.do_commits:
+ self.failUnless(repository.isResourceChanged(document))
+
+ document = repository.checkinResource(document, '')
+ self.commit()
+ if self.do_commits:
+ self.failIf(repository.isResourceChanged(document))
+
+
+ def testVersionBookkeeping(self):
+ # Check the consistency of the version bookkeeping info.
+ repository = self.repository
+
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.user_id == 'UnitTester')
+ self.failUnless(info.status == info.CHECKED_IN)
+ self.failUnless(info.sticky == None)
+ first_version = info.version_id
+
+ document = repository.checkoutResource(document)
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.status == info.CHECKED_OUT)
+
+ document = repository.checkinResource(document, '')
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.status == info.CHECKED_IN)
+
+ document = repository.updateResource(document, first_version)
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.status == info.CHECKED_IN)
+ self.failUnless(info.version_id == first_version)
+
+ branch_name = 'Bug Fix Branch'
+ repository.makeActivity(document, branch_name)
+ self.commit()
+ document = repository.updateResource(document, branch_name)
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.sticky == ('B', branch_name))
+
+ document = repository.updateResource(document, 'mainline')
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.sticky == None)
+
+ document = repository.checkoutResource(document)
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.status == info.CHECKED_OUT)
+
+ document.manage_edit('change 1', '')
+ self.commit()
+
+ document = repository.uncheckoutResource(document)
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.status == info.CHECKED_IN)
+
+
+ def testApplyVersionControl(self):
+ # Test checking whether a versioned resource is up to date.
+ from Products.ZopeVersionControl.Utility import VersionControlError
+ repository = self.repository
+
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+ self.failUnless(repository.isUnderVersionControl(document))
+
+ # Make sure we can't do it a second time.
+ self.failUnlessRaises(VersionControlError,
+ repository.applyVersionControl,
+ document
+ )
+
+ info = repository.getVersionInfo(document)
+
+ # Check that the last log entry record is what we expect.
+ record = repository.getLogEntries(document)[0]
+ self.failUnless(record.version_id == info.version_id)
+ self.failUnless(record.user_id == 'UnitTester')
+ self.failUnless(record.action == record.ACTION_CHECKIN)
+ self.failUnless(record.path == '/folder1/folder2/document1')
+
+
+ def testCheckoutResource(self):
+ # Test checking out a version controlled resource.
+ from Products.ZopeVersionControl.Utility import VersionControlError
+ repository = self.repository
+
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ first_version = info.version_id
+
+ repository.checkoutResource(document)
+ self.commit()
+
+ # Make sure you can't checkout a checked-out resource.
+ self.failUnlessRaises(VersionControlError,
+ repository.checkoutResource,
+ document
+ )
+
+ # Check that the last log entry record is what we expect.
+ record = repository.getLogEntries(document)[0]
+ self.failUnless(record.version_id == first_version)
+ self.failUnless(record.user_id == 'UnitTester')
+ self.failUnless(record.action == record.ACTION_CHECKOUT)
+ self.failUnless(record.path == '/folder1/folder2/document1')
+
+ document = repository.checkinResource(document, '')
+ self.commit()
+ document = repository.updateResource(document, first_version)
+ self.commit()
+
+ # Make sure you can't checkout a non-up-to-date resource.
+ self.failUnlessRaises(VersionControlError,
+ repository.checkoutResource,
+ document
+ )
+
+ # Check that the last log entry record is what we expect.
+ record = repository.getLogEntries(document)[0]
+ self.failUnless(record.version_id == first_version)
+ self.failUnless(record.user_id == 'UnitTester')
+ self.failUnless(record.action == record.ACTION_UPDATE)
+ self.failUnless(record.path == '/folder1/folder2/document1')
+
+
+ def testCheckinResource(self):
+ # Test checking in a version controlled resource.
+ from Products.ZopeVersionControl.Utility import VersionControlError
+ repository = self.repository
+
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+
+ # Make sure you can't checkin a checked-in resource.
+ self.failUnlessRaises(VersionControlError,
+ repository.checkinResource,
+ document, ''
+ )
+
+ info = repository.getVersionInfo(document)
+ first_version = info.version_id
+
+ repository.checkoutResource(document)
+ self.commit()
+
+ document = repository.checkinResource(document, '')
+ self.commit()
+
+ # Check that the last log entry record is what we expect.
+ record = repository.getLogEntries(document)[0]
+ info = repository.getVersionInfo(document)
+ self.failUnless(record.version_id == info.version_id)
+ self.failUnless(record.user_id == 'UnitTester')
+ self.failUnless(record.action == record.ACTION_CHECKIN)
+ self.failUnless(record.path == '/folder1/folder2/document1')
+
+ self.failUnlessRaises(VersionControlError,
+ repository.checkinResource,
+ document, ''
+ )
+
+ document = repository.updateResource(document, first_version)
+ self.commit()
+
+ self.failUnlessRaises(VersionControlError,
+ repository.checkinResource,
+ document, ''
+ )
+
+
+ def testUncheckoutResource(self):
+ # Test uncheckout of a version controlled resource.
+ from Products.ZopeVersionControl.Utility import VersionControlError
+ repository = self.repository
+
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ first_version = info.version_id
+
+ repository.checkoutResource(document)
+ self.commit()
+
+ document.manage_edit('change 1', '')
+
+ document = repository.uncheckoutResource(document)
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.status == info.CHECKED_IN)
+
+ # Check that the last log entry record is what we expect.
+ record = repository.getLogEntries(document)[0]
+ self.failUnless(record.version_id == first_version)
+ self.failUnless(record.user_id == 'UnitTester')
+ self.failUnless(record.action == record.ACTION_UNCHECKOUT)
+ self.failUnless(record.path == '/folder1/folder2/document1')
+
+
+ def testUpdateResource(self):
+ # Test updating a version controlled resource.
+ from Products.ZopeVersionControl.Utility import VersionControlError
+ repository = self.repository
+
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ first_version = info.version_id
+
+ repository.labelResource(document, 'First Version', 1)
+
+ repository.checkoutResource(document)
+ self.commit()
+
+ document = repository.checkinResource(document, '')
+ self.commit()
+
+ document = repository.updateResource(document, first_version)
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.version_id == first_version)
+
+ document = repository.updateResource(document, None)
+ self.commit()
+
+ document = repository.updateResource(document, 'First Version')
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.version_id == first_version)
+
+ # Check that the last log entry record is what we expect.
+ record = repository.getLogEntries(document)[0]
+ self.failUnless(record.version_id == first_version)
+ self.failUnless(record.user_id == 'UnitTester')
+ self.failUnless(record.action == record.ACTION_UPDATE)
+ self.failUnless(record.path == '/folder1/folder2/document1')
+
+
+ def testLabelResource(self):
+ # Test labeling a version controlled resource.
+ from Products.ZopeVersionControl.Utility import VersionControlError
+ repository = self.repository
+
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ first_version = info.version_id
+
+ repository.labelResource(document, 'First Version', 1)
+
+ document = repository.checkoutResource(document)
+ self.commit()
+
+ self.failUnlessRaises(VersionControlError,
+ repository.labelResource,
+ document, 'First Version', 1
+ )
+
+ document = repository.uncheckoutResource(document)
+ self.commit()
+
+ repository.makeActivity(document, 'Activity 1')
+
+ self.failUnlessRaises(VersionControlError,
+ repository.labelResource,
+ document, 'mainline', 1
+ )
+
+ self.failUnlessRaises(VersionControlError,
+ repository.labelResource,
+ document, 'Activity 1', 1
+ )
+
+ document = repository.checkoutResource(document)
+ self.commit()
+
+ document = repository.checkinResource(document, '')
+ self.commit()
+
+ self.failUnlessRaises(VersionControlError,
+ repository.labelResource,
+ document, 'First Version', 0
+ )
+
+ document = repository.updateResource(document, 'First Version')
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.version_id == first_version)
+
+
+ def testActivityAPI(self):
+ from Products.ZopeVersionControl.Utility import VersionControlError
+
+ repository = self.repository
+ document = self.document1
+
+ repository.applyVersionControl(document)
+ self.commit()
+
+ self.failUnless(repository.isUnderVersionControl(document))
+ self.failUnless(repository.isResourceUpToDate(document))
+ if self.do_commits:
+ self.failIf(repository.isResourceChanged(document))
+
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.sticky == None)
+ first_version = info.version_id
+
+ activity_name = 'My Big Project'
+
+ repository.makeActivity(document, activity_name)
+ self.commit()
+
+ # Make sure we can't do it again for the same activity id.
+ self.failUnlessRaises(VersionControlError,
+ repository.makeActivity,
+ document, activity_name
+ )
+
+ document = repository.updateResource(document, activity_name)
+ self.commit()
+
+ self.failUnless(repository.isResourceUpToDate(document))
+ if self.do_commits:
+ self.failIf(repository.isResourceChanged(document))
+
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.version_id == first_version)
+ self.failUnless(info.sticky == ('B', activity_name))
+
+ repository.checkoutResource(document)
+ self.commit()
+
+ document.manage_edit('activity change 1', '')
+ self.commit()
+
+ document = repository.checkinResource(document, 'activity change 1')
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.sticky == ('B', activity_name))
+
+ for n in range(10):
+ activity_name = 'Activity %d' % n
+
+ repository.makeActivity(document, activity_name)
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ root_version = info.version_id
+
+ document = repository.updateResource(document, activity_name)
+ self.commit()
+
+ self.failUnless(repository.isResourceUpToDate(document))
+
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.sticky == ('B', activity_name))
+ self.failUnless(info.version_id == root_version)
+
+ repository.checkoutResource(document)
+ self.commit()
+
+ document.manage_edit('activity change %d' % n, '')
+ self.commit()
+
+ document = repository.checkinResource(
+ document, 'activity change %d' % n
+ )
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.sticky == ('B', activity_name))
+ self.failIf(info.version_id == root_version)
+
+ document = repository.updateResource(document, root_version)
+ self.commit()
+
+ self.failIf(repository.isResourceUpToDate(document))
+
+ document = repository.updateResource(document, first_version)
+ self.commit()
+
+# self.failUnless(repository.isResourceUpToDate(document))
+
+
+
+
+ def testSelectionByDate(self):
+ # Test selection of versions by date.
+ from Products.ZopeVersionControl.Utility import VersionControlError
+ from DateTime.DateTime import DateTime
+ import time
+
+ repository = self.repository
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+
+ document = repository.checkoutResource(document)
+ self.commit()
+
+ document.manage_edit('change 1', '')
+ self.commit()
+
+ document = repository.checkinResource(document, 'change 1')
+ self.commit()
+
+ repository.labelResource(document, 'change 1')
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ first_version = info.version_id
+
+ # Trickery: we'll hack the timestamp of the first version so
+ # that we can act like it was created yesterday :)
+ history = repository.getVersionHistory(info.history_id)
+ version = history.getVersionById(info.version_id)
+ orig_time = version.date_created
+ new_time = orig_time - 86400.0
+ timestamp = int(orig_time / 60.0)
+ new_stamp = int(new_time / 60.0)
+ version.date_created = new_time
+ branch = history._branches['mainline']
+ key, val = branch.m_order.items()[0]
+ del branch.m_date[timestamp]
+ branch.m_date[new_stamp] = key
+ self.commit()
+
+ for n in range(10):
+ document = repository.checkoutResource(document)
+ self.commit()
+ change_no = 'change %d' % (n + 2)
+ document.manage_edit(change_no, '')
+ self.commit()
+ document = repository.checkinResource(document, change_no)
+ self.commit()
+ repository.labelResource(document, change_no)
+ self.commit()
+
+ target_time = time.time() - 14400.0
+ document = repository.updateResource(document, target_time)
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.version_id == first_version)
+
+ # Now do some branching and make sure we backtrack correctly
+ # through the branch lineage when doing date selection.
+ document = repository.updateResource(document, 'change 5')
+ self.commit()
+
+ for n in range(10):
+ activity_name = 'Activity %d' % n
+ repository.makeActivity(document, activity_name)
+ self.commit()
+ document = repository.updateResource(document, activity_name)
+ self.commit()
+ for i in range(10):
+ repository.checkoutResource(document)
+ self.commit()
+ document.manage_edit('activity change %d' % i, '')
+ self.commit()
+ document = repository.checkinResource(document, '')
+ self.commit()
+
+ document = repository.updateResource(document, target_time)
+ self.commit()
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.version_id == first_version)
+
+
+ def testSelectionByLabel(self):
+ # Test labeling and selection of versions using labels.
+ from Products.ZopeVersionControl.Utility import VersionControlError
+
+ repository = self.repository
+ document = repository.applyVersionControl(self.document1)
+
+ # Ensure that labeling and lookup by label works as expected.
+ label_set = []
+ for n in range(10):
+ change_no = 'change %d' % n
+ document = repository.checkoutResource(document)
+ document.manage_edit(change_no, '')
+ document = repository.checkinResource(document, change_no)
+ repository.labelResource(document, change_no)
+ info = repository.getVersionInfo(document)
+ label_set.append((change_no, info.version_id))
+
+ for label, version_id in label_set:
+ document = repository.updateResource(document, label)
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.version_id == version_id)
+ self.failUnless(info.sticky == ('L', label))
+
+ # Ensure that label moving works as expected and that we get an
+ # error if we try to reuse a label without forcing a label move.
+ document = repository.updateResource(document, 'change 0')
+ repository.labelResource(document, 'change 1', force=1)
+ document = repository.updateResource(document, 'change 1')
+ info = repository.getVersionInfo(document)
+ self.failUnless(info.version_id == label_set[0][1])
+
+ self.failUnlessRaises(VersionControlError,
+ repository.labelResource,
+ document, 'change 3'
+ )
+
+
+ def testGetVersionOfResource(self):
+ # Test retrieving specific versions of resources.
+ from Products.ZopeVersionControl.Utility import VersionControlError
+ repository = self.repository
+
+ document = repository.applyVersionControl(self.document1)
+ self.commit()
+
+ info = repository.getVersionInfo(document)
+ history_id = info.history_id
+ first_version = info.version_id
+
+ repository.labelResource(document, 'First Version')
+
+ for n in range(10):
+ repository.checkoutResource(document)
+ self.commit()
+ document = repository.checkinResource(document, '')
+ self.commit()
+
+ # Make sure the "get version of resource" api is working.
+ doc_copy = repository.getVersionOfResource(
+ info.history_id, first_version
+ )
+ info = repository.getVersionInfo(doc_copy)
+ self.failUnless(info.version_id == first_version)
+ self.failUnless(info.sticky == ('V', first_version))
+ self.failUnless(document._p_oid != doc_copy._p_oid)
+ self.failUnless(document is not doc_copy)
+
+ doc_copy = repository.getVersionOfResource(
+ info.history_id, "First Version"
+ )
+ info = repository.getVersionInfo(doc_copy)
+ self.failUnless(info.version_id == first_version)
+ self.failUnless(info.sticky == ('L', 'First Version'))
+ self.failUnless(document._p_oid != doc_copy._p_oid)
+ self.failUnless(document is not doc_copy)
+
+
+ def testDetectPersistentSubObjectChange(self):
+ # Test detection of changes to persistent sub-objects.
+ repository = self.repository
+ folder2 = self.folder2
+ document = self.document1
+
+ # Place a resource w/ persistent subobjects under version control.
+ repository.applyVersionControl(folder2)
+ get_transaction().commit()
+
+ document1 = getattr(folder2, 'document1')
+ document1.manage_edit('spam spam', '')
+ get_transaction().commit()
+
+ self.failUnless(repository.isResourceChanged(folder2))
+
+
+ def testContainerVersioning(self):
+ from OFS.DTMLDocument import addDTMLDocument
+ # Verify that containers and items are versioned independently.
+ repository = self.repository
+ folder1 = self.app.folder1
+ folder2 = folder1.folder2
+ folder1.testattr = 'container_v1'
+ folder2.testattr = 'item_v1'
+
+ self.assert_(not repository.isUnderVersionControl(folder1))
+ repository.applyVersionControl(folder1)
+ folder1 = self.app.folder1
+ self.assert_(repository.isUnderVersionControl(folder1))
+ self.assert_(not repository.isUnderVersionControl(folder2))
+ repository.applyVersionControl(folder2)
+ folder2 = folder1.folder2
+ self.assert_(repository.isUnderVersionControl(folder2))
+ self.assert_(not repository.isUnderVersionControl(folder2.document1))
+
+ # Make the first version of folder1 and check it in.
+ repository.checkoutResource(folder1)
+ folder1 = self.app.folder1
+ repository.checkinResource(folder1)
+ folder1 = self.app.folder1
+ folder2 = folder1.folder2
+ info = repository.getVersionInfo(folder1)
+ first_version = info.version_id
+
+ # Change folder1 and check it in again
+ repository.checkoutResource(folder1)
+ folder1 = self.app.folder1
+ folder1.testattr = 'container_v2'
+ addDTMLDocument(folder1, 'document3', file='some more text')
+ repository.checkinResource(folder1)
+ folder1 = self.app.folder1
+ folder2 = folder1.folder2
+
+ # Change folder2
+ repository.checkoutResource(folder2)
+ folder2 = folder1.folder2
+ folder2.testattr = 'item_v2'
+
+ # Now revert folder1 and verify that folder2 was not reverted.
+ repository.updateResource(folder1, first_version)
+ folder1 = self.app.folder1
+ folder2 = folder1.folder2
+ self.assertEqual(folder1.testattr, 'container_v1')
+ self.assertEqual(folder2.testattr, 'item_v2')
+
+ # Verify that document3 remains an item of the reverted folder1.
+ self.assert_(hasattr(folder1, 'document3'))
+ self.assert_(str(folder1.document3) == 'some more text')
+
+ # Remove document3 and verify that it doesn't reappear upon revert.
+ folder1._delObject('document3')
+ repository.updateResource(folder1, '')
+ folder1 = self.app.folder1
+ self.assertEqual(folder1.testattr, 'container_v2')
+ self.assertEqual(folder1.folder2.testattr, 'item_v2')
+ self.assert_(not hasattr(folder1, 'document3'))
+
+
+ def testNonVersionedAttribute(self):
+ # Test a non-version-controlled attribute mixed with
+ # a version-controlled attribute.
+ self.document1.extra_attr = 'v1'
+ self.document1.__vc_ignore__ = ('__ac_local_roles__',)
+ self.document1.__ac_local_roles__ = {'sam': ['Manager',]}
+ repository = self.repository
+ document = repository.applyVersionControl(self.document1)
+ info = repository.getVersionInfo(document)
+ first_version = info.version_id
+ repository.checkoutResource(document)
+ self.document1.extra_attr = 'v2'
+ self.document1.__ac_local_roles__ = {}
+ repository.checkinResource(document)
+ repository.updateResource(document, first_version)
+ self.assertEqual(document.extra_attr, 'v1')
+ self.assertEqual(document.__ac_local_roles__, {})
+
+ def testNonVersionedAttributeWithAcquisition(self):
+ # Test a non-version-controlled attribute
+ # that is acquired does not cause an error
+ self.document1.__vc_ignore__ = ('dummy_attr',)
+ self.folder1.dummy_attr = 'dummy_attr'
+ self.assertEqual( self.folder1.dummy_attr, self.document1.dummy_attr )
+
+ repository = self.repository
+ document = repository.applyVersionControl(self.document1)
+ info = repository.getVersionInfo(document)
+ first_version = info.version_id
+ repository.checkoutResource(document)
+ self.document1.extra_attr = 'new'
+ repository.checkinResource(document)
+ repository.updateResource(document, first_version)
+
+class VersionControlTestsWithCommits(VersionControlTests):
+ """Version control test suite with transaction commits that mimic
+ the transaction commits that you would get with Web based usage."""
+ do_commits = 1
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(VersionControlTests))
+ suite.addTest(unittest.makeSuite(VersionControlTestsWithCommits))
+ return suite
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
+
Property changes on: Products.ZopeVersionControl/tags/0.3.4/tests/testVersionControl.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/tests/test_all.py
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/tests/test_all.py 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/tests/test_all.py 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1,41 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL). A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Run all Zope Version Control tests
+
+$Id$"""
+
+import unittest
+
+from Products.ZopeVersionControl.tests import testVersionControl
+
+try:
+ from Products import References
+except ImportError:
+ # References product is not available
+ testReferenceVersioning = None
+else:
+ # References product is available
+ from Products.ZopeVersionControl.tests import testReferenceVersioning
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(testVersionControl.test_suite())
+ if testReferenceVersioning is not None:
+ suite.addTest(testReferenceVersioning.test_suite())
+ return suite
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="test_suite")
Property changes on: Products.ZopeVersionControl/tags/0.3.4/tests/test_all.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/version.txt
===================================================================
--- Products.ZopeVersionControl/tags/0.3.4/version.txt 2007-02-05 15:36:28 UTC (rev 72372)
+++ Products.ZopeVersionControl/tags/0.3.4/version.txt 2007-02-05 16:18:41 UTC (rev 72373)
@@ -0,0 +1 @@
+ZopeVersionControl-0.3.4
Property changes on: Products.ZopeVersionControl/tags/0.3.4/version.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Products.ZopeVersionControl/tags/0.3.4/www/Repository.gif
===================================================================
(Binary files differ)
Property changes on: Products.ZopeVersionControl/tags/0.3.4/www/Repository.gif
___________________________________________________________________
Name: svn:executable
+
Name: svn:mime-type
+ image/gif
Added: Products.ZopeVersionControl/tags/0.3.4/www/Version.gif
===================================================================
(Binary files differ)
Property changes on: Products.ZopeVersionControl/tags/0.3.4/www/Version.gif
___________________________________________________________________
Name: svn:executable
+
Name: svn:mime-type
+ image/gif
Added: Products.ZopeVersionControl/tags/0.3.4/www/VersionHistory.gif
===================================================================
(Binary files differ)
Property changes on: Products.ZopeVersionControl/tags/0.3.4/www/VersionHistory.gif
___________________________________________________________________
Name: svn:executable
+
Name: svn:mime-type
+ image/gif
More information about the Checkins
mailing list