def ProcessSubtabForm(self, post_data, mr): """Process the Rules subtab. Args: post_data: HTML form data for the HTTP request being processed. mr: commonly used info parsed from the request. Returns: The URL of the page to show after processing. """ old_rules = self.services.features.GetFilterRules( mr.cnxn, mr.project_id) rules = filterrules_helpers.ParseRules(mr.cnxn, post_data, self.services.user, mr.errors) new_rules = filterrules_helpers.ParseRules(mr.cnxn, post_data, self.services.user, mr.errors, prefix='new_') rules.extend(new_rules) if not mr.errors.AnyErrors(): config = self.services.features.UpdateFilterRules( mr.cnxn, mr.project_id, rules) if old_rules != rules: logging.info('recomputing derived fields') config = self.services.config.GetProjectConfig( mr.cnxn, mr.project_id) filterrules_helpers.RecomputeAllDerivedFields( mr.cnxn, self.services, mr.project, config) return urls.ADMIN_RULES
def testProcessEditComponent_RenameWithSubComponents(self): subcd_1 = tracker_bizobj.MakeComponentDef(2, self.project.project_id, 'BackEnd>Worker1', 'doc', False, [], [111L], 0, 125L, 3, 126L) subcd_2 = tracker_bizobj.MakeComponentDef(3, self.project.project_id, 'BackEnd>Worker2', 'doc', False, [], [111L], 0, 125L, 4, 127L) self.config.component_defs.extend([subcd_1, subcd_2]) self.mox.StubOutWithMock(filterrules_helpers, 'RecomputeAllDerivedFields') filterrules_helpers.RecomputeAllDerivedFields(self.mr.cnxn, self.services, self.mr.project, self.config) self.mox.ReplayAll() post_data = fake.PostData( leaf_name=['BackEnds'], docstring=['This is where the magic happens'], deprecated=[True], admins=['*****@*****.**'], cc=['*****@*****.**'], labels=['']) self.servlet._ProcessEditComponent(self.mr, post_data, self.config, self.cd) self.mox.VerifyAll() config = self.services.config.GetProjectConfig(self.mr.cnxn, self.mr.project_id) cd = tracker_bizobj.FindComponentDef('BackEnds', config) self.assertEqual('BackEnds', cd.path) subcd_1 = tracker_bizobj.FindComponentDef('BackEnds>Worker1', config) self.assertEqual('BackEnds>Worker1', subcd_1.path) # Assert that creator and modifier have not changed for subcd_1. self.assertEqual(125L, subcd_1.creator_id) self.assertEqual(0, subcd_1.created) self.assertEqual(126L, subcd_1.modifier_id) self.assertEqual(3, subcd_1.modified) subcd_2 = tracker_bizobj.FindComponentDef('BackEnds>Worker2', config) self.assertEqual('BackEnds>Worker2', subcd_2.path) # Assert that creator and modifier have not changed for subcd_2. self.assertEqual(125L, subcd_2.creator_id) self.assertEqual(0, subcd_2.created) self.assertEqual(127L, subcd_2.modifier_id) self.assertEqual(4, subcd_2.modified)
def testRecomputeDerivedFields_Disabled(self): """Servlet should just call RecomputeAllDerivedFieldsNow with no bounds.""" saved_flag = settings.recompute_derived_fields_in_worker settings.recompute_derived_fields_in_worker = False self.mox.ReplayAll() filterrules_helpers.RecomputeAllDerivedFields(self.cnxn, self.services, self.project, self.config) self.assertTrue(self.services.issue.get_all_issues_in_project_called) self.assertTrue(self.services.issue.update_issues_called) self.assertTrue(self.services.issue.enqueue_issues_called) self.mox.VerifyAll() settings.recompute_derived_fields_in_worker = saved_flag
def testRecomputeDerivedFields_NoIssues(self): """Servlet should not call because there is no work to do.""" saved_flag = settings.recompute_derived_fields_in_worker settings.recompute_derived_fields_in_worker = True self.mox.ReplayAll() filterrules_helpers.RecomputeAllDerivedFields(self.cnxn, self.services, self.project, self.config) self.assertFalse(self.services.issue.get_all_issues_in_project_called) self.assertFalse(self.services.issue.update_issues_called) self.assertFalse(self.services.issue.enqueue_issues_called) self.mox.VerifyAll() settings.recompute_derived_fields_in_worker = saved_flag
def testRecomputeDerivedFields_LotsOfIssues(self): """Servlet should enqueue multiple work items.""" saved_flag = settings.recompute_derived_fields_in_worker settings.recompute_derived_fields_in_worker = True self.services.issue.next_id = 12345 num_calls = (self.services.issue.next_id // self.BLOCK + 1) for _ in range(num_calls): taskqueue.add( params=mox.IsA(dict), url='/_task/recomputeDerivedFields.do').WithSideEffects( self.mock_task_queue.add) self.mox.ReplayAll() filterrules_helpers.RecomputeAllDerivedFields(self.cnxn, self.services, self.project, self.config) self.assertFalse(self.services.issue.get_all_issues_in_project_called) self.assertFalse(self.services.issue.update_issues_called) self.assertFalse(self.services.issue.enqueue_issues_called) work_items = self.mock_task_queue.work_items self.assertEqual(num_calls, len(work_items)) url, params = work_items[0]['url'], work_items[0]['params'] self.assertEqual(urls.RECOMPUTE_DERIVED_FIELDS_TASK + '.do', url) self.assertEqual(self.project.project_id, params['project_id']) self.assertEqual(12345 // self.BLOCK * self.BLOCK + 1, params['lower_bound']) self.assertEqual(12345, params['upper_bound']) url, params = work_items[-1]['url'], work_items[-1]['params'] self.assertEqual(urls.RECOMPUTE_DERIVED_FIELDS_TASK + '.do', url) self.assertEqual(self.project.project_id, params['project_id']) self.assertEqual(1, params['lower_bound']) self.assertEqual(self.BLOCK + 1, params['upper_bound']) self.mox.VerifyAll() settings.recompute_derived_fields_in_worker = saved_flag
def testRecomputeDerivedFields_SomeIssues(self): """Servlet should enqueue one work item rather than call directly.""" saved_flag = settings.recompute_derived_fields_in_worker settings.recompute_derived_fields_in_worker = True self.services.issue.next_id = 1234 num_calls = (self.services.issue.next_id // self.BLOCK + 1) for _ in range(num_calls): taskqueue.add( params=mox.IsA(dict), url='/_task/recomputeDerivedFields.do').WithSideEffects( self.mock_task_queue.add) self.mox.ReplayAll() filterrules_helpers.RecomputeAllDerivedFields(self.cnxn, self.services, self.project, self.config) self.assertFalse(self.services.issue.get_all_issues_in_project_called) self.assertFalse(self.services.issue.update_issues_called) self.assertFalse(self.services.issue.enqueue_issues_called) work_items = self.mock_task_queue.work_items self.assertEqual(num_calls, len(work_items)) self.mox.VerifyAll() settings.recompute_derived_fields_in_worker = saved_flag
def _ProcessEditComponent(self, mr, post_data, config, component_def): """The user wants to edit this component definition.""" parsed = component_helpers.ParseComponentRequest( mr, post_data, self.services) if not tracker_constants.COMPONENT_NAME_RE.match(parsed.leaf_name): mr.errors.leaf_name = 'Invalid component name' original_path = component_def.path if mr.component_path and '>' in mr.component_path: parent_path = mr.component_path[:mr.component_path.rindex('>')] new_path = '%s>%s' % (parent_path, parsed.leaf_name) else: new_path = parsed.leaf_name conflict = tracker_bizobj.FindComponentDef(new_path, config) if conflict and conflict.component_id != component_def.component_id: mr.errors.leaf_name = 'That name is already in use.' creator, created = self._GetUserViewAndFormattedTime( mr, component_def.creator_id, component_def.created) modifier, modified = self._GetUserViewAndFormattedTime( mr, component_def.modifier_id, component_def.modified) if mr.errors.AnyErrors(): self.PleaseCorrect( mr, initial_leaf_name=parsed.leaf_name, initial_docstring=parsed.docstring, initial_deprecated=ezt.boolean(parsed.deprecated), initial_admins=parsed.admin_usernames, initial_cc=parsed.cc_usernames, initial_labels=parsed.label_strs, created=created, creator=creator, modified=modified, modifier=modifier, ) return None new_modified = int(time.time()) new_modifier_id = self.services.user.LookupUserID( mr.cnxn, mr.auth.email, autocreate=False) self.services.config.UpdateComponentDef( mr.cnxn, mr.project_id, component_def.component_id, path=new_path, docstring=parsed.docstring, deprecated=parsed.deprecated, admin_ids=parsed.admin_ids, cc_ids=parsed.cc_ids, modified=new_modified, modifier_id=new_modifier_id, label_ids=parsed.label_ids) update_rule = False if new_path != original_path: update_rule = True # If the name changed then update all of its subcomponents as well. subcomponent_ids = tracker_bizobj.FindMatchingComponentIDs( original_path, config, exact=False) for subcomponent_id in subcomponent_ids: if subcomponent_id == component_def.component_id: continue subcomponent_def = tracker_bizobj.FindComponentDefByID( subcomponent_id, config) subcomponent_new_path = subcomponent_def.path.replace( original_path, new_path, 1) self.services.config.UpdateComponentDef( mr.cnxn, mr.project_id, subcomponent_def.component_id, path=subcomponent_new_path) if (set(parsed.cc_ids) != set(component_def.cc_ids) or set(parsed.label_ids) != set(component_def.label_ids)): update_rule = True if update_rule: filterrules_helpers.RecomputeAllDerivedFields( mr.cnxn, self.services, mr.project, config) return framework_helpers.FormatAbsoluteURL( mr, urls.COMPONENT_DETAIL, component=new_path, saved=1, ts=int(time.time()))
def components_update(self, request): """Update a component.""" mar = self.mar_factory(request) config = self._services.config.GetProjectConfig(mar.cnxn, mar.project_id) component_path = request.componentPath component_def = tracker_bizobj.FindComponentDef( component_path, config) if not component_def: raise config_svc.NoSuchComponentException( 'The component %s does not exist.' % component_path) if not permissions.CanViewComponentDef( mar.auth.effective_ids, mar.perms, mar.project, component_def): raise permissions.PermissionException( 'User is not allowed to view this component %s' % component_path) if not permissions.CanEditComponentDef( mar.auth.effective_ids, mar.perms, mar.project, component_def, config): raise permissions.PermissionException( 'User is not allowed to edit this component %s' % component_path) original_path = component_def.path new_path = component_def.path new_docstring = component_def.docstring new_deprecated = component_def.deprecated new_admin_ids = component_def.admin_ids new_cc_ids = component_def.cc_ids update_filterrule = False for update in request.updates: if update.field == api_pb2_v1.ComponentUpdateFieldID.LEAF_NAME: leaf_name = update.leafName if not tracker_constants.COMPONENT_NAME_RE.match(leaf_name): raise config_svc.InvalidComponentNameException( 'The component name %s is invalid.' % leaf_name) if '>' in original_path: parent_path = original_path[:original_path.rindex('>')] new_path = '%s>%s' % (parent_path, leaf_name) else: new_path = leaf_name conflict = tracker_bizobj.FindComponentDef(new_path, config) if conflict and conflict.component_id != component_def.component_id: raise config_svc.InvalidComponentNameException( 'The name %s is already in use.' % new_path) update_filterrule = True elif update.field == api_pb2_v1.ComponentUpdateFieldID.DESCRIPTION: new_docstring = update.description elif update.field == api_pb2_v1.ComponentUpdateFieldID.ADMIN: user_ids_dict = self._services.user.LookupUserIDs( mar.cnxn, list(update.admin), autocreate=True) new_admin_ids = [user_ids_dict[email] for email in update.admin] elif update.field == api_pb2_v1.ComponentUpdateFieldID.CC: user_ids_dict = self._services.user.LookupUserIDs( mar.cnxn, list(update.cc), autocreate=True) new_cc_ids = [user_ids_dict[email] for email in update.cc] update_filterrule = True elif update.field == api_pb2_v1.ComponentUpdateFieldID.DEPRECATED: new_deprecated = update.deprecated else: logging.error('Unknown component field %r', update.field) new_modified = int(time.time()) new_modifier_id = self._services.user.LookupUserID( mar.cnxn, mar.auth.email, autocreate=False) logging.info( 'Updating component id %d: path-%s, docstring-%s, deprecated-%s,' ' admin_ids-%s, cc_ids-%s modified by %s', component_def.component_id, new_path, new_docstring, new_deprecated, new_admin_ids, new_cc_ids, new_modifier_id) self._services.config.UpdateComponentDef( mar.cnxn, mar.project_id, component_def.component_id, path=new_path, docstring=new_docstring, deprecated=new_deprecated, admin_ids=new_admin_ids, cc_ids=new_cc_ids, modified=new_modified, modifier_id=new_modifier_id) # TODO(sheyang): reuse the code in componentdetails if original_path != new_path: # If the name changed then update all of its subcomponents as well. subcomponent_ids = tracker_bizobj.FindMatchingComponentIDs( original_path, config, exact=False) for subcomponent_id in subcomponent_ids: if subcomponent_id == component_def.component_id: continue subcomponent_def = tracker_bizobj.FindComponentDefByID( subcomponent_id, config) subcomponent_new_path = subcomponent_def.path.replace( original_path, new_path, 1) self._services.config.UpdateComponentDef( mar.cnxn, mar.project_id, subcomponent_def.component_id, path=subcomponent_new_path) if update_filterrule: filterrules_helpers.RecomputeAllDerivedFields( mar.cnxn, self._services, mar.project, config) return message_types.VoidMessage()