Chromium Code Reviews| Index: presubmit_support.py |
| diff --git a/presubmit_support.py b/presubmit_support.py |
| index fe3de7b05907f51e080b2093623f0b573c13fc0c..a1b6dc052571edba48c5267270919626e89e15df 100755 |
| --- a/presubmit_support.py |
| +++ b/presubmit_support.py |
| @@ -411,35 +411,7 @@ class InputApi(object): |
| """ |
| return self._current_presubmit_path |
| - def DepotToLocalPath(self, depot_path): |
| - """Translate a depot path to a local path (relative to client root). |
| - |
| - Args: |
| - Depot path as a string. |
| - |
| - Returns: |
| - The local path of the depot path under the user's current client, or None |
| - if the file is not mapped. |
| - |
| - Remember to check for the None case and show an appropriate error! |
| - """ |
| - return scm.SVN.CaptureLocalInfo([depot_path], self.change.RepositoryRoot() |
| - ).get('Path') |
| - |
| - def LocalToDepotPath(self, local_path): |
| - """Translate a local path to a depot path. |
| - |
| - Args: |
| - Local path (relative to current directory, or absolute) as a string. |
| - |
| - Returns: |
| - The depot path (SVN URL) of the file if mapped, otherwise None. |
| - """ |
| - return scm.SVN.CaptureLocalInfo([local_path], self.change.RepositoryRoot() |
| - ).get('URL') |
| - |
| - def AffectedFiles(self, include_dirs=False, include_deletes=True, |
|
Dan Beam
2016/11/29 19:13:45
can you grep for keywords when you remove them nex
Dan Beam
2016/11/29 19:16:29
"this broke" -> removing include_dirs=
|
| - file_filter=None): |
| + def AffectedFiles(self, include_deletes=True, file_filter=None): |
| """Same as input_api.change.AffectedFiles() except only lists files |
| (and optionally directories) in the same directory as the current presubmit |
| script, or subdirectories thereof. |
| @@ -450,34 +422,34 @@ class InputApi(object): |
| return filter( |
| lambda x: normpath(x.AbsoluteLocalPath()).startswith(dir_with_slash), |
| - self.change.AffectedFiles(include_dirs, include_deletes, file_filter)) |
| + self.change.AffectedFiles(include_deletes, file_filter)) |
| - def LocalPaths(self, include_dirs=False): |
| + def LocalPaths(self): |
| """Returns local paths of input_api.AffectedFiles().""" |
| - paths = [af.LocalPath() for af in self.AffectedFiles(include_dirs)] |
| + paths = [af.LocalPath() for af in self.AffectedFiles()] |
| logging.debug("LocalPaths: %s", paths) |
| return paths |
| - def AbsoluteLocalPaths(self, include_dirs=False): |
| + def AbsoluteLocalPaths(self): |
| """Returns absolute local paths of input_api.AffectedFiles().""" |
| - return [af.AbsoluteLocalPath() for af in self.AffectedFiles(include_dirs)] |
| + return [af.AbsoluteLocalPath() for af in self.AffectedFiles()] |
| - def ServerPaths(self, include_dirs=False): |
| - """Returns server paths of input_api.AffectedFiles().""" |
| - return [af.ServerPath() for af in self.AffectedFiles(include_dirs)] |
| - |
| - def AffectedTextFiles(self, include_deletes=None): |
| - """Same as input_api.change.AffectedTextFiles() except only lists files |
| + def AffectedTestableFiles(self, include_deletes=None): |
| + """Same as input_api.change.AffectedTestableFiles() except only lists files |
| in the same directory as the current presubmit script, or subdirectories |
| thereof. |
| """ |
| if include_deletes is not None: |
| - warn("AffectedTextFiles(include_deletes=%s)" |
| + warn("AffectedTestableFiles(include_deletes=%s)" |
| " is deprecated and ignored" % str(include_deletes), |
| category=DeprecationWarning, |
| stacklevel=2) |
| - return filter(lambda x: x.IsTextFile(), |
| - self.AffectedFiles(include_dirs=False, include_deletes=False)) |
| + return filter(lambda x: x.IsTestableFile(), |
| + self.AffectedFiles(include_deletes=False)) |
| + |
| + def AffectedTextFiles(self, include_deletes=None): |
| + """An alias to AffectedTestableFiles for backwards compatibility.""" |
| + return self.AffectedTestableFiles(include_deletes=include_deletes) |
| def FilterSourceFile(self, affected_file, white_list=None, black_list=None): |
| """Filters out files that aren't considered "source file". |
| @@ -500,13 +472,13 @@ class InputApi(object): |
| not Find(affected_file, black_list or self.DEFAULT_BLACK_LIST)) |
| def AffectedSourceFiles(self, source_file): |
| - """Filter the list of AffectedTextFiles by the function source_file. |
| + """Filter the list of AffectedTestableFiles by the function source_file. |
| If source_file is None, InputApi.FilterSourceFile() is used. |
| """ |
| if not source_file: |
| source_file = self.FilterSourceFile |
| - return filter(source_file, self.AffectedTextFiles()) |
| + return filter(source_file, self.AffectedTestableFiles()) |
| def RightHandSideLines(self, source_file_filter=None): |
| """An iterator over all text lines in "new" version of changed files. |
| @@ -579,19 +551,6 @@ class _DiffCache(object): |
| raise NotImplementedError() |
| -class _SvnDiffCache(_DiffCache): |
| - """DiffCache implementation for subversion.""" |
| - def __init__(self, *args, **kwargs): |
| - super(_SvnDiffCache, self).__init__(*args, **kwargs) |
| - self._diffs_by_file = {} |
| - |
| - def GetDiff(self, path, local_root): |
| - if path not in self._diffs_by_file: |
| - self._diffs_by_file[path] = scm.SVN.GenerateDiff([path], local_root, |
| - False, None) |
| - return self._diffs_by_file[path] |
| - |
| - |
| class _GitDiffCache(_DiffCache): |
| """DiffCache implementation for git; gets all file diffs at once.""" |
| def __init__(self, upstream): |
| @@ -646,19 +605,11 @@ class AffectedFile(object): |
| self._action = action |
| self._local_root = repository_root |
| self._is_directory = None |
| - self._properties = {} |
| self._cached_changed_contents = None |
| self._cached_new_contents = None |
| self._diff_cache = diff_cache |
| logging.debug('%s(%s)', self.__class__.__name__, self._path) |
| - def ServerPath(self): |
| - """Returns a path string that identifies the file in the SCM system. |
| - |
| - Returns the empty string if the file does not exist in SCM. |
| - """ |
| - return '' |
| - |
| def LocalPath(self): |
| """Returns the path of this file on the local disk relative to client root. |
| """ |
| @@ -669,32 +620,22 @@ class AffectedFile(object): |
| """ |
| return os.path.abspath(os.path.join(self._local_root, self.LocalPath())) |
| - def IsDirectory(self): |
| - """Returns true if this object is a directory.""" |
| - if self._is_directory is None: |
| - path = self.AbsoluteLocalPath() |
| - self._is_directory = (os.path.exists(path) and |
| - os.path.isdir(path)) |
| - return self._is_directory |
| - |
| def Action(self): |
| """Returns the action on this opened file, e.g. A, M, D, etc.""" |
| # TODO(maruel): Somewhat crappy, Could be "A" or "A +" for svn but |
| # different for other SCM. |
| return self._action |
| - def Property(self, property_name): |
| - """Returns the specified SCM property of this file, or None if no such |
| - property. |
| - """ |
| - return self._properties.get(property_name, None) |
| - |
| - def IsTextFile(self): |
| + def IsTestableFile(self): |
| """Returns True if the file is a text file and not a binary file. |
| Deleted files are not text file.""" |
| raise NotImplementedError() # Implement when needed |
| + def IsTextFile(self): |
| + """An alias to IsTestableFile for backwards compatibility.""" |
| + return self.IsTestableFile() |
| + |
| def NewContents(self): |
| """Returns an iterator over the lines in the new version of file. |
| @@ -706,12 +647,11 @@ class AffectedFile(object): |
| """ |
| if self._cached_new_contents is None: |
| self._cached_new_contents = [] |
| - if not self.IsDirectory(): |
| - try: |
| - self._cached_new_contents = gclient_utils.FileRead( |
| - self.AbsoluteLocalPath(), 'rU').splitlines() |
| - except IOError: |
| - pass # File not found? That's fine; maybe it was deleted. |
| + try: |
| + self._cached_new_contents = gclient_utils.FileRead( |
| + self.AbsoluteLocalPath(), 'rU').splitlines() |
| + except IOError: |
| + pass # File not found? That's fine; maybe it was deleted. |
| return self._cached_new_contents[:] |
| def ChangedContents(self): |
| @@ -727,9 +667,6 @@ class AffectedFile(object): |
| self._cached_changed_contents = [] |
| line_num = 0 |
| - if self.IsDirectory(): |
| - return [] |
| - |
| for line in self.GenerateScmDiff().splitlines(): |
| m = re.match(r'^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@', line) |
| if m: |
| @@ -748,57 +685,6 @@ class AffectedFile(object): |
| return self._diff_cache.GetDiff(self.LocalPath(), self._local_root) |
| -class SvnAffectedFile(AffectedFile): |
| - """Representation of a file in a change out of a Subversion checkout.""" |
| - # Method 'NNN' is abstract in class 'NNN' but is not overridden |
| - # pylint: disable=W0223 |
| - |
| - DIFF_CACHE = _SvnDiffCache |
| - |
| - def __init__(self, *args, **kwargs): |
| - AffectedFile.__init__(self, *args, **kwargs) |
| - self._server_path = None |
| - self._is_text_file = None |
| - |
| - def ServerPath(self): |
| - if self._server_path is None: |
| - self._server_path = scm.SVN.CaptureLocalInfo( |
| - [self.LocalPath()], self._local_root).get('URL', '') |
| - return self._server_path |
| - |
| - def IsDirectory(self): |
| - if self._is_directory is None: |
| - path = self.AbsoluteLocalPath() |
| - if os.path.exists(path): |
| - # Retrieve directly from the file system; it is much faster than |
| - # querying subversion, especially on Windows. |
| - self._is_directory = os.path.isdir(path) |
| - else: |
| - self._is_directory = scm.SVN.CaptureLocalInfo( |
| - [self.LocalPath()], self._local_root |
| - ).get('Node Kind') in ('dir', 'directory') |
| - return self._is_directory |
| - |
| - def Property(self, property_name): |
| - if not property_name in self._properties: |
| - self._properties[property_name] = scm.SVN.GetFileProperty( |
| - self.LocalPath(), property_name, self._local_root).rstrip() |
| - return self._properties[property_name] |
| - |
| - def IsTextFile(self): |
| - if self._is_text_file is None: |
| - if self.Action() == 'D': |
| - # A deleted file is not a text file. |
| - self._is_text_file = False |
| - elif self.IsDirectory(): |
| - self._is_text_file = False |
| - else: |
| - mime_type = scm.SVN.GetFileProperty( |
| - self.LocalPath(), 'svn:mime-type', self._local_root) |
| - self._is_text_file = (not mime_type or mime_type.startswith('text/')) |
| - return self._is_text_file |
| - |
| - |
| class GitAffectedFile(AffectedFile): |
| """Representation of a file in a change out of a git checkout.""" |
| # Method 'NNN' is abstract in class 'NNN' but is not overridden |
| @@ -809,39 +695,16 @@ class GitAffectedFile(AffectedFile): |
| def __init__(self, *args, **kwargs): |
| AffectedFile.__init__(self, *args, **kwargs) |
| self._server_path = None |
| - self._is_text_file = None |
| - |
| - def ServerPath(self): |
| - if self._server_path is None: |
| - raise NotImplementedError('TODO(maruel) Implement.') |
| - return self._server_path |
| - |
| - def IsDirectory(self): |
| - if self._is_directory is None: |
| - path = self.AbsoluteLocalPath() |
| - if os.path.exists(path): |
| - # Retrieve directly from the file system; it is much faster than |
| - # querying subversion, especially on Windows. |
| - self._is_directory = os.path.isdir(path) |
| - else: |
| - self._is_directory = False |
| - return self._is_directory |
| - |
| - def Property(self, property_name): |
| - if not property_name in self._properties: |
| - raise NotImplementedError('TODO(maruel) Implement.') |
| - return self._properties[property_name] |
| + self._is_testable_file = None |
| - def IsTextFile(self): |
| - if self._is_text_file is None: |
| + def IsTestableFile(self): |
| + if self._is_testable_file is None: |
| if self.Action() == 'D': |
| - # A deleted file is not a text file. |
| - self._is_text_file = False |
| - elif self.IsDirectory(): |
| - self._is_text_file = False |
| + # A deleted file is not testable. |
| + self._is_testable_file = False |
| else: |
| - self._is_text_file = os.path.isfile(self.AbsoluteLocalPath()) |
| - return self._is_text_file |
| + self._is_testable_file = os.path.isfile(self.AbsoluteLocalPath()) |
| + return self._is_testable_file |
| class Change(object): |
| @@ -943,51 +806,44 @@ class Change(object): |
| """List all files under source control in the repo.""" |
| raise NotImplementedError() |
| - def AffectedFiles(self, include_dirs=False, include_deletes=True, |
| - file_filter=None): |
| + def AffectedFiles(self, include_deletes=True, file_filter=None): |
| """Returns a list of AffectedFile instances for all files in the change. |
| Args: |
| include_deletes: If false, deleted files will be filtered out. |
| - include_dirs: True to include directories in the list |
| file_filter: An additional filter to apply. |
| Returns: |
| [AffectedFile(path, action), AffectedFile(path, action)] |
| """ |
| - if include_dirs: |
| - affected = self._affected_files |
| - else: |
| - affected = filter(lambda x: not x.IsDirectory(), self._affected_files) |
| - |
| - affected = filter(file_filter, affected) |
| + affected = filter(file_filter, self._affected_files) |
| if include_deletes: |
| return affected |
| else: |
| return filter(lambda x: x.Action() != 'D', affected) |
| - def AffectedTextFiles(self, include_deletes=None): |
| + def AffectedTestableFiles(self, include_deletes=None): |
| """Return a list of the existing text files in a change.""" |
| if include_deletes is not None: |
| - warn("AffectedTextFiles(include_deletes=%s)" |
| + warn("AffectedTeestableFiles(include_deletes=%s)" |
| " is deprecated and ignored" % str(include_deletes), |
| category=DeprecationWarning, |
| stacklevel=2) |
| - return filter(lambda x: x.IsTextFile(), |
| - self.AffectedFiles(include_dirs=False, include_deletes=False)) |
| + return filter(lambda x: x.IsTestableFile(), |
| + self.AffectedFiles(include_deletes=False)) |
| - def LocalPaths(self, include_dirs=False): |
| - """Convenience function.""" |
| - return [af.LocalPath() for af in self.AffectedFiles(include_dirs)] |
| + def AffectedTextFiles(self, include_deletes=None): |
| + """An alias to AffectedTestableFiles for backwards compatibility.""" |
| + return self.AffectedTestableFiles(include_deletes=include_deletes) |
| - def AbsoluteLocalPaths(self, include_dirs=False): |
| + def LocalPaths(self): |
| """Convenience function.""" |
| - return [af.AbsoluteLocalPath() for af in self.AffectedFiles(include_dirs)] |
| + return [af.LocalPath() for af in self.AffectedFiles()] |
| - def ServerPaths(self, include_dirs=False): |
| + def AbsoluteLocalPaths(self): |
| """Convenience function.""" |
| - return [af.ServerPath() for af in self.AffectedFiles(include_dirs)] |
| + return [af.AbsoluteLocalPath() for af in self.AffectedFiles()] |
| def RightHandSideLines(self): |
| """An iterator over all text lines in "new" version of changed files. |
| @@ -1005,19 +861,7 @@ class Change(object): |
| """ |
| return _RightHandSideLinesImpl( |
| x for x in self.AffectedFiles(include_deletes=False) |
| - if x.IsTextFile()) |
| - |
| - |
| -class SvnChange(Change): |
| - _AFFECTED_FILES = SvnAffectedFile |
| - scm = 'svn' |
| - _changelists = None |
| - |
| - def AllFiles(self, root=None): |
| - """List all files under source control in the repo.""" |
| - root = root or self.RepositoryRoot() |
| - return subprocess.check_output( |
| - ['svn', 'ls', '-R', '.'], cwd=root).splitlines() |
| + if x.IsTestableFile()) |
| class GitChange(Change): |
| @@ -1511,7 +1355,7 @@ def DoPresubmitChecks(change, |
| output.write("Running presubmit upload checks ...\n") |
| start_time = time.time() |
| presubmit_files = ListRelevantPresubmitFiles( |
| - change.AbsoluteLocalPaths(True), change.RepositoryRoot()) |
| + change.AbsoluteLocalPaths(), change.RepositoryRoot()) |
| if not presubmit_files and verbose: |
| output.write("Warning, no PRESUBMIT.py found.\n") |
| results = [] |
| @@ -1603,15 +1447,11 @@ def ParseFiles(args, recursive): |
| def load_files(options, args): |
| """Tries to determine the SCM.""" |
| - change_scm = scm.determine_scm(options.root) |
| files = [] |
| if args: |
| files = ParseFiles(args, options.recursive) |
| - if change_scm == 'svn': |
| - change_class = SvnChange |
| - if not files: |
| - files = scm.SVN.CaptureStatus([], options.root) |
| - elif change_scm == 'git': |
| + change_scm = scm.determine_scm(options.root) |
| + if change_scm == 'git': |
| change_class = GitChange |
| upstream = options.upstream or None |
| if not files: |