blob: 0147e5319b1dcc9896669d7654101c87d76cee95 [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001# Copyright 2016 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Copybara854996b2021-09-07 19:36:02 +00004
5"""Helper functions and classes used in issue search and sorting."""
6from __future__ import print_function
7from __future__ import division
8from __future__ import absolute_import
9
10import logging
11import re
12
13from features import savedqueries_helpers
14from search import query2ast
15from services import tracker_fulltext
16from services import fulltext_helpers
17from tracker import tracker_helpers
18
19
20# Users can use "is:starred" in queries to limit
21# search results to issues starred by that user.
22IS_STARRED_RE = re.compile(r'\b(?![-@.:])is:starred\b(?![-@.:])', re.I)
23
24# Users can use "me" in other fields to refer to the logged in user name.
25KEYWORD_ME_RE = re.compile(r'\b[-_a-z0-9]+[=:]me\b(?![-@.:=])', re.I)
26ME_RE = re.compile(r'(?<=[=:])me\b(?![-@.:=])', re.I)
27
28
29def _AccumulateIssueProjectsAndConfigs(
30 cnxn, project_dict, config_dict, services, issues):
31 """Fetch any projects and configs that we need but haven't already loaded.
32
33 Args:
34 cnxn: connection to SQL database.
35 project_dict: dict {project_id: project} of projects that we have
36 already retrieved.
37 config_dict: dict {project_id: project} of configs that we have
38 already retrieved.
39 services: connections to backends.
40 issues: list of issues, which may be parts of different projects.
41
42 Returns:
43 Nothing, but projects_dict will be updated to include all the projects that
44 contain the given issues, and config_dicts will be updated to incude all
45 the corresponding configs.
46 """
47 new_ids = {issue.project_id for issue in issues}
48 new_ids.difference_update(iter(project_dict.keys()))
49 new_projects_dict = services.project.GetProjects(cnxn, new_ids)
50 project_dict.update(new_projects_dict)
51 new_configs_dict = services.config.GetProjectConfigs(cnxn, new_ids)
52 config_dict.update(new_configs_dict)
53
54
55def ReplaceKeywordsWithUserIDs(me_user_ids, query):
56 """Substitutes User ID in terms such as is:starred and me.
57
58 This is done on the query string before it is parsed because the query string
59 is used as a key for cached search results in memcache. A search for by one
60 user for owner:me should not retrieve results stored for some other user.
61
62 Args:
63 me_user_ids: [] when no user is logged in, or user ID of the logged in
64 user when doing an interactive search, or the viewed user ID when
65 viewing someone else's dashboard, or the subscribing user's ID when
66 evaluating subscriptions. Also contains linked account IDs.
67 query: The query string.
68
69 Returns:
70 A pair (query, warnings) where query is a string with "me" and "is:starred"
71 removed or replaced by new terms that use the numeric user ID provided,
72 and warnings is a list of warning strings to display to the user.
73 """
74 warnings = []
75 if me_user_ids:
76 me_user_ids_str = ','.join(str(uid) for uid in me_user_ids)
77 star_term = 'starredby:%s' % me_user_ids_str
78 query = IS_STARRED_RE.sub(star_term, query)
79 if KEYWORD_ME_RE.search(query):
80 query = ME_RE.sub(me_user_ids_str, query)
81 else:
82 if IS_STARRED_RE.search(query):
83 warnings.append('"is:starred" ignored because you are not signed in.')
84 query = IS_STARRED_RE.sub('', query)
85 if KEYWORD_ME_RE.search(query):
86 warnings.append('"me" keyword ignored because you are not signed in.')
87 query = KEYWORD_ME_RE.sub('', query)
88
89 return query, warnings