[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>
+  &lt;&lt; <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>
+  &nbsp;&nbsp;<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>&nbsp;&gt&gt;</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">
+  &nbsp;&nbsp;&nbsp;&nbsp;
+  </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>
+  &lt;&lt; <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>
+  &nbsp;&nbsp;<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>&nbsp;&gt&gt;</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">&lt; Later entries</a>
+  </a>
+<dtml-else>
+&nbsp;
+</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 &gt</a>
+  </a>
+<dtml-else>
+&nbsp;
+</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">
+  &nbsp;
+  </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 &quot;Apply version 
+control&quot; 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>
+  &lt;&lt; <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>
+  &nbsp;&nbsp;<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>&nbsp;&gt&gt;</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">
+  &nbsp;&nbsp;&nbsp;&nbsp;
+  </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>
+  &lt;&lt; <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>
+  &nbsp;&nbsp;<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>&nbsp;&gt&gt;</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">
+  &nbsp;&nbsp;&nbsp;&nbsp;
+  </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>
+  &nbsp;
+  </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