def testFindMatchingComponentIDs_NoMatch(self): config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) config.component_defs.append(tracker_pb2.ComponentDef( component_id=1, path='UI>Splash')) config.component_defs.append(tracker_pb2.ComponentDef( component_id=2, path='UI>AboutBox')) actual = tracker_bizobj.FindMatchingComponentIDs('DB', config) self.assertEqual([], actual) actual = tracker_bizobj.FindMatchingComponentIDs('DB', config, exact=False) self.assertEqual([], actual)
def testFindMatchingComponentIDs_MatchMultiple(self): config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) config.component_defs.append(tracker_pb2.ComponentDef( component_id=1, path='UI>Splash')) config.component_defs.append(tracker_pb2.ComponentDef( component_id=2, path='UI>AboutBox')) config.component_defs.append(tracker_pb2.ComponentDef( component_id=22, path='UI>AboutBox')) config.component_defs.append(tracker_pb2.ComponentDef( component_id=3, path='DB>Attachments')) actual = tracker_bizobj.FindMatchingComponentIDs('UI>AboutBox', config) self.assertEqual([2, 22], actual) actual = tracker_bizobj.FindMatchingComponentIDs('UI', config, exact=False) self.assertEqual([1, 2, 22], actual)
def _CompareComponents(config, op, rule_values, issue_values): """Compare the components specified in the rule vs those in the issue.""" trivial_result = _CheckTrivialCases(op, issue_values) if trivial_result is not None: return trivial_result exact = op in (ast_pb2.QueryOp.EQ, ast_pb2.QueryOp.NE) rule_component_ids = set() for path in rule_values: rule_component_ids.update(tracker_bizobj.FindMatchingComponentIDs( path, config, exact=exact)) if op == ast_pb2.QueryOp.TEXT_HAS or op == ast_pb2.QueryOp.EQ: return any(rv in issue_values for rv in rule_component_ids) elif op == ast_pb2.QueryOp.NOT_TEXT_HAS or op == ast_pb2.QueryOp.NE: return all(rv not in issue_values for rv in rule_component_ids) return False
def _PreprocessComponentCond(cnxn, cond, project_ids, services, harmonized_config, _is_member): """Preprocess a component= or component:name cond into component_id=IDs.""" exact = _IsEqualityOp(cond.op) component_ids = [] if project_ids: # We are searching within specific projects, so harmonized_config # holds the config data for all those projects. for comp_path in cond.str_values: component_ids.extend( tracker_bizobj.FindMatchingComponentIDs(comp_path, harmonized_config, exact=exact)) else: # We are searching across the whole site, so we have no harmonized_config # to use. component_ids = services.config.FindMatchingComponentIDsAnyProject( cnxn, cond.str_values, exact=exact) return ast_pb2.Condition( op=_TextOpToIntOp(cond.op), field_defs=[query2ast.BUILTIN_ISSUE_FIELDS['component_id']], int_values=component_ids)
def testFindMatchingComponentIDs_Empty(self): config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) actual = tracker_bizobj.FindMatchingComponentIDs('DB', config) self.assertEqual([], actual) actual = tracker_bizobj.FindMatchingComponentIDs('DB', config, exact=False) self.assertEqual([], actual)
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()