[Zope-CVS] CVS: Products/ZopeVersionControl - Repository.py:1.1 Utility.py:1.1 Version.py:1.1 VersionHistory.py:1.1 __init__.py:1.1 notes.py:1.1

Brian Lloyd brian@digicool.com
Fri, 19 Oct 2001 13:58:38 -0400


Update of /cvs-repository/Products/ZopeVersionControl
In directory cvs.zope.org:/tmp/cvs-serv27333/ZopeVersionControl

Added Files:
	Repository.py Utility.py Version.py VersionHistory.py 
	__init__.py notes.py 
Log Message:
initial commit of version control prototype code

=== Added File Products/ZopeVersionControl/Repository.py ===
__version__='$Revision: 1.1 $'[11:-2]

from Globals import DTMLFile, InitializeClass
from OFS.ObjectManager import ObjectManager
from VersionHistory import VersionHistory
import OFS, AccessControl, Acquisition


class Repository(
    OFS.ObjectManager.ObjectManager,
    AccessControl.Role.RoleManager,
    OFS.SimpleItem.Item,
    ):
    """ """
    __non_versionable__ = 1

    security = AccessControl.ClassSecurityInfo()
    
    meta_type = 'Repository'

    manage_options=(
        ( {'label': 'Contents',    'action':'manage_main',
           'help': ('Zope Help', 'Repository-Manage.stx')},
          {'label': 'Properties', 'action':'manage_properties_form',
           'help': ('Zope Help', 'Repository-Properties.stx')},
        ) +
        AccessControl.Role.RoleManager.manage_options +
        OFS.SimpleItem.Item.manage_options
        )

    security.declareProtected('View management screens',
                              'manage_main', 'manage_properties_form'
                              )

    manage_main = DTMLFile('dtml/RepositoryManageMain', globals())
    manage_properties_form = DTMLFile('dtml/RepositoryProperties', globals())
    manage_main._setName('manage_main')
    manage = manage_main

    def __init__(self, id, title=''):
        self.id = id
        self.title = title


    security.declareProtected('Change 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
                )



    # Repository object public API

    def getVersionHistories(self):
        """Return a sequence containing the version history objects in the
           repository."""
        # make this a tricky sequence! :)
        return self.objectValues()

    def createVersionHistory(self, object):
        """Create a new version history in the repository for the object."""
        next_id = getattr(self, '_next_id', 0)
        self._next_id = next_id + 1
        id = '%0.09d' % self._next_id
        vhistory = VersionHistory(id, object)
        self._setObject(id, vhistory)
        return self.getVersionHistory(id)

    def getVersionHistory(self, id):
        """Get an object version history given a version history id, or
           None if a version history with the given id does not exist."""
        return self._getOb(id, None)

    def delVersionHistory(self, id):
        """Permanently remove a version history from the repository by id."""
        self._delObject(id)



InitializeClass(Repository)


def addRepository(self, id, title='', REQUEST=None):
    """Zope object constructor function."""
    object = Repository(id, title)
    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),
)


=== Added File Products/ZopeVersionControl/Utility.py ===
__version__='$Revision: 1.1 $'[11:-2]

from Globals import InitializeClass, Persistent
import ExtensionClass, AccessControl
import string


class VersionInfo(Persistent):
    """ """

    security = AccessControl.ClassSecurityInfo()
    
    def __init__(self, object):
        pass

    security.declarePublic('getRepositoryId')
    def getRepositoryId(self):
        return self._repository_id

    security.declarePrivate('setRepositoryId')
    def setRepositoryId(self, id):
        self._repository_id = id

    security.declarePublic('getVersionHistoryId')
    def getVersionHistoryId(self):
        return self._history_id

    security.declarePrivate('setVersionHistoryId')
    def setVersionHistoryId(self, id):
        self._history_id = id

    security.declarePublic('getSourceVersionId')
    def getSourceVersionId(self):
        return self._version_id

    security.declarePrivate('setSourceVersionId')
    def setSourceVersionId(self, id):
        self._version_id = id

    security.declarePublic('getVersionPath')
    def getVersionPath(self):
        return self._version_path

    security.declarePrivate('setVersionPath')
    def setVersionPath(self, path):
        self._version_path = path

    security.declarePublic('getResourceStatus')
    def getResourceStatus(self):
        return getattr(self, '_status', 'checked-in')

    security.declarePrivate('setResourceStatus')
    def setResourceStatus(self, status):
        if not status in ('checked-in', 'checked-out'):
            raise ValueError, status
        self._status = status



    security.declarePrivate('clone')
    def clone(self):
        info = VersionInfo(None)
        dict = info.__dict__
        for name, value in self.__dict__.items():
            dict[name] = value
        return info


class ObjectMetadata(Persistent):
    """ """

    security = AccessControl.ClassSecurityInfo()
    
    def __init__(self, object):
        # Save some basic information about the object, so that we
        # don't have to wake it up for simple things like listing
        # the available version histories in the repository.
        self._ob_meta_type = getattr_ex(object, 'meta_type', None)
        self._ob_icon = getattr_ex(object, 'icon', None)
        path = object.getPhysicalPath()
        self._ob_path = string.join(path, '/')
        self._ob_id = find_id(object)

    security.declarePublic('getItemIcon')
    def getItemIcon(self):
        """Return the icon of the underlying version controlled resource."""
        return self._ob_icon

    security.declarePublic('getItemType')
    def getItemType(self):
        """Return the type name of the version controlled resource."""
        return self._ob_meta_type

    security.declarePublic('getItemPath')
    def getItemPath(self):
        """Return the original path of the resource that intially was
           used to create the version history in the repository."""
        return self._ob_path

    security.declarePublic('getItemId')
    def getItemId(self):
        """Return the original id of the version controlled resource."""
        return self._ob_id


InitializeClass(ObjectMetadata)



from DateTime.DateTime import DateTime
import time

class AuditRecord(Persistent):
    """ """

    security = AccessControl.ClassSecurityInfo()

    def __init__(self, action, username, path, message):
        self._version_id = None
        self._action = action
        self._path = path
        self._username = username
        self._message = message
        self._time = time.time()

    security.declarePublic('getVersionId')
    def getVersionId(self):
        return self._version_id

    security.declarePublic('setVersionId')
    def setVersionId(self, version_id):
        self._version_id = version_id

    security.declarePublic('getAction')
    def getAction(self):
        return self._action

    security.declarePublic('getTargetPath')
    def getTargetPath(self):
        return self._path

    security.declarePublic('getUserName')
    def getUserName(self):
        return self._username

    security.declarePublic('getMessage')
    def getMessage(self):
        return self._message

    security.declarePublic('getDateTime')
    def getDateTime(self):
        return DateTime(self._time)



InitializeClass(AuditRecord)


class CheckoutRecord(Persistent):
    """ """

    security = AccessControl.ClassSecurityInfo()

    def __init__(self, activity_id, version_id, path, username):
        self._activity_id = activity_id
        self._version_id = version_id
        self._username = username
        self._time = time.time()
        self._path = path

    security.declarePublic('getActivityId')
    def getActivityId(self):
        return self._activity_id

    security.declarePublic('getVersionId')
    def getVersionId(self):
        return self._version_id

    security.declarePublic('getTargetPath')
    def getTargetPath(self):
        return self._path

    security.declarePublic('getUserName')
    def getUserName(self):
        return self._username

    security.declarePublic('getMessage')
    def getMessage(self):
        return self._message

    security.declarePublic('getDateTime')
    def getDateTime(self):
        return DateTime(self._time)

InitializeClass(CheckoutRecord)



_marker = []

def getattr_ex(object, name, default=_marker):
    data = getattr(object, name, default)
    if data is _marker and default is _marker:
        raise AttributeError, name
    if callable(data):
        return data()
    return data
    
def find_id(object):
    name=getattr(object, 'id', None)
    if callable(name):
        return name()
    if name is not None:
        return name
    if hasattr(object, '__name__'):
        return object.__name__
    raise AttributeError, 'This object has no id'


=== Added File Products/ZopeVersionControl/Version.py ===
__version__='$Revision: 1.1 $'[11:-2]

from Globals import DTMLFile, InitializeClass
from Globals import PersistentMapping
from OFS.ObjectManager import ObjectManager
import OFS, AccessControl, Acquisition
from Utility import ObjectMetadata
from Utility import AuditRecord
import copy

class Version(
    Acquisition.Implicit,
    OFS.SimpleItem.Item,
    AccessControl.Role.RoleManager
    ):
    """A "version resource", or simply "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 server allocates a 
       distinct new URL for each new version, and this URL will never be 
       used to identify any resource other than that version.  The content 
       and dead properties of a version never change.

       A "version name" is a string chosen by the server to distinguish 
       one version of a version history from the other versions of that 
       version history.  Versions from different version histories may 
       have the same version name."""

    security = AccessControl.ClassSecurityInfo()
    __non_versionable__ = 1

    meta_type = 'Version'

    manage_options=(
        ( {'label': 'Information',    'action':'manage_main',
           'help': ('Zope Help', 'Version-Manage.stx')},
          {'label': 'Activity Log',    'action':'manage_activity_form',
           'help': ('Zope Help', 'Version-ActivityLog.stx')},
          {'label': 'Properties', 'action':'manage_properties_form',
           'help': ('Zope Help', '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_properties_form',
                              'manage_activity_form'
                              )

    manage_main = DTMLFile('dtml/VersionManageMain', globals())
    manage_main._setName('manage_main')
    manage = manage_main

    manage_properties_form = DTMLFile('dtml/VersionProperties', globals())
    manage_activity_form = DTMLFile('dtml/VersionActivityLog', globals())

    security.declareProtected('Manage version resources', '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 __init__(self, id, object):
        self.id = id
        self.meta = ObjectMetadata(object)
        self.saveState(object)
        # xxx - fix this
        self.records = []
#        self.co_state = PersistentMapping()

    def addMessageEntry(self, action, username, path, message):
        record = AuditRecord(action, username, path, message)
        record.setVersionId(self.id)
        records = self.records
        records.append(record)
        self.records = records


    def getMessageEntries(self):
        return self.records

    def saveState(self, object):
        baseobj = Acquisition.aq_base(object)
        # xxx - fix this!
        obcopy =  object._getCopy(object)
        obcopy.__non_versionable__ = 1
        self.data = obcopy
        return

    def copyState(self):
        # xxx - fix this!
        object = self.data._getCopy(self.data)
        if hasattr(object, '__non_versionable__'):
            del object.__non_versionable__
        return object

    def getVersionId(self):
        """ """
        return self.id

InitializeClass(Version)



=== Added File Products/ZopeVersionControl/VersionHistory.py ===
__version__='$Revision: 1.1 $'[11:-2]

from Globals import DTMLFile, InitializeClass
from Globals import PersistentMapping
from OFS.ObjectManager import ObjectManager
import OFS, AccessControl, Acquisition
from Utility import ObjectMetadata
from Utility import CheckoutRecord
from Version import Version
import copy


class VersionHistory(
    OFS.ObjectManager.ObjectManager,
    AccessControl.Role.RoleManager,
    OFS.SimpleItem.Item,
    ):
    """A version history resource, or simply version history, is a 
       resource that contains all the versions of a particular version
       controlled resource."""
    __non_versionable__ = 1

    security = AccessControl.ClassSecurityInfo()

    meta_type = 'Version History'

    manage_options=(
        ( {'label': 'Contents',    'action':'manage_main',
           'help': ('Zope Help', 'VersionHistory-Manage.stx')},
          {'label': 'Activity Log',    'action':'manage_activity_form',
           'help': ('Zope Help', 'VersionHistory-ActivityLog.stx')},
          {'label': 'Properties', 'action':'manage_properties_form',
           'help': ('Zope Help', '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_properties_form',
                              'manage_activity_form'
                              )

    manage_main = DTMLFile('dtml/VersionHistoryManageMain', globals())
    manage_main._setName('manage_main')
    manage = manage_main

    manage_properties_form = DTMLFile('dtml/VersionHistoryProperties',
                                      globals())
    manage_activity_form = DTMLFile('dtml/VersionHistoryActivityLog',
                                    globals())


    def __init__(self, id, object):
        self.id = id
        self.meta = ObjectMetadata(object)
        self.co_state = PersistentMapping()

    security.declareProtected('Manage version histories', '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 getDescription(self):
        return getattr(self, '_description', '')

    def setDescription(self, description):
        self._description = description

    def nextVersionId(self, object):
        # xxx - fix this
        next_id = getattr(self, '_next_id', 0)
        self._next_id = next_id + 1
        return'1.%d' % self._next_id

    def lastVersionId(self):
        ids = self.objectIds()
        ids.sort()
        return ids[-1]

    def createVersion(self, object):
        ver_id = self.nextVersionId(object)
        version = Version(ver_id, object)
        self._setObject(ver_id, version)
        return self.getVersion(ver_id)

    def getVersionIds(self):
        """ """
        return self.objectIds()

    def getVersions(self):
        """Return a sequence containing the versions of the resource."""
        # make this a tricky sequence! :)
        return self.objectValues()

    def getVersion(self, id):
        """ """
        return self._getOb(id, None)

    def delVersion(self, id):
        """ """
        self._delObject(id)


    def registerCheckout(self, activity, version_id, path, username):
        """ """
        if self.co_state.has_key(activity):
            raise ValueError, 'Already checked out in activity!'

        co_record = CheckoutRecord(activity, version_id, path, username)
        self.co_state[activity] = co_record

    def unregisterCheckout(self, activity):
        """ """
        if self.co_state.has_key(activity):
            del self.co_state[activity]
        return

    def getCheckoutRecords(self):
        """ """
        return self.co_state.values()

    def getCurrentCheckout(self, activity):
        return self.co_state.get(activity)

    def getAllMessageEntries(self):
        """ """
        entries = {}
        for item in self.getVersions():
            for message in item.getMessageEntries():
                entries[message.getDateTime()] = message
        keys = entries.keys()
        keys.sort()
        keys.reverse()
        result = []
        for key in keys:
            result.append(entries[key])
        return result


InitializeClass(VersionHistory)




=== Added File Products/ZopeVersionControl/__init__.py ===
""" """

__version__='$Revision: 1.1 $'[11:-2]

import Repository, OFS, App

def initialize(context):

    context.registerClass(
        instance_class = Repository.Repository,
        meta_type      = 'Repository',
        permission     = 'Add Repositories',
        constructors   = Repository.constructors,
        icon           = 'www/Repository.gif'
      )

    context.registerHelp()
    context.registerHelpTitle('Zope Help')

    registerIcon('VersionHistory.gif')
    registerIcon('Version.gif')


def registerIcon(filename):
    setattr(OFS.misc_.misc_.ZopeVersionControl, filename, 
            App.ImageFile.ImageFile('www/%s' % filename, globals())
            )



=== Added File Products/ZopeVersionControl/notes.py ===

"""
operations on versionable resources
  put under vc:
    - select repository
    - create a version history
    - associate ob with vh
    - commit obj

  checkout:

  checkin:
    - find repository & vh
    - create a new version
    - update obj version pointers

  update:
    - select new version

  label:
    - xxx

  
  

collection:
  contains a set of relationships, called bindings

configuration:
  is a set of resources, induced recursively by the
  binding relationships

  is a set of resources that consists of a root
  collection and all members (not just internal
  members) of that root collection

baseline:
  captures the state of the version-controlled members
  of a configuration

  represents a configuration, with the added constraint that
  a baseline only represents those members of a configuration
  that are under version control. For a configuration of a
  collection that has versioned and unversioned resources, the
  baseline will be a subset of the configuration (only the
  version-controlled resources).

workspace:
  a resource (location, non-versionable)

activity:
  logically like a transaction, contains all of the changes for
  a single logical change



"""

class Repository:
    pass


class VersionHistory:
    """A "version history resource", or simply "version history", is a 
       resource that contains all the versions of a particular version-
       controlled resource."""

    versions = ('list of version resources',)
    def getRootVersion(self):
        pass


class Version:
    """A "version resource", or simply "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 server allocates a 
       distinct new URL for each new version, and this URL will never be 
       used to identify any resource other than that version.  The content 
       and dead properties of a version never change.

       A "version name" is a string chosen by the server to distinguish 
       one version of a version history from the other versions of that 
       version history.  Versions from different version histories may 
       have the same version name."""

    def getVersionName(self):
        pass

    def getVersionURL(self):
        pass

    def getPredecessor(self):
        pass

    def getSuccessor(self):
        pass

    def getAncestors(self):
        pass

    def getDescendants(self):
        pass

    def getCheckoutSet(self):
        pass


class VersionControlledResource:
    """When a versionable resource is put under version control, it 
       becomes a "version-controlled resource".  A version-controlled
       resource can be "checked out" to allow modification of its content 
       or dead properties by standard HTTP and WebDAV methods."""
    def getAutoVersion(self):
        return 'auto versioning settings'

    def getCheckedOutVersion(self):
        return 'pointer to version'

    def getCheckedInVersion(self):
        return 'pointer to version'

    def checkOut(self):
        pass

    def uncheckOut(self):
        pass

    def checkIn(self):
        pass

    def update(self):
        """The update feature provides a mechanism for changing the state of a 
           checked-in version-controlled resource to be that of another 
           version from the version history of that resource."""
        pass

    def label(self):
        """A LABEL request can be applied to a version to modify the labels 
           that select that version.  The case of a label name MUST be 
           preserved when it is stored and retrieved."""
        pass

class Workspace:
    """A "workspace resource", or simply "workspace", is a collection that 
       contains at most one version-controlled resource for a given 
       version history (see Section 6)."""
    def getCheckOutSet(self):
        pass

    


class WorkingResource:
    """A "working resource" is a checked-out resource created by the 
       server at a server-defined URL when a version (instead of a 
       version-controlled resource) is checked out.  Unlike a checked-out 
       version-controlled resource, a working resource is a deleted when 
       it is checked in."""
    pass