[Zope-CVS] CVS: Packages/VersionControl - VersionControl.py:1.1 VersionSupport.py:1.1 __init__.py:1.1

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


Update of /cvs-repository/Packages/VersionControl
In directory cvs.zope.org:/tmp/cvs-serv26291/VersionControl

Added Files:
	VersionControl.py VersionSupport.py __init__.py 
Log Message:
initial checkin of version control prototype code


=== Added File Packages/VersionControl/VersionControl.py ===
__version__='$Revision: 1.1 $'[11:-2]

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

class VersionControl(ExtensionClass.Base):
    """ """

    def __init__(self, context):
        self.context = context

    def getRepositoryIds(self):
        """Return a list of valid repository ids."""
        # XXX - fix this
        context = self.context
        base = Acquisition.aq_base(context)
        try:
            items = self.superValues('Repository')
        except:
            items = context.aq_inner.aq_parent.superValues('Repository')
        result = []
        for item in items:
            result.append(item.getId())
        return result

    def getRepository(self, id):
        """Return the named repository object."""
        return getattr(self.context, id)

    def versionControl(self, object, repository_id, description, use_auto=0):
        """Place an object under version control."""

        # First, make sure object is not already under version control.
        if self.isUnderVersionControl(object):
            raise 

        # Check for semantic conflicts
        # xxx

        # Get the repository we'll be using and create a new version history.
        repository = self.getRepository(repository_id)
        history = repository.createVersionHistory(object)
        history.setDescription(description)
        version = history.createVersion(object)
        version.addMessageEntry('checkin',
                                self._findUserName(),
                                self._getObjectPath(object),
                                'Initial checkin.'
                                )


        # Set versioning information on the version-controlled object.
        vinfo = VersionInfo(object)
        vinfo.setRepositoryId(repository.getId())
        vinfo.setVersionHistoryId(history.getId())
        vinfo.setSourceVersionId(version.getId())
        vinfo.setVersionPath(self._getObjectPath(version))
        self.setVersionInfo(object, vinfo)
        return object

    def isUnderVersionControl(self, object):
        """Return true if object is under version control."""
        return self.getVersionInfo(object) is not None

    def getVersionInfo(self, object):
        """Return version control information associated with object."""
        return getattr(object, '_vc_info', None)

    def setVersionInfo(self, object, info):
        """Set the version control information associated with object."""
        object._vc_info = info

    def checkOut(self, object, activity='mainline'):
        """Checkout"""

        # First, make sure object is not already under version control.
        if not self.isUnderVersionControl(object):
            raise 

        # Check for semantic conflicts
        # xxx

        vinfo = self.getVersionInfo(object)
        status = vinfo.getResourceStatus()
        if status == 'checked-out':
            raise CheckOutError(
                'The selected resource is already checked out.'
                )
        repository_id = vinfo.getRepositoryId()
        repository = self.getRepository(repository_id)
        history_id = vinfo.getVersionHistoryId()
        history = repository.getVersionHistory(history_id)
        version_id = vinfo.getSourceVersionId()
        version = history.getVersion(version_id)


        # These assume linear versioning!
        if history.lastVersionId() != version_id:
            raise CheckOutError(
                'The current resource does not reflect the latest version!'
                )

        co_record = history.getCurrentCheckout(activity)
        if co_record is not None:
            raise CheckOutError(
                'The resource is already checked out by %s at %s.' % (
                co_record.getUserName(), co_record.getTargetPath()
                ))
        object_path = self._getObjectPath(object)
        username = self._findUserName()

        history.registerCheckout(activity, version_id, object_path, username)

        version.addMessageEntry('checkout',
                                self._findUserName(),
                                self._getObjectPath(object),
                                'Resource checked out.'
                                )

        # note - checkout info wants to have more metadata
        vinfo.setResourceStatus('checked-out')
        return object

    def checkIn(self, object, message=''):
        """Checkin"""

        activity = 'mainline'

        # First, make sure object is not already under version control.
        if not self.isUnderVersionControl(object):
            raise 

        # Check for semantic conflicts
        # xxx

        vinfo = self.getVersionInfo(object)
        status = vinfo.getResourceStatus()
        if status == 'checked-in':
            raise CheckInError(
                'The selected resource is already checked in.'
                )
        repository_id = vinfo.getRepositoryId()
        repository = self.getRepository(repository_id)
        history_id = vinfo.getVersionHistoryId()
        history = repository.getVersionHistory(history_id)
        last_version_id = vinfo.getSourceVersionId()
        last_version = history.getVersion(last_version_id)

        # This assumes linear versioning.
        if history.lastVersionId() != last_version_id:
            raise CheckInError(
                'The current resource is not up to date.'
                )

        # Create new version and update the versioning information.
        version = history.createVersion(object)
        version.addMessageEntry('checkin',
                                self._findUserName(),
                                self._getObjectPath(object),
                                message
                                )

        history.unregisterCheckout(activity)

        vinfo.setSourceVersionId(version.getId())
        vinfo.setResourceStatus('checked-in')
        vinfo.setVersionPath(self._getObjectPath(version))
        return object

    def unCheckOut(self, object):
        """Revert to last checked-in version."""
        activity = 'mainline'
        # First, make sure object is not already under version control.
        if not self.isUnderVersionControl(object):
            raise 

        # Check for semantic conflicts
        # xxx

        vinfo = self.getVersionInfo(object)
        status = vinfo.getResourceStatus()
        if status == 'checked-in':
            raise CheckInError(
                'The selected resource is already checked in.'
                )
        repository_id = vinfo.getRepositoryId()
        repository = self.getRepository(repository_id)
        history_id = vinfo.getVersionHistoryId()
        history = repository.getVersionHistory(history_id)
        version_id = vinfo.getSourceVersionId()
        version = history.getVersion(version_id)

        new_object = version.copyState()

        # Set versioning information on the version-controlled object.
        new_info = vinfo.clone()
        vinfo.setResourceStatus('checked-in')
        vinfo.setSourceVersionId(version.getId())
        vinfo.setVersionPath(self._getObjectPath(version))
        self.setVersionInfo(new_object, vinfo)

        # Re-seat the reverted object in its container. Returns the new
        # correctly wrapped object.
        new_object = self.replaceObject(object, new_object)

        version.addMessageEntry('uncheckout',
                                self._findUserName(),
                                self._getObjectPath(object),
                                'Reverted working copy.'
                                )

        history.unregisterCheckout(activity)

        return new_object


    def updateResource(self, object, version_id=None):
        """ """
        # First, make sure object is not already under version control.
        if not self.isUnderVersionControl(object):
            raise 

        # Check for semantic conflicts
        # xxx

        vinfo = self.getVersionInfo(object)
        status = vinfo.getResourceStatus()
        if status != 'checked-in':
            # This would cause lost changes.
            raise CheckInError(
                'The selected resource is already checked in.'
                )
        repository_id = vinfo.getRepositoryId()
        repository = self.getRepository(repository_id)
        history_id = vinfo.getVersionHistoryId()
        history = repository.getVersionHistory(history_id)
        if version_id is None:
            version_id = history.lastVersionId()

        # Short-circuit if update is to the current checked in version.
        cur_ver = vinfo.getSourceVersionId()
        if version_id == cur_ver:
            return object
        
        version = history.getVersion(version_id)

        new_object = version.copyState()

        # Set versioning information on the version-controlled object.
        new_info = vinfo.clone()
        vinfo.setResourceStatus('checked-in')
        vinfo.setSourceVersionId(version_id)
        vinfo.setVersionPath(self._getObjectPath(version))
        self.setVersionInfo(new_object, vinfo)

        # Re-seat the reverted object in its container. Returns the new
        # correctly wrapped object.
        new_object = self.replaceObject(object, new_object)

        version.addMessageEntry('update',
                                self._findUserName(),
                                self._getObjectPath(object),
                                'Updated resource to version %s.' % version_id
                                )
        return new_object


    def isObjectUpToDate(self):
        """ """
        pass

    def _getObjectPath(self, object):
        path = object.getPhysicalPath()
        return string.join(path, '/')

    def _findUserName(self):
        user = AccessControl.getSecurityManager().getUser()
        return user.getUserName()
    
    def getAutoVersion(self):
        return 'auto versioning settings'

    def getSourceVersionId(self, object):
        """Return the version of the resource that this object represents."""
        return self.getVersionInfo(object).getSourceVersionId()

    def getAvailableVersionIds(self, object):
        """ """
        vinfo = self.getVersionInfo(object)
        repository_id = vinfo.getRepositoryId()
        repository = self.getRepository(repository_id)
        history_id = vinfo.getVersionHistoryId()
        history = repository.getVersionHistory(history_id)
        return history.getVersionIds()

    def getAllMessageEntries(self, object):
        """ """
        vinfo = self.getVersionInfo(object)
        repository_id = vinfo.getRepositoryId()
        repository = self.getRepository(repository_id)
        history_id = vinfo.getVersionHistoryId()
        history = repository.getVersionHistory(history_id)
        return history.getAllMessageEntries()

    def replaceObject(self, object, new_object):
        # Note - this is probably not right, which is why I made it a
        # separate method.
        container = Acquisition.aq_parent(Acquisition.aq_inner(object))
        item_id = object.getId()
        container._delObject(item_id)
        container._setObject(item_id, new_object)
        return container._getOb(item_id)

InitializeClass(VersionControl)





class CheckOutError(Exception):
    pass

class CheckInError(Exception):
    pass


_VersionInfo = None

def VersionInfo(object):
    global _VersionInfo
    if _VersionInfo is None:
        import Products.ZopeVersionControl.Utility
        _VersionInfo = Products.ZopeVersionControl.Utility.VersionInfo
    return _VersionInfo(object)


=== Added File Packages/VersionControl/VersionSupport.py ===
__version__='$Revision: 1.1 $'[11:-2]

import ExtensionClass, AccessControl, Acquisition
from Globals import DTMLFile, InitializeClass
from VersionControl import VersionControl


def _isAVersionableResource(object):
    if hasattr(object, '__non_versionable__'):
        return 0
    return 1

class VersionSupport(ExtensionClass.Base):
    """Mixin class to support version control."""

    manage_options=(
        {'label': 'Version Control', 'action':'vcPropertiesForm',
         'help':  ('OFSP', 'Security.stx'),
         'filter': _isAVersionableResource,
         },
        )

    security = AccessControl.ClassSecurityInfo()


    security.declareProtected('View management screens',
                              'vcPropertiesForm')
    vcPropertiesForm = DTMLFile('dtml/vcPropertiesForm', globals())

    security.declareProtected('Change vc properties', 'vcChangeProperties')
    def vcChangeProperties(self, REQUEST=None):
        """Change version control properties."""
        if REQUEST is not None:
            message="Saved changes."
            return self.vcPropertiesForm(
                self, REQUEST,
                manage_tabs_message=message
                )


    security.declareProtected('View management screens',
                              'vcVersionControlForm')
    vcVersionControlForm = DTMLFile('dtml/vcVersionControlForm', globals())

    security.declareProtected('Change vc properties', 'vcVersionControl')
    def vcVersionControl(self, description, repository_id, use_auto=0,
                         REQUEST=None):
        """Place object under version control."""
        vc = VersionControl(self)

        # Note - catch exceptions here later.
        vc.versionControl(self, repository_id, description)

        if REQUEST is not None:
            message="This object has been placed under version control."
            return self.vcPropertiesForm(
                self, REQUEST,
                manage_tabs_message=message
                )


    security.declareProtected('Use version control', 'vcCheckOut')
    def vcCheckOut(self, REQUEST=None):
        """Checkout object."""
        vc = VersionControl(self)

        # Note - catch exceptions here later.
        vc.checkOut(self)

        if REQUEST is not None:
            message="This object has been checked out."
            return self.vcPropertiesForm(
                self, REQUEST,
                manage_tabs_message=message
                )

    security.declareProtected('Use version control', 'vcCheckIn')
    def vcCheckIn(self, message='', REQUEST=None):
        """Checkin object."""
        vc = VersionControl(self)

        # Note - catch exceptions here later.
        vc.checkIn(self, message)
        new_ver = vc.getVersionInfo(self).getSourceVersionId()
        if REQUEST is not None:
            message="This object has been checked in [version %s]." % new_ver
            return self.vcPropertiesForm(
                self, REQUEST,
                manage_tabs_message=message
                )



    security.declareProtected('Use version control', 'vcCheckOut')
    def vcUnCheckOut(self, REQUEST=None):
        """Uncheckout object."""
        vc = VersionControl(self)

        # Note - catch exceptions here later.
        newself = vc.unCheckOut(self)

        ver_id = vc.getVersionInfo(newself).getSourceVersionId()

        if REQUEST is not None:
            message="This object has been reverted to version %s." % ver_id
            return newself.vcPropertiesForm(
                newself, REQUEST,
                manage_tabs_message=message
                )

    security.declareProtected('Use version control', 'vcUpdateResource')
    def vcUpdateResource(self, version_id, REQUEST=None):
        """ """
        vc = VersionControl(self)

        # Note - catch exceptions here later.
        if version_id == 'latest':
            version_id = None
        newself = vc.updateResource(self, version_id)
        new_ver = vc.getVersionInfo(self).getSourceVersionId()
        if REQUEST is not None:
            message="This object has been updated to version %s." % new_ver
            return newself.vcPropertiesForm(
                newself, REQUEST,
                manage_tabs_message=message
                )

    def isUnderVersionControl(self):
        """Return true if object is under version control."""
        return VersionControl(self).isUnderVersionControl(self)

    def getVersionInfo(self):
        """ """
        return VersionControl(self).getVersionInfo(self)

    def getAvailableVersionIds(self):
        """ """
        return VersionControl(self).getAvailableVersionIds(self)

    def getRepositoryIds(self):
        """Return a list of valid repository ids."""
        return VersionControl(self).getRepositoryIds()

    security.declareProtected('View management screens',
                              'vcActivityLog')
    vcActivityLog = DTMLFile('dtml/vcActivityLog', globals())

    def getAllMessageEntries(self):
        """ """
        return VersionControl(self).getAllMessageEntries(self)

    unVC__roles__ = None
    def unVC(self, REQUEST):
        """ """
        del self._vc_info
        return 'ok'



InitializeClass(VersionSupport)




=== Added File Packages/VersionControl/__init__.py ===
""" """

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