Back to index

plone3  3.1.7
Public Member Functions | Static Public Attributes | Private Attributes
ZopeVersionControl.Repository.Repository Class Reference
Inheritance diagram for ZopeVersionControl.Repository.Repository:
Inheritance graph
[legend]
Collaboration diagram for ZopeVersionControl.Repository.Repository:
Collaboration graph
[legend]

List of all members.

Public Member Functions

def __init__
def createVersionHistory
def getVersionHistory
def replaceState
def isAVersionableResource
 This is the implementation of the public version control interface.
def isUnderVersionControl
def isResourceUpToDate
def isResourceChanged
def getVersionInfo
def applyVersionControl
def checkoutResource
def checkinResource
def uncheckoutResource
def updateResource
def labelResource
def makeActivity
def getVersionOfResource
def getVersionIds
def getLabelsForResource
def getLogEntries

Static Public Attributes

tuple security = ClassSecurityInfo()

Private Attributes

 _branches
 _labels
 _histories
 _created

Detailed Description

The repository implementation manages the actual data of versions
   and version histories. It does not handle user interface issues.

Definition at line 34 of file Repository.py.


Constructor & Destructor Documentation

Definition at line 38 of file Repository.py.

00038 
00039     def __init__(self):
00040         # These keep track of symbolic label and branch names that
00041         # have been used to ensure that they don't collide.
00042         self._branches = OIBTree()
00043         self._branches['mainline'] = 1
00044         self._labels = OIBTree()
00045 
00046         self._histories = OOBTree()
00047         self._created = time.time()


Member Function Documentation

def ZopeVersionControl.Repository.Repository.applyVersionControl (   self,
  object,
  message = None 
)

Definition at line 146 of file Repository.py.

00146 
00147     def applyVersionControl(self, object, message=None):
00148         if self.isUnderVersionControl(object):
00149             raise VersionControlError(
00150                 'The resource is already under version control.'
00151                 )
00152         if not self.isAVersionableResource(object):
00153             raise VersionControlError(
00154                 'This resource cannot be put under version control.'
00155                 )
00156 
00157         # Need to check the parent to see if the container of the object
00158         # being put under version control is itself a version-controlled
00159         # object. If so, we need to use the branch id of the container.
00160         branch = 'mainline'
00161         parent = aq_parent(aq_inner(object))
00162         p_info = getattr(parent, '__vc_info__', None)
00163         if p_info is not None:
00164             sticky = p_info.sticky
00165             if sticky and sticky[0] == 'B':
00166                 branch = sticky[1]
00167 
00168         # Create a new version history and initial version object.
00169         history = self.createVersionHistory(object)
00170         version = history.createVersion(object, branch)
00171 
00172         history_id = history.getId()
00173         version_id = version.getId()
00174 
00175         # Add bookkeeping information to the version controlled object.
00176         info = VersionInfo(history_id, version_id, VersionInfo.CHECKED_IN)
00177         if branch != 'mainline':
00178             info.sticky = ('B', branch)
00179         object.__vc_info__ = info
00180 
00181         # Save an audit record of the action being performed.
00182         history.addLogEntry(version_id,
00183                             LogEntry.ACTION_CHECKIN,
00184                             _findPath(object),
00185                             message is None and 'Initial checkin.' or message
00186                             )
00187         return object

Here is the call graph for this function:

def ZopeVersionControl.Repository.Repository.checkinResource (   self,
  object,
  message = '' 
)

Definition at line 224 of file Repository.py.

00224 
00225     def checkinResource(self, object, message=''):
00226         info = self.getVersionInfo(object)
00227         if info.status != info.CHECKED_OUT:
00228             raise VersionControlError(
00229                 'The selected resource is not checked out.'
00230                 )
00231 
00232         if info.sticky and info.sticky[0] != 'B':
00233             raise VersionControlError(
00234                 'The selected resource has been updated to a particular '
00235                 'version, label or date. The resource must be updated to '
00236                 'the mainline or a branch before it may be checked in.'
00237                 )
00238 
00239         if not self.isResourceUpToDate(object):
00240             raise VersionControlError(
00241                 'The selected resource is not up to date!'
00242                 )
00243 
00244         history = self.getVersionHistory(info.history_id)
00245         ob_path = _findPath(object)
00246 
00247         branch = 'mainline'
00248         if info.sticky is not None and info.sticky[0] == 'B':
00249             branch = info.sticky[1]
00250 
00251         version = history.createVersion(object, branch)
00252 
00253         # Save an audit record of the action being performed.
00254         history.addLogEntry(version.getId(),
00255                             LogEntry.ACTION_CHECKIN,
00256                             ob_path,
00257                             message
00258                             )
00259 
00260         # Update bookkeeping information.
00261         newinfo = info.clone()
00262         newinfo.version_id = version.getId()
00263         newinfo.status = newinfo.CHECKED_IN
00264         object.__vc_info__ = newinfo
00265         return object

Here is the call graph for this function:

Definition at line 189 of file Repository.py.

00189 
00190     def checkoutResource(self, object):
00191         info = self.getVersionInfo(object)
00192         if info.status != info.CHECKED_IN:
00193             raise VersionControlError(
00194                 'The selected resource is already checked out.'
00195                 )
00196 
00197         if info.sticky and info.sticky[0] != 'B':
00198             raise VersionControlError(
00199                 'The selected resource has been updated to a particular '
00200                 'version, label or date. The resource must be updated to '
00201                 'the mainline or a branch before it may be checked out.'
00202                 )
00203 
00204         if not self.isResourceUpToDate(object):
00205             raise VersionControlError(
00206                 'The selected resource is not up to date!'
00207                 )
00208 
00209         history = self.getVersionHistory(info.history_id)
00210         ob_path = _findPath(object)
00211 
00212         # Save an audit record of the action being performed.
00213         history.addLogEntry(info.version_id,
00214                             LogEntry.ACTION_CHECKOUT,
00215                             ob_path
00216                             )
00217 
00218         # Update bookkeeping information.
00219         newinfo = info.clone()
00220         newinfo.status = newinfo.CHECKED_OUT
00221         object.__vc_info__ = newinfo
00222         return object

Here is the call graph for this function:

Internal: create a new version history for a resource.

Definition at line 51 of file Repository.py.

00051 
00052     def createVersionHistory(self, object):
00053         """Internal: create a new version history for a resource."""
00054         # When one creates the first version in a version history, neither
00055         # the version or version history yet have a _p_jar, which causes
00056         # copy operations to fail. To work around that, we share our _p_jar.
00057         history_id = None
00058         while history_id is None or self._histories.has_key(history_id):
00059             history_id = str(randint(1, 9999999999))
00060         history = ZopeVersionHistory(history_id, object)
00061         self._histories[history_id] = history
00062         return history.__of__(self)

Here is the caller graph for this function:

Definition at line 477 of file Repository.py.

00477 
00478     def getLabelsForResource(self, object):
00479         info = self.getVersionInfo(object)
00480         history = self.getVersionHistory(info.history_id)
00481         return history.getLabels()

Here is the call graph for this function:

Definition at line 483 of file Repository.py.

00483 
00484     def getLogEntries(self, object):
00485         info = self.getVersionInfo(object)
00486         history = self.getVersionHistory(info.history_id)
00487         return history.getLogEntries()
00488 
00489 InitializeClass(Repository)

Here is the call graph for this function:

Internal: return a version history given a version history id.

Definition at line 64 of file Repository.py.

00064 
00065     def getVersionHistory(self, history_id):
00066         """Internal: return a version history given a version history id."""
00067         return self._histories[history_id].__of__(self)

Here is the caller graph for this function:

Definition at line 471 of file Repository.py.

00471 
00472     def getVersionIds(self, object):
00473         info = self.getVersionInfo(object)
00474         history = self.getVersionHistory(info.history_id)
00475         return history.getVersionIds()

Here is the call graph for this function:

Definition at line 137 of file Repository.py.

00137 
00138     def getVersionInfo(self, object):
00139         info = getattr(object, '__vc_info__', None)
00140         if info is not None:
00141             return info
00142         raise VersionControlError(
00143             'The specified resource is not under version control.'
00144             )

Here is the caller graph for this function:

def ZopeVersionControl.Repository.Repository.getVersionOfResource (   self,
  history_id,
  selector 
)

Definition at line 433 of file Repository.py.

00433 
00434     def getVersionOfResource(self, history_id, selector):
00435         history = self.getVersionHistory(history_id)
00436         sticky = None
00437 
00438         if not selector or selector == 'mainline':
00439             version = history.getLatestVersion('mainline')
00440         else:
00441             if history.hasVersionId(selector):
00442                 version = history.getVersionById(selector)
00443                 sticky = ('V', selector)
00444 
00445             elif self._labels.has_key(selector):
00446                 version = history.getVersionByLabel(selector)
00447                 sticky = ('L', selector)
00448 
00449             elif self._branches.has_key(selector):
00450                 version = history.getLatestVersion(selector)
00451                 sticky = ('B', selector)
00452             else:
00453                 try: date = DateTime(selector)
00454                 except:
00455                     raise VersionControlError(
00456                         'Invalid version selector: %s' % selector
00457                         )
00458                 else:
00459                     timestamp = date.timeTime()
00460                     sticky = ('D', timestamp)
00461                     version = history.getVersionByDate('mainline', timestamp)
00462 
00463         object = version.copyState()
00464 
00465         info = VersionInfo(history_id, version.getId(), VersionInfo.CHECKED_IN)
00466         if sticky is not None:
00467             info.sticky = sticky
00468         object.__vc_info__ = info
00469         return object

Here is the call graph for this function:

This is the implementation of the public version control interface.

Definition at line 98 of file Repository.py.

00098 
00099     def isAVersionableResource(self, obj):
00100         # For now, an object must be persistent (have its own db record)
00101         # in order to be considered a versionable resource.
00102         return isAVersionableResource(obj)

Here is the caller graph for this function:

Definition at line 123 of file Repository.py.

00123 
00124     def isResourceChanged(self, object):
00125         # Return true if the state of a resource has changed in a transaction
00126         # *after* the version bookkeeping was saved. Note that this method is
00127         # not appropriate for detecting changes within a transaction!
00128         info = self.getVersionInfo(object)
00129         itime = getattr(info, '_p_mtime', None)
00130         if itime is None:
00131             return 0
00132         mtime = Utility._findModificationTime(object)
00133         if mtime is None:
00134             return 0
00135         return mtime > itime

Here is the call graph for this function:

def ZopeVersionControl.Repository.Repository.isResourceUpToDate (   self,
  object,
  require_branch = 0 
)

Definition at line 108 of file Repository.py.

00108 
00109     def isResourceUpToDate(self, object, require_branch=0):
00110         info = self.getVersionInfo(object)
00111         history = self.getVersionHistory(info.history_id)
00112         branch = 'mainline'
00113         if info.sticky:
00114             if info.sticky[0] == 'B':
00115                 branch = info.sticky[1]
00116             elif require_branch:
00117                 # The object is updated to a particular version
00118                 # rather than a branch.  The caller
00119                 # requires a branch.
00120                 return 0
00121         return history.isLatestVersion(info.version_id, branch)

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 104 of file Repository.py.

00104 
00105     def isUnderVersionControl(self, object):
00106         return hasattr(object, '__vc_info__')

Here is the caller graph for this function:

def ZopeVersionControl.Repository.Repository.labelResource (   self,
  object,
  label,
  force = 0 
)

Definition at line 380 of file Repository.py.

00380 
00381     def labelResource(self, object, label, force=0):
00382         info = self.getVersionInfo(object)
00383         if info.status != info.CHECKED_IN:
00384             raise VersionControlError(
00385                 'The selected resource must be checked in to be labeled.'
00386                 )
00387 
00388         # Make sure that labels and branch ids do not collide.
00389         if self._branches.has_key(label) or label == 'mainline':
00390             raise VersionControlError(
00391                 'The label value given is already in use as an activity id.'
00392                 )
00393         if not self._labels.has_key(label):
00394             self._labels[label] = 1
00395 
00396         history = self.getVersionHistory(info.history_id)
00397         history.labelVersion(info.version_id, label, force)
00398         return object

Here is the call graph for this function:

def ZopeVersionControl.Repository.Repository.makeActivity (   self,
  object,
  branch_id 
)

Definition at line 400 of file Repository.py.

00400 
00401     def makeActivity(self, object, branch_id):
00402         # Note - this is not part of the official version control API yet.
00403         # It is here to allow unit testing of the architectural aspects
00404         # that are already in place to support activities in the future.
00405 
00406         info = self.getVersionInfo(object)
00407         if info.status != info.CHECKED_IN:
00408             raise VersionControlError(
00409                 'The selected resource must be checked in.'
00410                 )
00411 
00412         branch_id = branch_id or None
00413 
00414         # Make sure that activity ids and labels do not collide.
00415         if self._labels.has_key(branch_id) or branch_id == 'mainline':
00416             raise VersionControlError(
00417                 'The value given is already in use as a version label.'
00418                 )
00419 
00420         if not self._branches.has_key(branch_id):
00421             self._branches[branch_id] = 1
00422 
00423         history = self.getVersionHistory(info.history_id)
00424 
00425         if history._branches.has_key(branch_id):
00426             raise VersionControlError(
00427                 'The resource is already associated with the given activity.'
00428                 )
00429 
00430         history.createBranch(branch_id, info.version_id)
00431         return object

Here is the call graph for this function:

def ZopeVersionControl.Repository.Repository.replaceState (   self,
  obj,
  new_state 
)
Internal: replace the state of a persistent object.

Definition at line 69 of file Repository.py.

00069 
00070     def replaceState(self, obj, new_state):
00071         """Internal: replace the state of a persistent object.
00072         """
00073         non_versioned = getNonVersionedData(obj)
00074         # XXX There ought to be some way to do this more cleanly.
00075         # This fills the __dict__ of the old object with new state.
00076         # The other way to achieve the desired effect is to replace
00077         # the object in its container, but this method preserves the
00078         # identity of the object.
00079         if obj.__class__ is not new_state.__class__:
00080             raise VersionControlError(
00081                 "The class of the versioned object has changed. %s != %s"
00082                 % (repr(obj.__class__, new_state.__class__)))
00083         obj._p_changed = 1
00084         for key in obj.__dict__.keys():
00085             if not new_state.__dict__.has_key(key):
00086                 del obj.__dict__[key]
00087         for key, value in new_state.__dict__.items():
00088             obj.__dict__[key] = value
00089         if non_versioned:
00090             # Restore the non-versioned data into the new state.
00091             restoreNonVersionedData(obj, non_versioned)
00092         return obj

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 267 of file Repository.py.

00267 
00268     def uncheckoutResource(self, object):
00269         info = self.getVersionInfo(object)
00270         if info.status != info.CHECKED_OUT:
00271             raise VersionControlError(
00272                 'The selected resource is not checked out.'
00273                 )
00274 
00275         history = self.getVersionHistory(info.history_id)
00276         ob_path = _findPath(object)
00277 
00278         version = history.getVersionById(info.version_id)
00279         new_obj = version.copyState()
00280 
00281         # Save an audit record of the action being performed.
00282         history.addLogEntry(info.version_id,
00283                             LogEntry.ACTION_UNCHECKOUT,
00284                             ob_path
00285                             )
00286 
00287         # Replace the state of the object with a reverted state.
00288         new_obj = self.replaceState(object, new_obj)
00289 
00290         # Update bookkeeping information.
00291         newinfo = info.clone()
00292         newinfo.version_id = version.getId()
00293         newinfo.status = newinfo.CHECKED_IN
00294         new_obj.__vc_info__ = newinfo
00295         return new_obj

Here is the call graph for this function:

def ZopeVersionControl.Repository.Repository.updateResource (   self,
  object,
  selector = None 
)

Definition at line 297 of file Repository.py.

00297 
00298     def updateResource(self, object, selector=None):
00299         info = self.getVersionInfo(object)
00300         if info.status != info.CHECKED_IN:
00301             raise VersionControlError(
00302                 'The selected resource must be checked in to be updated.'
00303                 )
00304 
00305         history = self.getVersionHistory(info.history_id)
00306         version = None
00307         sticky = info.sticky
00308 
00309         if not selector:
00310             # If selector is null, update to the latest version taking any
00311             # sticky attrs into account (branch, date). Note that the sticky
00312             # tag could also be a date or version id. We don't bother checking
00313             # for those, since in both cases we do nothing (because we'll
00314             # always be up to date until the sticky tag changes).
00315             if sticky and sticky[0] == 'L':
00316                 # A label sticky tag, so update to that label (since it is
00317                 # possible, but unlikely, that the label has been moved).
00318                 version = history.getVersionByLabel(sticky[1])
00319             elif sticky and sticky[0] == 'B':
00320                 # A branch sticky tag. Update to latest version on branch.
00321                 version = history.getLatestVersion(selector)
00322             else:
00323                 # Update to mainline, forgetting any date or version id
00324                 # sticky tag that was previously associated with the object.
00325                 version = history.getLatestVersion('mainline')
00326                 sticky = None
00327         else:
00328             # If the selector is non-null, we find the version specified
00329             # and update the sticky tag. Later we'll check the version we
00330             # found and decide whether we really need to update the object.
00331             if history.hasVersionId(selector):
00332                 version = history.getVersionById(selector)
00333                 sticky = ('V', selector)
00334 
00335             elif self._labels.has_key(selector):
00336                 version = history.getVersionByLabel(selector)
00337                 sticky = ('L', selector)
00338 
00339             elif self._branches.has_key(selector):
00340                 version = history.getLatestVersion(selector)
00341                 if selector == 'mainline':
00342                     sticky = None
00343                 else:
00344                     sticky = ('B', selector)
00345             else:
00346                 try:    date = DateTime(selector)
00347                 except:
00348                     raise VersionControlError(
00349                         'Invalid version selector: %s' % selector
00350                         )
00351                 else:
00352                     timestamp = date.timeTime()
00353                     sticky = ('D', timestamp)
00354                     # Fix!
00355                     branch = history.findBranchId(info.version_id)
00356                     version = history.getVersionByDate(branch, timestamp)
00357 
00358         # If the state of the resource really needs to be changed, do the
00359         # update and make a log entry for the update.
00360         version_id = version and version.getId() or info.version_id
00361         new_object = object
00362         if version and (version_id != info.version_id):
00363             new_object = version.copyState()
00364             new_object = self.replaceState(object, new_object)
00365 
00366             history.addLogEntry(version_id,
00367                                 LogEntry.ACTION_UPDATE,
00368                                 _findPath(new_object)
00369                                 )
00370 
00371         # Update bookkeeping information.
00372         newinfo = info.clone(1)
00373         newinfo.version_id = version_id
00374         newinfo.status = newinfo.CHECKED_IN
00375         if sticky is not None:
00376             newinfo.sticky = sticky
00377         new_object.__vc_info__ = newinfo
00378         return new_object

Here is the call graph for this function:


Member Data Documentation

Definition at line 41 of file Repository.py.

Definition at line 46 of file Repository.py.

Definition at line 45 of file Repository.py.

Definition at line 43 of file Repository.py.

tuple ZopeVersionControl.Repository.Repository.security = ClassSecurityInfo() [static]

Reimplemented in ZopeVersionControl.ZopeRepository.ZopeRepository.

Definition at line 48 of file Repository.py.


The documentation for this class was generated from the following file: