Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 from collections import namedtuple | |
| 6 import os | |
| 7 import re | |
| 8 | |
| 9 from libs.gitiles.diff import ChangeType | |
| 10 | |
| 11 # Some projects like "chromium", it has many dependency projects like | |
|
Martin Barbella
2017/01/27 23:30:58
Nit: s/it has/have/
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 12 # "chromium-blink", "chromium-skia", "chromium-pdfium"...etc., for those | |
| 13 # dep projects, the "chromium" ``Project`` can derive the names from their | |
| 14 # dep paths. | |
| 15 # Some other projects like "android_os", "clank", they don't have any dependency | |
| 16 # projects that are relavent to Predator. | |
| 17 _PROJECTS_WITH_DEP_PROJECTS = ['chromium'] | |
| 18 | |
| 19 | |
| 20 # TODO(http://crbug.com/659346): write the coverage tests. | |
| 21 class Project(namedtuple('Project', | |
| 22 ['name', 'path_regexs', 'function_regexs', | |
|
wrengr
2017/01/30 19:14:19
Nit: "regexes" is the standard way to pluralize "r
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 23 'host_directories'])): | |
| 24 """A representation of a "project". | |
|
wrengr
2017/01/30 19:14:19
This line doesn't explain anything beyond what the
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 25 | |
| 26 For example: 'android_os', 'clank' or 'chromium'. Notably, a project knows | |
| 27 how to identify itself. Hence, given a stack frame, file path or dependency | |
| 28 path or whatever, we ask the ``Project`` whether it matches that frame, | |
| 29 CL, etc. | |
| 30 | |
| 31 Properties: | |
| 32 name (str): The name of the project, like "chromium", "android_os". | |
| 33 path_regexs (list of re.RegexObject): Patterns of paths that project has. | |
| 34 function_regexs (list of re.RegexObject): Patterns of functions that project | |
| 35 has. | |
| 36 host_directories (list of str): The root directoris of this project and its | |
|
wrengr
2017/01/30 19:14:19
(s/directoris/directories/ && s/and its/and their/
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 37 dependency projects. | |
| 38 N.B. If ``host_directories`` is availabe, this project can match | |
|
wrengr
2017/01/30 19:14:19
s/availabe/available/
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 39 it with the passed-in ``dep_path`` to tell whether a suspect or stack is | |
| 40 from this project, else if this information is missing, the project cannot | |
|
wrengr
2017/01/30 19:14:19
s/, else if/. If/
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 41 tell that from ``dep_path``, however that doesn't mean the suspect or | |
|
wrengr
2017/01/30 19:14:19
s/, however/; however,/
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 42 stack does not belong to this project, we can use other information like | |
| 43 ``path_regexs`` or ``function_regexs`` to analyze. | |
| 44 """ | |
| 45 __slots__ = () | |
| 46 | |
| 47 def __new__(cls, name, path_regexs=None, | |
| 48 function_regexs=None, host_directories=None): | |
| 49 path_regexs = [re.compile(path_regex) for path_regex in | |
|
wrengr
2017/01/30 19:14:19
can replace this line with ``map(re.compile, path_
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 50 path_regexs] if path_regexs else [] | |
| 51 function_regexs = [re.compile(function_regex) for function_regex in | |
| 52 function_regexs] if function_regexs else [] | |
|
wrengr
2017/01/30 19:14:19
ditto
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 53 host_directories = host_directories or [] | |
| 54 | |
| 55 return super(cls, Project).__new__( | |
| 56 cls, name, path_regexs, function_regexs, host_directories) | |
| 57 | |
| 58 def MatchesStackFrame(self, frame): | |
| 59 """Returns true if this project matches the frame.""" | |
| 60 # Sometimes some marker information are in the frame.raw_file_path. | |
| 61 # An example, the path_regex for android_os is -- | |
| 62 # "https___googleplex-android.googlesource.com_a_platform_manifest.git/". | |
| 63 # It can only be found in frame.raw_file_path, since the frame.file_path | |
| 64 # has those kind of information stripped. | |
| 65 for path_regex in self.path_regexs: | |
| 66 if (path_regex.match(os.path.join(frame.dep_path, frame.file_path)) or | |
| 67 path_regex.match(frame.raw_file_path)): | |
| 68 return True | |
| 69 | |
| 70 for function_regex in self.function_regexs: | |
| 71 if function_regex.match(frame.function): | |
| 72 return True | |
| 73 | |
| 74 for host_directory in self.host_directories: | |
| 75 if frame.dep_path.startswith(host_directory): | |
| 76 return True | |
| 77 | |
| 78 return False | |
| 79 | |
| 80 def MatchesTouchedFile(self, dep_path, touched_file): | |
| 81 """Returns true if this project matches the file path.""" | |
| 82 if touched_file.change_type == ChangeType.DELETE: | |
|
wrengr
2017/01/30 19:14:19
Since this conditional shows up repeatedly, should
Sharu Jiang
2017/01/30 22:23:52
Done.
| |
| 83 path = touched_file.old_path | |
| 84 else: | |
| 85 path = touched_file.new_path | |
| 86 | |
| 87 # If the path matches the path patterns. | |
| 88 for path_regex in self.path_regexs: | |
| 89 if path_regex.match(os.path.join(dep_path, path)): | |
| 90 return True | |
| 91 | |
| 92 # If the dep_path hosted by this project. | |
| 93 for host_directory in self.host_directories: | |
| 94 if dep_path.startswith(host_directory): | |
| 95 return True | |
| 96 | |
| 97 return False | |
| 98 | |
| 99 def GetName(self, dep_path=None): | |
| 100 """Returns the project name based on dep path. | |
| 101 | |
| 102 N.B. (1) If this project doesn't have dep projects, just return the project | |
| 103 name. (2) If this project does, return the derived dep project name based on | |
| 104 the self.host_directories. | |
| 105 """ | |
| 106 if self.name not in _PROJECTS_WITH_DEP_PROJECTS or dep_path is None: | |
| 107 return self.name | |
| 108 | |
| 109 # For chromium project, get the name of the sub project from ``dep_path``. | |
| 110 for host_directory in self.host_directories: | |
| 111 if dep_path.startswith(host_directory): | |
| 112 path = dep_path[len(host_directory):] | |
| 113 if not path: | |
| 114 return self.name | |
| 115 | |
| 116 return '%s-%s' % (self.name, path.split('/')[0].lower()) | |
| 117 | |
| 118 # Unknown path, return the whole path as project name. | |
| 119 return '%s-%s' % (self.name, | |
| 120 '_'.join([dep_part for dep_part in dep_path.split('/') | |
| 121 if dep_part])) | |
| OLD | NEW |