OLD | NEW |
---|---|
1 # Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import logging | 5 import logging |
6 import re | 6 import re |
7 | 7 |
8 from threading import Lock | 8 from threading import Lock |
9 | 9 |
10 import crash_utils | 10 import crash_utils |
11 | 11 |
12 | 12 |
13 REVIEW_URL_PATTERN = re.compile(r'Review URL:( *)(.*)') | 13 REVIEW_URL_PATTERN = re.compile(r'Review URL:( *)(.*?)/(\d+)') |
14 | 14 |
15 | 15 |
16 class Match(object): | 16 class Match(object): |
17 """Represents a match entry. | 17 """Represents a match entry. |
18 | 18 |
19 A match is a CL that is suspected to have caused the crash. A match object | 19 A match is a CL that is suspected to have caused the crash. A match object |
20 contains information about files it changes, their authors, etc. | 20 contains information about files it changes, their authors, etc. |
21 | 21 |
22 Attributes: | 22 Attributes: |
23 is_reverted: True if this CL is reverted by other CL. | 23 is_revert: True if this CL is reverted by other CL. |
24 revert_of: If this CL is a revert of some other CL, a revision number/ | 24 revert_of: If this CL is a revert of some other CL, a revision number/ |
25 git hash of that CL. | 25 git hash of that CL. |
26 crashed_line_numbers: The list of lines that caused crash for this CL. | 26 crashed_line_numbers: The list of lines that caused crash for this CL. |
27 function_list: The list of functions that caused the crash. | 27 function_list: The list of functions that caused the crash. |
28 min_distance: The minimum distance between the lines that CL changed and | 28 min_distance: The minimum distance between the lines that CL changed and |
29 lines that caused the crash. | 29 lines that caused the crash. |
30 changed_files: The list of files that the CL changed. | 30 changed_files: The list of files that the CL changed. |
31 changed_file_urls: The list of URLs for the file. | 31 changed_file_urls: The list of URLs for the file. |
32 author: The author of the CL. | 32 author: The author of the CL. |
33 component_name: The name of the component that this CL belongs to. | 33 component_name: The name of the component that this CL belongs to. |
34 stack_frame_indices: For files that caused crash, list of where in the | 34 stack_frame_indices: For files that caused crash, list of where in the |
35 stackframe they occur. | 35 stackframe they occur. |
36 rank: The highest priority among the files the CL changes. Priority = 1 | |
37 if it changes the crashed line, and priority = 2 if it is a simple | |
38 file change. | |
39 priorities: A list of priorities for each of the changed file. | 36 priorities: A list of priorities for each of the changed file. |
stgao
2014/08/22 06:50:54
Please add a description on how priority is define
jeun
2014/08/22 22:58:44
Done.
| |
40 reivision_url: The revision URL of the CL. | 37 reivision_url: The revision URL of the CL. |
41 review_url: The codereview URL that reviews this CL. | 38 review_url: The codereview URL that reviews this CL. |
42 reviewers: The list of people that reviewed this CL. | 39 reviewers: The list of people that reviewed this CL. |
43 reason: The reason why this CL is suspected. | 40 reason: The reason why this CL is suspected. |
44 """ | 41 """ |
45 REVERT_PATTERN = re.compile(r'(revert\w*) r?(\d+)', re.I) | 42 REVERT_PATTERN = re.compile(r'(revert\w*) r?(\d+)', re.I) |
46 | 43 |
47 def __init__(self, revision, component_name): | 44 def __init__(self, revision, component_name): |
48 self.is_reverted = False | 45 self.is_revert = False |
49 self.revert_of = None | 46 self.revert_of = None |
47 self.message = None | |
50 self.crashed_line_numbers = [] | 48 self.crashed_line_numbers = [] |
51 self.function_list = [] | 49 self.function_list = [] |
52 self.min_distance = crash_utils.INFINITY | 50 self.min_distance = crash_utils.INFINITY |
53 self.changed_files = [] | 51 self.changed_files = [] |
54 self.changed_file_urls = [] | 52 self.changed_file_urls = [] |
55 self.author = revision['author'] | 53 self.author = revision['author'] |
56 self.component_name = component_name | 54 self.component_name = component_name |
57 self.stack_frame_indices = [] | 55 self.stack_frame_indices = [] |
58 self.rank = crash_utils.INFINITY | |
59 self.priorities = [] | 56 self.priorities = [] |
60 self.revision_url = revision['url'] | 57 self.revision_url = revision['url'] |
61 self.review_url = '' | 58 self.review_url = '' |
62 self.reviewers = [] | 59 self.reviewers = [] |
63 self.reason = None | 60 self.reason = None |
64 | 61 |
65 def ParseMessage(self, message, codereview_api_url): | 62 def ParseMessage(self, message, codereview_api_url): |
66 """Parses the message. | 63 """Parses the message. |
67 | 64 |
68 It checks the message to extract the code review website and list of | 65 It checks the message to extract the code review website and list of |
69 reviewers, and it also checks if the CL is a revert of another CL. | 66 reviewers, and it also checks if the CL is a revert of another CL. |
70 | 67 |
71 Args: | 68 Args: |
72 message: The message to parse. | 69 message: The message to parse. |
73 codereview_api_url: URL to retrieve codereview data from. | 70 codereview_api_url: URL to retrieve codereview data from. |
74 """ | 71 """ |
72 self.message = message | |
75 for line in message.splitlines(): | 73 for line in message.splitlines(): |
76 line = line.strip() | 74 line = line.strip() |
77 review_url_line_match = REVIEW_URL_PATTERN.match(line) | 75 review_url_line_match = REVIEW_URL_PATTERN.match(line) |
78 | 76 |
79 # Check if the line has the code review information. | 77 # Check if the line has the code review information. |
80 if review_url_line_match: | 78 if review_url_line_match: |
81 | 79 |
82 # Get review number for the code review site from the line. | 80 # Get review number for the code review site from the line. |
83 issue_number = review_url_line_match.group(2) | 81 issue_number = review_url_line_match.group(3) |
84 | 82 |
85 # Get JSON from the code review site, ignore the line if it fails. | 83 # Get JSON from the code review site, ignore the line if it fails. |
86 url = codereview_api_url % issue_number | 84 url = codereview_api_url % issue_number |
87 json_string = crash_utils.GetDataFromURL(url) | 85 json_string = crash_utils.GetDataFromURL(url) |
88 if not json_string: | 86 if not json_string: |
89 logging.warning('Failed to retrieve code review information from %s', | 87 logging.warning('Failed to retrieve code review information from %s', |
90 url) | 88 url) |
91 continue | 89 continue |
92 | 90 |
93 # Load the JSON from the string, and get the list of reviewers. | 91 # Load the JSON from the string, and get the list of reviewers. |
94 code_review = crash_utils.LoadJSON(json_string) | 92 code_review = crash_utils.LoadJSON(json_string) |
95 if code_review: | 93 if code_review: |
96 self.reviewers = code_review['reviewers'] | 94 self.reviewers = code_review['reviewers'] |
97 | 95 |
98 # Check if this CL is a revert of other CL. | 96 # Check if this CL is a revert of other CL. |
99 if line.lower().startswith('revert'): | 97 if line.lower().startswith('revert'): |
100 self.is_reverted = True | 98 self.is_revert = True |
101 | 99 |
102 # Check if the line says what CL this CL is a revert of. | 100 # Check if the line says what CL this CL is a revert of. |
103 revert = self.REVERT_PATTERN.match(line) | 101 revert = self.REVERT_PATTERN.match(line) |
104 if revert: | 102 if revert: |
105 self.revert_of = revert.group(2) | 103 self.revert_of = revert.group(2) |
106 return | 104 return |
107 | 105 |
108 | 106 |
109 class MatchSet(object): | 107 class MatchSet(object): |
110 """Represents a set of matches. | 108 """Represents a set of matches. |
111 | 109 |
112 Attributes: | 110 Attributes: |
113 matches: A map from CL to a match object. | 111 matches: A map from CL to a match object. |
114 cls_to_ignore: A set of CLs to ignore. | 112 cls_to_ignore: A set of CLs to ignore. |
115 matches_lock: A lock guarding matches dictionary. | 113 matches_lock: A lock guarding matches dictionary. |
116 """ | 114 """ |
117 | 115 |
118 def __init__(self, codereview_api_url): | 116 def __init__(self, codereview_api_url): |
119 self.codereview_api_url = codereview_api_url | 117 self.codereview_api_url = codereview_api_url |
120 self.matches = {} | 118 self.matches = {} |
121 self.cls_to_ignore = set() | 119 self.cls_to_ignore = set() |
122 self.matches_lock = Lock() | 120 self.matches_lock = Lock() |
123 | 121 |
124 def RemoveRevertedCLs(self): | 122 def RemoveRevertedCLs(self): |
125 """Removes CLs that are revert.""" | 123 """Removes CLs that are revert.""" |
126 for cl in self.matches: | 124 for cl in self.matches: |
127 if cl in self.cls_to_ignore: | 125 if cl in self.cls_to_ignore: |
128 del self.matches[cl] | 126 del self.matches[cl] |
OLD | NEW |