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