Chromium Code Reviews| 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 cgi | 5 import cgi |
| 6 import ConfigParser | 6 import ConfigParser |
| 7 import json | 7 import json |
| 8 import logging | 8 import logging |
| 9 import os | 9 import os |
| 10 import time | 10 import time |
| 11 import urllib2 | 11 import urllib2 |
| 12 | 12 |
| 13 from result import Result | 13 from result import Result |
| 14 | 14 |
| 15 | 15 |
| 16 INFINITY = float('inf') | 16 INFINITY = float('inf') |
| 17 | 17 |
| 18 | 18 |
| 19 def ParseURLsFromConfig(file_name): | 19 def ParseURLsFromConfig(file_name): |
| 20 """Parses URLS from the config file. | 20 """Parses URLS from the config file. |
| 21 | 21 |
| 22 The file should be in python config format, where svn section is in the | 22 The file should be in python config format, where svn section is in the |
| 23 format "svn:component_path", except for git URLs and codereview URL. | 23 format "svn:component_path". |
| 24 Each of the section for svn should contain changelog_url, revision_url, | 24 Each of the section for svn should contain changelog_url, revision_url, |
| 25 diff_url and blame_url. | 25 diff_url and blame_url. |
| 26 | 26 |
| 27 Args: | 27 Args: |
| 28 file_name: The name of the file that contains URL information. | 28 file_name: The name of the file that contains URL information. |
| 29 | 29 |
| 30 Returns: | 30 Returns: |
| 31 A dictionary that maps repository type to list of URLs. For svn, it maps | 31 A dictionary that maps repository type to list of URLs. For svn, it maps |
| 32 key 'svn' to another dictionary, which maps component path to the URLs | 32 key 'svn' to another dictionary, which maps component path to the URLs |
| 33 as explained above. For git, it maps to the URLs as explained above. | 33 as explained above. For git, it maps to the URLs as explained above. |
| 34 Codereview maps to codereview API url. | |
| 35 """ | 34 """ |
| 36 config = ConfigParser.ConfigParser() | 35 config = ConfigParser.ConfigParser() |
| 37 | 36 |
| 38 # Get the absolute path of the config file, and read the file. If it fails, | 37 # Get the absolute path of the config file, and read the file. If it fails, |
| 39 # return none. | 38 # return none. |
| 40 config_file_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), | 39 config_file_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), |
| 41 file_name) | 40 file_name) |
| 42 config.read(config_file_path) | 41 config.read(config_file_path) |
| 43 if not config: | 42 if not config: |
| 44 logging.error('Config file with URLs does not exist.') | 43 logging.error('Config file with URLs does not exist.') |
| 45 return None | 44 return None |
| 46 | 45 |
| 47 # Iterate through the config file, check for sections. | 46 # Iterate through the config file, check for sections. |
| 48 repository_type_to_url_map = {} | 47 parsed_config = {} |
| 49 for section in config.sections(): | 48 for section in config.sections(): |
| 50 # These two do not need another layer of dictionary, so add it and go | 49 # These two do not need another layer of dictionary, so add it and go |
| 51 # to next section. | 50 # to next section. |
| 52 if section == 'git' or section == 'codereview': | 51 if ':' not in section: |
| 53 for option in config.options(section): | 52 for option in config.options(section): |
| 54 if section not in repository_type_to_url_map: | 53 if section not in parsed_config: |
| 55 repository_type_to_url_map[section] = {} | 54 parsed_config[section] = {} |
| 56 | 55 |
| 57 url = config.get(section, option) | 56 url = config.get(section, option) |
| 58 repository_type_to_url_map[section][option] = url | 57 parsed_config[section][option] = url |
| 59 | 58 |
| 60 continue | 59 continue |
| 61 | 60 |
| 62 # Get repository type and component name from the section name. | 61 # Get repository type and component name from the section name. |
| 63 repository_type_and_component = section.split(':') | 62 repository_type_and_component = section.split(':') |
| 64 repository_type = repository_type_and_component[0] | 63 repository_type = repository_type_and_component[0] |
| 65 component_path = repository_type_and_component[1] | 64 component_path = repository_type_and_component[1] |
| 66 | 65 |
| 67 # Add 'svn' as the key, if it is not already there. | 66 # Add 'svn' as the key, if it is not already there. |
| 68 if repository_type not in repository_type_to_url_map: | 67 if repository_type not in parsed_config: |
| 69 repository_type_to_url_map[repository_type] = {} | 68 parsed_config[repository_type] = {} |
| 70 url_map_for_repository = repository_type_to_url_map[repository_type] | 69 url_map_for_repository = parsed_config[repository_type] |
| 71 | 70 |
| 72 # Add the path to the 'svn', if it is not already there. | 71 # Add the path to the 'svn', if it is not already there. |
| 73 if component_path not in url_map_for_repository: | 72 if component_path not in url_map_for_repository: |
| 74 url_map_for_repository[component_path] = {} | 73 url_map_for_repository[component_path] = {} |
| 75 type_to_url = url_map_for_repository[component_path] | 74 type_to_url = url_map_for_repository[component_path] |
| 76 | 75 |
| 77 # Add all URLs to this map. | 76 # Add all URLs to this map. |
| 78 for option in config.options(section): | 77 for option in config.options(section): |
| 79 url = config.get(section, option) | 78 url = config.get(section, option) |
| 80 type_to_url[option] = url | 79 type_to_url[option] = url |
| 81 | 80 |
| 82 return repository_type_to_url_map | 81 return parsed_config |
| 83 | 82 |
| 84 | 83 |
| 85 def NormalizePathLinux(path, parsed_deps): | 84 def NormalizePathLinux(path, parsed_deps): |
| 86 """Normalizes linux path. | 85 """Normalizes linux path. |
| 87 | 86 |
| 88 Args: | 87 Args: |
| 89 path: A string representing a path. | 88 path: A string representing a path. |
| 90 parsed_deps: A map from component path to its component name, repository, | 89 parsed_deps: A map from component path to its component name, repository, |
| 91 etc. | 90 etc. |
| 92 | 91 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 116 | 115 |
| 117 # Normalize the path by stripping everything off the component's relative | 116 # Normalize the path by stripping everything off the component's relative |
| 118 # path. | 117 # path. |
| 119 normalized_path = normalized_path.split(new_path,1)[1] | 118 normalized_path = normalized_path.split(new_path,1)[1] |
| 120 | 119 |
| 121 # Add 'src/' or 'Source/' at the front of the normalized path, depending | 120 # Add 'src/' or 'Source/' at the front of the normalized path, depending |
| 122 # on what prefix the component path uses. For example, blink uses | 121 # on what prefix the component path uses. For example, blink uses |
| 123 # 'Source' but chromium uses 'src/', and blink component path is | 122 # 'Source' but chromium uses 'src/', and blink component path is |
| 124 # 'src/third_party/WebKit/Source', so add 'Source/' in front of the | 123 # 'src/third_party/WebKit/Source', so add 'Source/' in front of the |
| 125 # normalized path. | 124 # normalized path. |
| 126 if not normalized_path.startswith('src/') or \ | 125 if not (normalized_path.startswith('src/') or \ |
|
stgao
2014/08/15 19:42:38
Ending \ could be removed.
| |
| 127 normalized_path.startswith('Source/'): | 126 normalized_path.startswith('Source/')): |
| 128 | 127 |
| 129 if (new_path.lower().endswith('src/') or | 128 if (new_path.lower().endswith('src/') or |
| 130 new_path.lower().endswith('source/')): | 129 new_path.lower().endswith('source/')): |
| 131 normalized_path = new_path.split('/')[-2] + '/' + normalized_path | 130 normalized_path = new_path.split('/')[-2] + '/' + normalized_path |
| 132 | 131 |
| 133 else: | 132 else: |
| 134 normalized_path = 'src/' + normalized_path | 133 normalized_path = 'src/' + normalized_path |
| 135 | 134 |
| 136 component_name = parsed_deps[component_path]['name'] | 135 component_name = parsed_deps[component_path]['name'] |
| 137 | 136 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 JSON object if the string represents a JSON object, None otherwise. | 176 JSON object if the string represents a JSON object, None otherwise. |
| 178 """ | 177 """ |
| 179 try: | 178 try: |
| 180 data = json.loads(json_string) | 179 data = json.loads(json_string) |
| 181 except ValueError: | 180 except ValueError: |
| 182 data = None | 181 data = None |
| 183 | 182 |
| 184 return data | 183 return data |
| 185 | 184 |
| 186 | 185 |
| 187 def GetDataFromURL(url, retries=10, sleep_time=0.1, timeout=10): | 186 def GetDataFromURL(url, retries=10, sleep_time=0.1, timeout=5): |
| 188 """Retrieves raw data from URL, tries 10 times. | 187 """Retrieves raw data from URL, tries 10 times. |
| 189 | 188 |
| 190 Args: | 189 Args: |
| 191 url: URL to get data from. | 190 url: URL to get data from. |
| 192 retries: Number of times to retry connection. | 191 retries: Number of times to retry connection. |
| 193 sleep_time: Time in seconds to wait before retrying connection. | 192 sleep_time: Time in seconds to wait before retrying connection. |
| 194 timeout: Time in seconds to wait before time out. | 193 timeout: Time in seconds to wait before time out. |
| 195 | 194 |
| 196 Returns: | 195 Returns: |
| 197 None if the data retrieval fails, or the raw data. | 196 None if the data retrieval fails, or the raw data. |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 suspected_cl = blame.revision | 432 suspected_cl = blame.revision |
| 434 revision_url = blame.url | 433 revision_url = blame.url |
| 435 component_name = blame.component_name | 434 component_name = blame.component_name |
| 436 author = blame.author | 435 author = blame.author |
| 437 reason = ( | 436 reason = ( |
| 438 'The CL changes line %s of file %s from stack %d.' % | 437 'The CL changes line %s of file %s from stack %d.' % |
| 439 (blame.line_number, blame.file, blame.stack_frame_index)) | 438 (blame.line_number, blame.file, blame.stack_frame_index)) |
| 440 # Blame object does not have review url and reviewers. | 439 # Blame object does not have review url and reviewers. |
| 441 review_url = None | 440 review_url = None |
| 442 reviewers = None | 441 reviewers = None |
| 443 line_content = blame.content | 442 line_content = blame.line_content |
| 444 | 443 |
| 445 result = Result(suspected_cl, revision_url, component_name, author, reason, | 444 result = Result(suspected_cl, revision_url, component_name, author, reason, |
| 446 review_url, reviewers, line_content) | 445 review_url, reviewers, line_content) |
| 447 result_list.append(result) | 446 result_list.append(result) |
| 448 | 447 |
| 449 return result_list | 448 return result_list |
| 450 | |
| 451 | |
| 452 def ResultListToJSON(result_list): | |
| 453 """Converts result list to JSON format. | |
| 454 | |
| 455 Args: | |
| 456 result_list: A list of result objects | |
| 457 | |
| 458 Returns: | |
| 459 A string, JSON format of the result_list. | |
| 460 | |
| 461 """ | |
| 462 return json.dumps([result.ToDictionary() for result in result_list]) | |
| OLD | NEW |