def getLogEntries(self, obj, only_checkins=0): """Returns the log entries for an object as a sequence of mappings. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() if not repo.isUnderVersionControl(obj): return [] entries = repo.getLogEntries(obj) res = [] for entry in entries: a = entry.action if a == entry.ACTION_CHECKOUT: action = 'checkout' elif a == entry.ACTION_CHECKIN: action = 'checkin' elif a == entry.ACTION_UNCHECKOUT: action = 'uncheckout' elif a == entry.ACTION_UPDATE: action = 'update' else: action = '?' if only_checkins and action != 'checkin': continue res.append({ 'timestamp': entry.timestamp, 'version_id': entry.version_id, 'action': action, 'message': entry.message, 'user_id': entry.user_id, 'path': entry.path, }) return res
def unlock(self, obj, message=''): """Unlocks an object. """ verifyPermission(UnlockObjects, obj) locker = self.locker(obj) if not locker: raise LockingError, ("Unlocking an unlocked item: %s" % pathOf(obj)) user = getSecurityManager().getUser() if user.getId() != locker: raise LockingError, ("Cannot unlock %s: lock is held by %s" % (pathOf(obj), locker)) # According to WriteLockInterface, we shouldn't call # wl_clearLocks(), but it seems like the right thing to do anyway. obj.wl_clearLocks() if self.auto_version: vt = getToolByName(self, 'portal_versions', None) if vt is not None: if (vt.isUnderVersionControl(obj) and vt.isCheckedOut(obj)): vt.checkin(obj, message) self.noteUnlock(obj, locker)
def getHistoryId(self, obj): """Returns the version history ID of the object. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() return repo.getVersionInfo(obj).history_id
def checkin(self, obj, message=None): """Checks in a new version. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() if not repo.isUnderVersionControl(obj): repo.applyVersionControl(obj, message) else: if (not repo.isResourceUpToDate(obj, require_branch=1) and self.isCheckedOut(obj)): # This is a strange state, but it can be fixed. # Revert the object to the branch, replace the # reverted state with the new state, and check in. new_dict = obj.__dict__.copy() # Uncheckout obj = repo.uncheckoutResource(obj) info = repo.getVersionInfo(obj) obj = repo.updateResource(obj, self._getBranchName(info)) # Checkout obj = repo.checkoutResource(obj) # Restore the new state for key in obj.__dict__.keys(): if key != '__vc_info__': if not new_dict.has_key(key): del obj.__dict__[key] for key, value in new_dict.items(): if key != '__vc_info__': obj.__dict__[key] = value repo.checkinResource(obj, message or '') return None
def getHistoryId(self, obj): """Returns the version history ID of the object. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() return repo.getVersionInfo(obj).history_id
def getLogEntries(self, obj, only_checkins=0): """Returns the log entries for an object as a sequence of mappings. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() if not repo.isUnderVersionControl(obj): return [] entries = repo.getLogEntries(obj) res = [] for entry in entries: a = entry.action if a == entry.ACTION_CHECKOUT: action = 'checkout' elif a == entry.ACTION_CHECKIN: action = 'checkin' elif a == entry.ACTION_UNCHECKOUT: action = 'uncheckout' elif a == entry.ACTION_UPDATE: action = 'update' else: action = '?' if only_checkins and action != 'checkin': continue res.append({'timestamp': entry.timestamp, 'version_id': entry.version_id, 'action': action, 'message': entry.message, 'user_id': entry.user_id, 'path': entry.path, }) return res
def checkin(self, obj, message=None): """Checks in a new version. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() if not repo.isUnderVersionControl(obj): repo.applyVersionControl(obj, message) else: if (not repo.isResourceUpToDate(obj, require_branch=1) and self.isCheckedOut(obj)): # This is a strange state, but it can be fixed. # Revert the object to the branch, replace the # reverted state with the new state, and check in. new_dict = obj.__dict__.copy() # Uncheckout obj = repo.uncheckoutResource(obj) info = repo.getVersionInfo(obj) obj = repo.updateResource(obj, self._getBranchName(info)) # Checkout obj = repo.checkoutResource(obj) # Restore the new state for key in obj.__dict__.keys(): if key != '__vc_info__': if not new_dict.has_key(key): del obj.__dict__[key] for key, value in new_dict.items(): if key != '__vc_info__': obj.__dict__[key] = value repo.checkinResource(obj, message or '') return None
def unlock(self, obj, message=''): """Unlocks an object. """ verifyPermission(UnlockObjects, obj) locker = self.locker(obj) if not locker: raise LockingError, ("Unlocking an unlocked item: %s" % pathOf(obj)) user = getSecurityManager().getUser() if user.getId() != locker: raise LockingError, ("Cannot unlock %s: lock is held by %s" % (pathOf(obj), locker)) # According to WriteLockInterface, we shouldn't call # wl_clearLocks(), but it seems like the right thing to do anyway. obj.wl_clearLocks() if self.auto_version: vt = getToolByName(self, 'portal_versions', None) if vt is not None: if (vt.isUnderVersionControl(obj) and vt.isCheckedOut(obj)): vt.checkin(obj, message) self.noteUnlock(obj, locker)
def getVersionIds(self, obj): """Returns the version IDs of all revisions for an object. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() ids = repo.getVersionIds(obj) ids = map(int, ids) ids.sort() return map(str, ids)
def getVersionIds(self, obj): """Returns the version IDs of all revisions for an object. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() ids = repo.getVersionIds(obj) ids = map(int, ids) ids.sort() return map(str, ids)
def checkContainers(self, obj, stages): """Verifies that the container exists on the given stages. If the container is missing on one of the stages, an exception is raised. """ verifyPermission(StageObjects, obj) containers = self._getObjectStages(obj, get_container=1) self._checkContainers(obj, stages, containers) return 1
def updateStages2(self, obj, to_stages, message=''): """Updates objects to match the version in the source stage. """ verifyPermission(StageObjects, obj) from_stage = self.getStageOf(obj) if from_stage is None: raise StagingError("Object %s is not in any stage" % '/'.join(obj.getPhysicalPath())) if from_stage in to_stages or not to_stages: raise StagingError("Invalid to_stages parameter") if aq_base(unproxied(obj)) is not aq_base(obj): ref = obj.__dict__.get("_Proxy__reference") if ref is None: # Carefully wrap an *un*proxied version of obj in the same # context: IAW = ImplicitAcquisitionWrapper obj = IAW(unproxied(obj), aq_parent(aq_inner(obj))) proxy = None else: # obj is a proxy. Find the wrapped target and update that # instead of the reference. Note that the reference will # be updated with the container. proxy = obj obj = ref.getTarget(obj) # Decide whether the reference should be staged at the # same time. If the reference is contained in a # non-versioned container, the reference should be staged. # OTOH, if the reference is in a versioned container, # staging the container will create the reference, so the # reference should not be staged by this operation. repo = self._getVersionRepository() if repo.isUnderVersionControl(aq_parent(aq_inner(proxy))): proxy = None else: proxy = None # Check containers first. cmap = self._getObjectStages(obj, get_container=1) self._checkContainers(obj, to_stages, cmap) proxy_cmap = None if proxy is not None: # Check the containers of the reference also. proxy_cmap = self._getObjectStages(proxy, get_container=1) self._checkContainers(proxy, to_stages, proxy_cmap) # Update the stages. if self.auto_checkin: self._autoCheckin(obj, message) self._updateObjectStates(obj, cmap, to_stages) if proxy is not None: # Create and update the reference objects also. self._updateReferences(proxy, proxy_cmap, to_stages)
def breaklock(self, obj, message=''): """Breaks the lock in an emergency. """ locker = self.locker(obj) verifyPermission(UnlockObjects, obj) obj.wl_clearLocks() if self.auto_version: vt = getToolByName(self, 'portal_versions', None) if vt is not None: if (vt.isUnderVersionControl(obj) and vt.isCheckedOut(obj)): vt.checkin(obj, message) if locker: self.noteUnlock(obj, locker)
def removeStages(self, obj, stages): """Removes the copies on the given stages. """ # If the object is a reference or proxy, this removes only the # reference or proxy; this is probably the right thing to do. verifyPermission(StageObjects, obj) object_map = self._getObjectStages(obj) container_map = self._getObjectStages(obj, get_container=1) id = obj.getId() for stage_name, container in container_map.items(): if object_map.get(stage_name) is not None: if container is not None and stage_name in stages: container._delObject(id)
def breaklock(self, obj, message=''): """Breaks the lock in an emergency. """ locker = self.locker(obj) verifyPermission(UnlockObjects, obj) obj.wl_clearLocks() if self.auto_version: vt = getToolByName(self, 'portal_versions', None) if vt is not None: if (vt.isUnderVersionControl(obj) and vt.isCheckedOut(obj)): vt.checkin(obj, message) if locker: self.noteUnlock(obj, locker)
def isStageable(self, obj): """Returns a true value if the object can be staged.""" verifyPermission(StageObjects, obj) repo = self._getVersionRepository() if not repo.isAVersionableResource(unproxied(obj)): return 0 if not getattr(obj, '_stageable', 1): return 0 # An object is stageable only if it is located in one of the stages. portal = aq_parent(aq_inner(self)) for stage_name, stage_title, path in self._stages: stage = self._getStage(portal, path) if stage is not None and obj.aq_inContextOf(stage, 1): return 1 return 0
def revertToVersion(self, obj, version_id): """Reverts the object to the given version. If make_new_revision, a new revision is created, so that the object's state can progress along a new line without making the user deal with branches, labels, etc. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() # Verify the object is under version control. repo.getVersionInfo(obj) if self.isCheckedOut(obj): # Save the current data. self.checkin(obj, 'Auto-saved') repo.updateResource(obj, version_id)
def revertToVersion(self, obj, version_id): """Reverts the object to the given version. If make_new_revision, a new revision is created, so that the object's state can progress along a new line without making the user deal with branches, labels, etc. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() # Verify the object is under version control. repo.getVersionInfo(obj) if self.isCheckedOut(obj): # Save the current data. self.checkin(obj, 'Auto-saved') repo.updateResource(obj, version_id)
def lock(self, obj): """Locks an object. """ verifyPermission(LockObjects, obj) locker = self.locker(obj) if locker: raise LockingError, '%s is already locked' % pathOf(obj) if self.auto_version: vt = getToolByName(self, 'portal_versions', None) if vt is not None: if (vt.isUnderVersionControl(obj) and not vt.isCheckedOut(obj)): vt.checkout(obj) user = getSecurityManager().getUser() lockitem = LockItem(user, timeout=(self.timeout_days * 86400)) obj.wl_setLock(lockitem.getLockToken(), lockitem) self.noteLock(obj, user.getId())
def lock(self, obj): """Locks an object. """ verifyPermission(LockObjects, obj) locker = self.locker(obj) if locker: raise LockingError, '%s is already locked' % pathOf(obj) if self.auto_version: vt = getToolByName(self, 'portal_versions', None) if vt is not None: if (vt.isUnderVersionControl(obj) and not vt.isCheckedOut(obj)): vt.checkout(obj) user = getSecurityManager().getUser() lockitem = LockItem(user, timeout=(self.timeout_days * 86400)) obj.wl_setLock(lockitem.getLockToken(), lockitem) self.noteLock(obj, user.getId())
def checkout(self, obj): """Opens the object for development. Returns the object, which might be different from what was passed to the method if the object was replaced. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() old_state = None if not repo.isUnderVersionControl(obj): repo.applyVersionControl(obj) elif self.auto_copy_forward: if not repo.isResourceUpToDate(obj, require_branch=1): # The object is not at the latest revision or has a # sticky tag. Get it unstuck by copying the old state # forward after the object has been checked out. info = repo.getVersionInfo(obj) old_state = repo.getVersionOfResource( info.history_id, info.version_id) # Momentarily revert to the branch. obj = repo.updateResource(obj, self._getBranchName(info)) obj = repo.checkoutResource(obj) # Copy the old state into the object, minus __vc_info__. # XXX There ought to be some way to do this more cleanly. obj._p_changed = 1 for key in obj.__dict__.keys(): if key != '__vc_info__': if not old_state.__dict__.has_key(key): del obj.__dict__[key] for key, value in old_state.__dict__.items(): if key != '__vc_info__': obj.__dict__[key] = value # Check in as a copy. obj = repo.checkinResource( obj, 'Copied from revision %s' % info.version_id) repo.checkoutResource(obj) return None
def checkout(self, obj): """Opens the object for development. Returns the object, which might be different from what was passed to the method if the object was replaced. """ verifyPermission(UseVersionControl, obj) obj = unproxied(obj) repo = self._getVersionRepository() old_state = None if not repo.isUnderVersionControl(obj): repo.applyVersionControl(obj) elif self.auto_copy_forward: if not repo.isResourceUpToDate(obj, require_branch=1): # The object is not at the latest revision or has a # sticky tag. Get it unstuck by copying the old state # forward after the object has been checked out. info = repo.getVersionInfo(obj) old_state = repo.getVersionOfResource(info.history_id, info.version_id) # Momentarily revert to the branch. obj = repo.updateResource(obj, self._getBranchName(info)) obj = repo.checkoutResource(obj) # Copy the old state into the object, minus __vc_info__. # XXX There ought to be some way to do this more cleanly. obj._p_changed = 1 for key in obj.__dict__.keys(): if key != '__vc_info__': if not old_state.__dict__.has_key(key): del obj.__dict__[key] for key, value in old_state.__dict__.items(): if key != '__vc_info__': obj.__dict__[key] = value # Check in as a copy. obj = repo.checkinResource( obj, 'Copied from revision %s' % info.version_id) repo.checkoutResource(obj) return None
def getVersionIds(self, obj, include_status=0): """Retrieves object version identifiers in the different stages. """ verifyPermission(StageObjects, obj) return self._getObjectVersionIds(obj, include_status)
def getObjectInStage(self, obj, stage_name): """Returns the version of the object in the given stage. """ verifyPermission(StageObjects, obj) stages = self._getObjectStages(obj) return stages[stage_name]