def run_pylint(self, path): finder = PathFinder(FileSystem()) executive = Executive() env = os.environ.copy() env['PYTHONPATH'] = os.pathsep.join([ get_blink_tools_dir(), finder.path_from_blink_source('build', 'scripts'), get_blinkpy_thirdparty_dir(), finder.path_from_blink_source('bindings', 'scripts'), finder.path_from_chromium_base('build', 'android'), finder.path_from_chromium_base('third_party', 'catapult', 'devil'), finder.path_from_chromium_base('third_party', 'pymock'), ]) return executive.run_command([ sys.executable, finder.path_from_depot_tools_base('pylint.py'), '--output-format=parseable', '--rcfile=' + finder.path_from_blink_tools('blinkpy', 'pylintrc'), path, ], env=env, error_handler=executive.ignore_error)
class DirectoryOwnersExtractor(object): def __init__(self, host): self.filesystem = host.filesystem self.finder = PathFinder(self.filesystem) self.executive = host.executive self.owner_map = None def list_owners(self, changed_files): """Looks up the owners for the given set of changed files. Args: changed_files: A list of file paths relative to the repository root. Returns: A dict mapping tuples of owner email addresses to lists of owned directories (paths relative to the root of web tests). """ email_map = collections.defaultdict(set) external_root_owners = self.finder.path_from_web_tests( 'external', 'OWNERS') for relpath in changed_files: # Try to find the first *non-empty* OWNERS file. absolute_path = self.finder.path_from_chromium_base(relpath) owners = None owners_file = self.find_owners_file(absolute_path) while owners_file: owners = self.extract_owners(owners_file) if owners: break # Found an empty OWNERS file. Try again from the parent directory. absolute_path = self.filesystem.dirname( self.filesystem.dirname(owners_file)) owners_file = self.find_owners_file(absolute_path) # Skip web_tests/external/OWNERS. if not owners or owners_file == external_root_owners: continue owned_directory = self.filesystem.dirname(owners_file) owned_directory_relpath = self.filesystem.relpath( owned_directory, self.finder.web_tests_dir()) email_map[tuple(owners)].add(owned_directory_relpath) return { owners: sorted(owned_directories) for owners, owned_directories in email_map.iteritems() } def find_owners_file(self, start_path): """Finds the first enclosing OWNERS file for a given path. Starting from the given path, walks up the directory tree until the first OWNERS file is found or web_tests/external is reached. Args: start_path: A relative path from the root of the repository, or an absolute path. The path can be a file or a directory. Returns: The absolute path to the first OWNERS file found; None if not found or if start_path is outside of web_tests/external. """ abs_start_path = (start_path if self.filesystem.isabs(start_path) else self.finder.path_from_chromium_base(start_path)) directory = (abs_start_path if self.filesystem.isdir(abs_start_path) else self.filesystem.dirname(abs_start_path)) external_root = self.finder.path_from_web_tests('external') if not directory.startswith(external_root): return None # Stop at web_tests, which is the parent of external_root. while directory != self.finder.web_tests_dir(): owners_file = self.filesystem.join(directory, 'OWNERS') if self.filesystem.isfile( self.finder.path_from_chromium_base(owners_file)): return owners_file directory = self.filesystem.dirname(directory) return None def extract_owners(self, owners_file): """Extracts owners from an OWNERS file. Args: owners_file: An absolute path to an OWNERS file. Returns: A list of valid owners (email addresses). """ contents = self._read_text_file(owners_file) email_regexp = re.compile(BASIC_EMAIL_REGEXP) addresses = [] for line in contents.splitlines(): line = line.strip() if email_regexp.match(line): addresses.append(line) return addresses def extract_component(self, owners_file): """Extracts the component from an OWNERS file. Args: owners_file: An absolute path to an OWNERS file. Returns: A string, or None if not found. """ dir_metadata = self._read_dir_metadata(owners_file) if dir_metadata and dir_metadata.component: return dir_metadata.component contents = self._read_text_file(owners_file) search = re.search(COMPONENT_REGEXP, contents, re.MULTILINE) if search: return search.group(1) return None def is_wpt_notify_enabled(self, owners_file): """Checks if the OWNERS file enables WPT-NOTIFY. Args: owners_file: An absolute path to an OWNERS file. Returns: A boolean. """ dir_metadata = self._read_dir_metadata(owners_file) if dir_metadata and dir_metadata.should_notify is not None: return dir_metadata.should_notify contents = self._read_text_file(owners_file) return bool(re.search(WPT_NOTIFY_REGEXP, contents, re.MULTILINE)) @memoized def _read_text_file(self, path): return self.filesystem.read_text_file(path) @memoized def _read_dir_metadata(self, path): """Read the content from a path. Args: path: An absolute path. Returns: A WPTDirMetadata object, or None if not found. """ root_path = self.finder.web_tests_dir() dir_path = self.filesystem.dirname(path) # dirmd starts with an absolute directory path, `dir_path`, traverses all # parent directories and stops at `root_path` to find the first available DIR_METADATA # file. `root_path` is the web_tests directory. json_data = self.executive.run_command([ self.finder.path_from_depot_tools_base('dirmd'), 'compute', '-root', root_path, dir_path ]) try: data = json.loads(json_data) except ValueError: return None relative_path = self.filesystem.relpath(dir_path, root_path) return WPTDirMetadata(data, relative_path)