Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 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 os | |
| 7 import xml.dom.minidom as minidom | 6 import xml.dom.minidom as minidom |
| 8 from xml.parsers.expat import ExpatError | 7 from xml.parsers.expat import ExpatError |
| 9 | 8 |
| 10 import crash_utils | 9 import crash_utils |
| 11 from repository_parser_interface import ParserInterface | 10 from repository_parser_interface import ParserInterface |
| 12 | 11 |
| 13 | 12 |
| 14 # This number is 6 because each linediff page in src.chromium.org should | 13 # This number is 6 because each linediff page in src.chromium.org should |
| 15 # contain the following tables: table with revision number, table with actual | 14 # contain the following tables: table with revision number, table with actual |
| 16 # diff, table with dropdown menu, table with legend, a border table and a table | 15 # diff, table with dropdown menu, table with legend, a border table and a table |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 71 revision_object['author'] = revision.getElementsByTagName( | 70 revision_object['author'] = revision.getElementsByTagName( |
| 72 'author')[0].firstChild.nodeValue | 71 'author')[0].firstChild.nodeValue |
| 73 | 72 |
| 74 # Get the revision number from xml. | 73 # Get the revision number from xml. |
| 75 revision_number = int(revision.getAttribute('revision')) | 74 revision_number = int(revision.getAttribute('revision')) |
| 76 | 75 |
| 77 # Iterate through the changed paths in the CL. | 76 # Iterate through the changed paths in the CL. |
| 78 paths = revision.getElementsByTagName('paths') | 77 paths = revision.getElementsByTagName('paths') |
| 79 if paths: | 78 if paths: |
| 80 for changed_path in paths[0].getElementsByTagName('path'): | 79 for changed_path in paths[0].getElementsByTagName('path'): |
| 81 # Get path, file action and file name from the xml. | 80 # Get path, file action and file name from the xml. |
|
stgao
2014/08/22 06:50:54
comment is not updated.
jeun
2014/08/22 22:58:44
Done.
| |
| 82 file_path = changed_path.firstChild.nodeValue | 81 file_path = changed_path.firstChild.nodeValue |
| 83 file_action = changed_path.getAttribute('action') | 82 file_change_type = changed_path.getAttribute('action') |
| 84 changed_file = os.path.basename(file_path) | 83 |
| 84 if file_path.startswith('/trunk/'): | |
| 85 file_path = file_path[len('/trunk/'):] | |
| 85 | 86 |
| 86 # Add file to the map. | 87 # Add file to the map. |
| 87 if changed_file not in file_to_revision_map: | 88 if file_path not in file_to_revision_map: |
| 88 file_to_revision_map[changed_file] = [] | 89 file_to_revision_map[file_path] = [] |
| 89 file_to_revision_map[changed_file].append( | 90 file_to_revision_map[file_path].append( |
| 90 (revision_number, file_action, file_path)) | 91 (revision_number, file_change_type)) |
| 91 | 92 |
| 92 # Set commit message of the CL. | 93 # Set commit message of the CL. |
| 93 revision_object['message'] = revision.getElementsByTagName('msg')[ | 94 revision_object['message'] = revision.getElementsByTagName('msg')[ |
| 94 0].firstChild.nodeValue | 95 0].firstChild.nodeValue |
| 95 | 96 |
| 96 # Set url of this CL. | 97 # Set url of this CL. |
| 97 revision_url = url_map['revision_url'] % revision_number | 98 revision_url = url_map['revision_url'] % revision_number |
| 98 revision_object['url'] = revision_url | 99 revision_object['url'] = revision_url |
| 99 | 100 |
| 100 # Add this CL to the revision map. | 101 # Add this CL to the revision map. |
| 101 revision_map[revision_number] = revision_object | 102 revision_map[revision_number] = revision_object |
| 102 | 103 |
| 103 return (revision_map, file_to_revision_map) | 104 return (revision_map, file_to_revision_map) |
| 104 | 105 |
| 105 def ParseLineDiff(self, path, component, file_action, revision_number): | 106 def ParseLineDiff(self, path, component, file_change_type, revision_number): |
| 106 changed_line_numbers = [] | 107 changed_line_numbers = [] |
| 107 changed_line_contents = [] | 108 changed_line_contents = [] |
| 108 | 109 |
| 109 url_map = self.component_to_urls_map.get(component) | 110 url_map = self.component_to_urls_map.get(component) |
| 110 if not url_map: | 111 if not url_map: |
| 111 logging.error('Component %s is not currently supported.', component) | 112 logging.error('Component %s is not currently supported.', component) |
| 112 return (None, None, None) | 113 return (None, None, None) |
| 113 | 114 |
| 114 # If the file is added (not modified), treat it as if it is not changed. | 115 # If the file is added (not modified), treat it as if it is not changed. |
| 115 backup_url = url_map['revision_url'] % revision_number | 116 backup_url = url_map['revision_url'] % revision_number |
| 116 if file_action == 'A': | 117 if file_change_type == 'A': |
| 117 return (backup_url, changed_line_numbers, changed_line_contents) | 118 return (backup_url, changed_line_numbers, changed_line_contents) |
| 118 | 119 |
| 119 # Retrieve data from the url. If no data is retrieved, return empty lists. | 120 # Retrieve data from the url. If no data is retrieved, return empty lists. |
| 120 url = url_map['diff_url'] % (path, revision_number - 1, | 121 url = url_map['diff_url'] % (path, revision_number - 1, |
| 121 revision_number, revision_number) | 122 revision_number, revision_number) |
| 122 data = crash_utils.GetDataFromURL(url) | 123 data = crash_utils.GetDataFromURL(url) |
| 123 if not data: | 124 if not data: |
| 124 logging.error('Failed to get line changes from %s.', url) | 125 logging.error('Failed to get line changes from %s.', url) |
| 125 return (backup_url, changed_line_numbers, changed_line_contents) | 126 return (backup_url, changed_line_numbers, changed_line_contents) |
| 126 | 127 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 blame_html = minidom.parseString(data) | 213 blame_html = minidom.parseString(data) |
| 213 | 214 |
| 214 title = blame_html.getElementsByTagName('title') | 215 title = blame_html.getElementsByTagName('title') |
| 215 # If the returned html page is an exception page, return None. | 216 # If the returned html page is an exception page, return None. |
| 216 if title[0].firstChild.nodeValue == 'ViewVC Exception': | 217 if title[0].firstChild.nodeValue == 'ViewVC Exception': |
| 217 logging.error('Failed to retrieve blame information from %s.', url) | 218 logging.error('Failed to retrieve blame information from %s.', url) |
| 218 return None | 219 return None |
| 219 | 220 |
| 220 # Each of the blame result is in <tr>. | 221 # Each of the blame result is in <tr>. |
| 221 blame_results = blame_html.getElementsByTagName('tr') | 222 blame_results = blame_html.getElementsByTagName('tr') |
| 222 blame_result = blame_results[line] | 223 try: |
| 224 blame_result = blame_results[line] | |
| 225 except IndexError: | |
| 226 logging.error('Failed to retrieve blame information from %s.', url) | |
| 227 return None | |
| 223 | 228 |
| 224 # There must be 4 <td> for each <tr>. If not, this page is wrong. | 229 # There must be 4 <td> for each <tr>. If not, this page is wrong. |
| 225 tds = blame_result.getElementsByTagName('td') | 230 tds = blame_result.getElementsByTagName('td') |
| 226 if len(tds) != 4: | 231 if len(tds) != 4: |
| 227 logging.error('Failed to retrieve blame information from %s.', url) | 232 logging.error('Failed to retrieve blame information from %s.', url) |
| 228 return None | 233 return None |
| 229 | 234 |
| 230 # The third <td> has the line content, separated by <span>s. Combine | 235 # The third <td> has the line content, separated by <span>s. Combine |
| 231 # those to get a string of changed line. If it has nothing, the line | 236 # those to get a string of changed line. If it has nothing, the line |
| 232 # is empty. | 237 # is empty. |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 250 blame_result = blame_results[line] | 255 blame_result = blame_results[line] |
| 251 tds = blame_result.getElementsByTagName('td') | 256 tds = blame_result.getElementsByTagName('td') |
| 252 author = tds[1].firstChild.nodeValue | 257 author = tds[1].firstChild.nodeValue |
| 253 | 258 |
| 254 # Revision can either be in hyperlink or plain text. | 259 # Revision can either be in hyperlink or plain text. |
| 255 try: | 260 try: |
| 256 revision = tds[2].getElementsByTagName('a')[0].firstChild.nodeValue | 261 revision = tds[2].getElementsByTagName('a')[0].firstChild.nodeValue |
| 257 except IndexError: | 262 except IndexError: |
| 258 revision = tds[2].firstChild.nodeValue | 263 revision = tds[2].firstChild.nodeValue |
| 259 | 264 |
| 265 (revision_info, _) = self.ParseChangelog(component, revision, revision) | |
| 266 message = revision_info[int(revision)]['message'] | |
| 267 | |
| 260 # Return the parsed information. | 268 # Return the parsed information. |
| 261 revision_url = url_map['revision_url'] % int(revision) | 269 revision_url = url_map['revision_url'] % int(revision) |
| 262 return (line_content, revision, author, revision_url) | 270 return (line_content, revision, author, revision_url, message) |
| OLD | NEW |