Chromium Code Reviews| Index: tools/findit/match_set.py |
| diff --git a/tools/findit/match_set.py b/tools/findit/match_set.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b5cb24ff930a6e6c2ffb324cb951ecc1a032884a |
| --- /dev/null |
| +++ b/tools/findit/match_set.py |
| @@ -0,0 +1,121 @@ |
| +# Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +import logging |
| +import re |
| +from threading import Lock |
| + |
| +import crash_utils |
| + |
| + |
| +class Match(object): |
| + """Represents a match entry. |
| + |
| + A match is a CL that is suspected to have caused the crash. A match object |
| + contains information about files it changes, their authors, etc. |
| + |
| + Attributes: |
| + line_of_crash: The list of lines that caused crash for this CL. |
| + function: The list of functions that caused the crash. |
| + min_distance: The minimum difference between the lines that CL changed and |
| + lines that caused the crash. |
| + files: The list of files that the CL changed. |
| + file_urls: The list of URLs for the file. |
| + author: The author of the CL. |
| + component_name: The name of the component that this CL belongs to. |
| + stack_frame_indices: For files that caused crash, list of where in the |
| + stackframe they occur. |
|
stgao
2014/08/14 16:31:19
indent?
jeun
2014/08/14 17:38:57
Done.
|
| + rank: The highest priority among the files the CL changes. |
| + priorities: For each files, whether it changes the crashed line |
| + (priority = 1) or is a simple file change (priority = 2). |
| + url: URL of the CL. |
|
stgao
2014/08/14 16:31:19
|url| is not that clear. Please find a better name
jeun
2014/08/14 17:38:57
Done.
|
| + review_url: The codereview address that reviews this CL. |
|
stgao
2014/08/14 16:31:19
address -> url?
jeun
2014/08/14 17:38:57
Done.
|
| + reviewers: The list of people that reviewed this CL. |
| + reason: The reason why this CL is suspected. |
| + """ |
| + REVERT_PATTERN = re.compile(r'(revert\w*) r?(\d+)', re.I) |
| + |
| + def __init__(self, revision, component_name): |
| + self.is_reverted = False |
| + self.revert_of = None |
| + self.line_of_crash = [] |
| + self.function = [] |
| + self.min_distance = crash_utils.INFINITY |
| + self.files = [] |
| + self.file_urls = [] |
| + self.author = revision['author'] |
| + self.component_name = component_name |
| + self.stack_frame_indices = [] |
| + self.rank = crash_utils.INFINITY |
| + self.priorities = [] |
| + self.url = revision['url'] |
| + self.review_url = 'N/A' |
| + self.reviewers = ['N/A'] |
| + self.reason = None |
| + |
| + def ParseMessage(self, message, codereview_api_url): |
| + """Parses the message. |
| + |
| + It checks the message to extract the code review website and list of |
| + reviewers, and it also checks if the CL is a revert of another CL. |
| + |
| + Args: |
| + message: The message to parse. |
| + codereview_api_url: URL to retrieve codereview data from. |
| + """ |
| + for line in message.splitlines(): |
| + line = line.strip() |
| + |
| + # Check if the line has the code review information. |
| + if line.startswith('Review URL: '): |
| + |
| + # Get review number for the code review site from the line. |
| + parts = line.split('Review URL: ') |
| + self.review_url = parts[1].strip() |
| + issue_number = self.review_url.split('/')[-1] |
| + |
| + # Get JSON from the code review site, ignore the line if it fails. |
| + url = codereview_api_url % issue_number |
| + json_string = crash_utils.GetDataFromURL(url) |
| + if not json_string: |
| + logging.warning('Failed to retrieve code review information from %s', |
| + url) |
| + continue |
| + |
| + # Load the JSON from the string, and get the list of reviewers. |
| + code_review = crash_utils.LoadJSON(json_string) |
| + if code_review: |
| + self.reviewers = code_review['reviewers'] |
| + |
| + # Check if this CL is a revert of other CL. |
| + if line.lower().startswith('revert'): |
| + self.is_reverted = True |
| + |
| + # Check if the line says what CL this CL is a revert of. |
| + revert = self.REVERT_PATTERN.match(line) |
| + if revert: |
| + self.revert_of = revert.group(2) |
| + return |
| + |
| + |
| +class MatchSet(object): |
| + """Represents a set of matches. |
| + |
| + Attributes: |
| + matches: A map from CL to a match object. |
| + cls_to_ignore: A set of CLs to ignore. |
| + matches_lock: A lock guarding matches dictionary. |
| + """ |
| + |
| + def __init__(self, codereview_api_url): |
| + self.codereview_api_url = codereview_api_url |
| + self.matches = {} |
| + self.cls_to_ignore = set() |
| + self.matches_lock = Lock() |
| + |
| + def RemoveReverts(self): |
| + """Removes CLs that are revert.""" |
| + for cl in self.matches: |
| + if cl in self.cls_to_ignore: |
| + del self.matches[cl] |