Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: tools/findit/blame.py

Issue 421223003: [Findit] Plain objects to represent the returned result from running the algorithm, (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: addressed code review Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tools/findit/match_set.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 # found in the LICENSE file.
4
5 from threading import Lock, Thread
6
7 import utils
8
9
10 class Blame(object):
11 """Represents a blame object.
12
13 The object contains blame information for one line of stack, and this
14 information is shown when there are no CLs that change the crashing files.
15 Attributes:
16 line_content: The content of the line to find the blame for.
17 component_name: The name of the component for this line.
18 stack_frame_index: The stack frame index of this file.
19 file_name: The name of the file.
20 line_number: The line that caused a crash.
21 author: The author of this line on the latest revision.
22 crash_revision: The revision that caused the crash.
23 revision: The latest revision of this line before the crash revision.
24 url: The url of the change for the revision.
25 range_start: The starting range of the regression for this component.
26 range_end: The ending range of the regression.
27
28 """
29
30 def __init__(self, line_content, component_name, stack_frame_index,
31 file_name, line_number, author, revision,
32 url, range_start, range_end):
33 # Set all the variables from the arguments.
34 self.line_content = line_content
35 self.component_name = component_name
36 self.stack_frame_index = stack_frame_index
37 self.file = file_name
38 self.line_number = line_number
39 self.author = author
40 self.revision = revision
41 self.url = url
42 self.range_start = range_start
43 self.range_end = range_end
44
45
46 class BlameList(object):
47 """Represents a list of blame objects.
48
49 Thread-safe.
50 """
51
52 def __init__(self):
53 self.blame_list = []
54 self.blame_list_lock = Lock()
55
56 def __getitem__(self, index):
57 return self.blame_list[index]
58
59 def FindBlame(self, callstack, crash_revision_dict, regression_dict, parsers,
60 top_n_frames=10):
61 """Given a stack within a stacktrace, retrieves blame information.
62
63 Only either first 'top_n_frames' or the length of stack, whichever is
64 shorter, results are returned. The default value of 'top_n_frames' is 10.
65
66 Args:
67 callstack: The list of stack frames.
68 crash_revision_dict: A dictionary that maps component to its crash
69 revision.
70 regression_dict: A dictionary that maps component to its revision
71 range.
72 parsers: A list of two parsers, svn_parser and git_parser
73 top_n_frames: A number of stack frames to show the blame result for.
74 """
75 # Only return blame information for first 'top_n_frames' frames.
76 stack_frames = callstack.GetTopNFrames(top_n_frames)
77
78 threads = []
79 # Iterate through frames in stack.
80 for stack_frame in stack_frames:
81 # If the component this line is from does not have a crash revision,
82 # it is not possible to get blame information, so ignore this line.
83 component_path = stack_frame.component_path
84 if component_path not in crash_revision_dict:
85 continue
86
87 crash_revision = crash_revision_dict[component_path]['revision']
88 range_start = None
89 range_end = None
90 is_git = utils.IsGitHash(crash_revision)
91 if is_git:
92 repository_parser = parsers['git']
93 else:
94 repository_parser = parsers['svn']
95
96 # If the revision is in SVN, and if regression information is available,
97 # get it. For Git, we cannot know the ordering between hash numbers.
98 if not is_git:
99 if regression_dict and component_path in regression_dict:
100 component_object = regression_dict[component_path]
101 range_start = int(component_object['old_revision'])
102 range_end = int(component_object['new_revision'])
103
104 # Generate blame entry, one thread for one entry.
105 blame_thread = Thread(
106 target=self.__GenerateBlameEntry,
107 args=[repository_parser, stack_frame, crash_revision,
108 range_start, range_end])
109 threads.append(blame_thread)
110 blame_thread.start()
111
112 # Join the results before returning.
113 for blame_thread in threads:
114 blame_thread.join()
115
116 def __GenerateBlameEntry(self, repository_parser, stack_frame,
117 crash_revision, range_start, range_end):
118 """Generates blame list from the arguments."""
119 stack_frame_index = stack_frame.index
120 component_path = stack_frame.component_path
121 component_name = stack_frame.component_name
122 file_name = stack_frame.file_name
123 file_path = stack_frame.file_path
124 crashed_line_number = stack_frame.crashed_line_number
125
126 # Parse blame information.
127 parsed_blame_info = repository_parser.ParseBlameInfo(
128 component_path, file_path, crashed_line_number, crash_revision)
129
130 # If it fails to retrieve information, do not do anything.
131 if not parsed_blame_info or len(parsed_blame_info) != 4:
132 return
133
134 # Create blame object from the parsed info and add it to the list.
135 (line_content, revision, author, url) = parsed_blame_info
136 blame = Blame(line_content, component_name, stack_frame_index, file_name,
137 crashed_line_number, author, revision, url,
138 range_start, range_end)
139
140 with self.blame_list_lock:
141 self.blame_list.append(blame)
142
143 def FilterAndSortBlameList(self):
144 """Filters and sorts the blame list."""
145 # Sort the blame list by its position in stack.
146 self.blame_list.sort(key=lambda blame: blame.stack_frame_index)
147
148 filtered_blame_list = []
149
150 for blame in self.blame_list:
151 # If regression information is available, check if it needs to be
152 # filtered.
153 if blame.range_start and blame.range_end:
154
155 # Discards results that are after the end of regression.
156 if not utils.IsGitHash(blame.revision) and (
157 int(blame.revision) < int(blame.range_end)):
158 continue
159
160 filtered_blame_list.append(blame)
161
162 self.blame_list = filtered_blame_list
OLDNEW
« no previous file with comments | « no previous file | tools/findit/match_set.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698