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

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

Issue 478763003: [Findit] Bug fixing and implemented some feature requests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed a bug in intersection 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
OLDNEW
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 from threading import Lock, Thread 5 from threading import Lock, Thread
6 6
7 from common import utils 7 from common import utils
8 8
9 9
10 class Blame(object): 10 class Blame(object):
(...skipping 10 matching lines...) Expand all
21 author: The author of this line on the latest revision. 21 author: The author of this line on the latest revision.
22 crash_revision: The revision that caused the crash. 22 crash_revision: The revision that caused the crash.
23 revision: The latest revision of this line before the crash revision. 23 revision: The latest revision of this line before the crash revision.
24 url: The url of the change for the revision. 24 url: The url of the change for the revision.
25 range_start: The starting range of the regression for this component. 25 range_start: The starting range of the regression for this component.
26 range_end: The ending range of the regression. 26 range_end: The ending range of the regression.
27 27
28 """ 28 """
29 29
30 def __init__(self, line_content, component_name, stack_frame_index, 30 def __init__(self, line_content, component_name, stack_frame_index,
31 file_name, line_number, author, revision, 31 file_name, line_number, author, revision, message,
32 url, range_start, range_end): 32 url, range_start, range_end):
33 # Set all the variables from the arguments. 33 # Set all the variables from the arguments.
34 self.line_content = line_content 34 self.line_content = line_content
35 self.component_name = component_name 35 self.component_name = component_name
36 self.stack_frame_index = stack_frame_index 36 self.stack_frame_index = stack_frame_index
37 self.file = file_name 37 self.file = file_name
38 self.line_number = line_number 38 self.line_number = line_number
39 self.author = author 39 self.author = author
40 self.revision = revision 40 self.revision = revision
41 self.message = message
41 self.url = url 42 self.url = url
42 self.range_start = range_start 43 self.range_start = range_start
43 self.range_end = range_end 44 self.range_end = range_end
44 45
45 46
46 class BlameList(object): 47 class BlameList(object):
47 """Represents a list of blame objects. 48 """Represents a list of blame objects.
48 49
49 Thread-safe. 50 Thread-safe.
50 """ 51 """
51 52
52 def __init__(self): 53 def __init__(self):
53 self.blame_list = [] 54 self.blame_list = []
54 self.blame_list_lock = Lock() 55 self.blame_list_lock = Lock()
55 56
56 def __getitem__(self, index): 57 def __getitem__(self, index):
57 return self.blame_list[index] 58 return self.blame_list[index]
58 59
59 def FindBlame(self, callstack, crash_revision_dict, regression_dict, parsers, 60 def FindBlame(self, callstack, component_to_crash_revision_dict,
61 component_to_regression_dict, parsers,
60 top_n_frames=10): 62 top_n_frames=10):
61 """Given a stack within a stacktrace, retrieves blame information. 63 """Given a stack within a stacktrace, retrieves blame information.
62 64
63 Only either first 'top_n_frames' or the length of stack, whichever is 65 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. 66 shorter, results are returned. The default value of 'top_n_frames' is 10.
65 67
66 Args: 68 Args:
67 callstack: The list of stack frames. 69 callstack: The list of stack frames.
68 crash_revision_dict: A dictionary that maps component to its crash 70 component_to_crash_revision_dict: A dictionary that maps component to its
69 revision. 71 crash revision.
70 regression_dict: A dictionary that maps component to its revision 72 component_to_regression_dict: A dictionary that maps component to its
71 range. 73 revision range.
72 parsers: A list of two parsers, svn_parser and git_parser 74 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. 75 top_n_frames: A number of stack frames to show the blame result for.
74 """ 76 """
75 # Only return blame information for first 'top_n_frames' frames. 77 # Only return blame information for first 'top_n_frames' frames.
76 stack_frames = callstack.GetTopNFrames(top_n_frames) 78 stack_frames = callstack.GetTopNFrames(top_n_frames)
77 threads = [] 79 threads = []
78 # Iterate through frames in stack. 80 # Iterate through frames in stack.
79 for stack_frame in stack_frames: 81 for stack_frame in stack_frames:
80 # If the component this line is from does not have a crash revision, 82 # If the component this line is from does not have a crash revision,
81 # it is not possible to get blame information, so ignore this line. 83 # it is not possible to get blame information, so ignore this line.
82 component_path = stack_frame.component_path 84 component_path = stack_frame.component_path
83 if component_path not in crash_revision_dict: 85 if component_path not in component_to_crash_revision_dict:
84 continue 86 continue
85 87
86 crash_revision = crash_revision_dict[component_path]['revision'] 88 crash_revision = component_to_crash_revision_dict[
89 component_path]['revision']
87 range_start = None 90 range_start = None
88 range_end = None 91 range_end = None
89 is_git = utils.IsGitHash(crash_revision) 92 is_git = utils.IsGitHash(crash_revision)
90 if is_git: 93 if is_git:
91 repository_parser = parsers['git'] 94 repository_parser = parsers['git']
92 else: 95 else:
93 repository_parser = parsers['svn'] 96 repository_parser = parsers['svn']
94 97
95 # If the revision is in SVN, and if regression information is available, 98 # If the revision is in SVN, and if regression information is available,
96 # get it. For Git, we cannot know the ordering between hash numbers. 99 # get it. For Git, we cannot know the ordering between hash numbers.
97 if not is_git: 100 if not is_git:
98 if regression_dict and component_path in regression_dict: 101 if component_to_regression_dict and \
99 component_object = regression_dict[component_path] 102 component_path in component_to_regression_dict:
103 component_object = component_to_regression_dict[component_path]
100 range_start = int(component_object['old_revision']) 104 range_start = int(component_object['old_revision'])
101 range_end = int(component_object['new_revision']) 105 range_end = int(component_object['new_revision'])
102 106
103 # Generate blame entry, one thread for one entry. 107 # Generate blame entry, one thread for one entry.
104 blame_thread = Thread( 108 blame_thread = Thread(
105 target=self.__GenerateBlameEntry, 109 target=self.__GenerateBlameEntry,
106 args=[repository_parser, stack_frame, crash_revision, 110 args=[repository_parser, stack_frame, crash_revision,
107 range_start, range_end]) 111 range_start, range_end])
108 threads.append(blame_thread) 112 threads.append(blame_thread)
109 blame_thread.start() 113 blame_thread.start()
110 114
111 # Join the results before returning. 115 # Join the results before returning.
112 for blame_thread in threads: 116 for blame_thread in threads:
113 blame_thread.join() 117 blame_thread.join()
114 118
115 def __GenerateBlameEntry(self, repository_parser, stack_frame, 119 def __GenerateBlameEntry(self, repository_parser, stack_frame,
116 crash_revision, range_start, range_end): 120 crash_revision, range_start, range_end):
117 """Generates blame list from the arguments.""" 121 """Generates blame list from the arguments."""
118 stack_frame_index = stack_frame.index 122 stack_frame_index = stack_frame.index
119 component_path = stack_frame.component_path 123 component_path = stack_frame.component_path
120 component_name = stack_frame.component_name 124 component_name = stack_frame.component_name
121 file_name = stack_frame.file_name 125 file_name = stack_frame.file_name
122 file_path = stack_frame.file_path 126 file_path = stack_frame.file_path
123 crashed_line_number = stack_frame.crashed_line_number 127 crashed_line_number = stack_frame.crashed_line_number[0]
Martin Barbella 2014/08/22 02:24:13 I mention this in more detail in stacktrace.py, bu
jeun 2014/08/22 22:58:43 Done.
124 128
125 # Parse blame information. 129 # Parse blame information.
126 parsed_blame_info = repository_parser.ParseBlameInfo( 130 parsed_blame_info = repository_parser.ParseBlameInfo(
127 component_path, file_path, crashed_line_number, crash_revision) 131 component_path, file_path, crashed_line_number, crash_revision)
128 132
129 # If it fails to retrieve information, do not do anything. 133 # If it fails to retrieve information, do not do anything.
130 if not parsed_blame_info or len(parsed_blame_info) != 4: 134 if not parsed_blame_info or len(parsed_blame_info) != 5:
Martin Barbella 2014/08/22 02:24:13 It doesn't seem like a good practice to allow pars
stgao 2014/08/22 06:50:53 +1 Why do we use 5 here?
jeun 2014/08/22 22:58:43 Done.
jeun 2014/08/22 22:58:43 Done.
131 return 135 return
132 136
133 # Create blame object from the parsed info and add it to the list. 137 # Create blame object from the parsed info and add it to the list.
134 (line_content, revision, author, url) = parsed_blame_info 138 (line_content, revision, author, url, message) = parsed_blame_info
135 blame = Blame(line_content, component_name, stack_frame_index, file_name, 139 blame = Blame(line_content, component_name, stack_frame_index, file_name,
136 crashed_line_number, author, revision, url, 140 crashed_line_number, author, revision, message, url,
137 range_start, range_end) 141 range_start, range_end)
138 142
139 with self.blame_list_lock: 143 with self.blame_list_lock:
140 self.blame_list.append(blame) 144 self.blame_list.append(blame)
141 145
142 def FilterAndSortBlameList(self): 146 def FilterAndSortBlameList(self):
143 """Filters and sorts the blame list.""" 147 """Filters and sorts the blame list."""
144 # Sort the blame list by its position in stack. 148 # Sort the blame list by its position in stack.
145 self.blame_list.sort(key=lambda blame: blame.stack_frame_index) 149 self.blame_list.sort(key=lambda blame: blame.stack_frame_index)
146 150
147 filtered_blame_list = [] 151 filtered_blame_list = []
148 152
149 for blame in self.blame_list: 153 for blame in self.blame_list:
150 # If regression information is available, check if it needs to be 154 # If regression information is available, check if it needs to be
151 # filtered. 155 # filtered.
152 if blame.range_start and blame.range_end: 156 if blame.range_start and blame.range_end:
153 157
154 # Discards results that are after the end of regression. 158 # Discards results that are after the end of regression.
155 if not utils.IsGitHash(blame.revision) and ( 159 if not utils.IsGitHash(blame.revision) and (
156 int(blame.range_end) <= int(blame.revision)): 160 int(blame.range_end) <= int(blame.revision)):
157 continue 161 continue
158 162
159 filtered_blame_list.append(blame) 163 filtered_blame_list.append(blame)
160 164
161 self.blame_list = filtered_blame_list 165 self.blame_list = filtered_blame_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698