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
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
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
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
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
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
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.')