|
@@ -880,7 +880,7 @@ class InputApi(object):
|
|
|
|
|
|
def ListSubmodules(self):
|
|
def ListSubmodules(self):
|
|
"""Returns submodule paths for current change's repo."""
|
|
"""Returns submodule paths for current change's repo."""
|
|
- return scm.GIT.ListSubmodules(self.change.RepositoryRoot())
|
|
|
|
|
|
+ return self.change._repo_submodules()
|
|
|
|
|
|
@property
|
|
@property
|
|
def tbr(self):
|
|
def tbr(self):
|
|
@@ -912,9 +912,6 @@ class InputApi(object):
|
|
|
|
|
|
class _DiffCache(object):
|
|
class _DiffCache(object):
|
|
"""Caches diffs retrieved from a particular SCM."""
|
|
"""Caches diffs retrieved from a particular SCM."""
|
|
- def __init__(self, upstream=None):
|
|
|
|
- """Stores the upstream revision against which all diffs will be computed."""
|
|
|
|
- self._upstream = upstream
|
|
|
|
|
|
|
|
def GetDiff(self, path, local_root):
|
|
def GetDiff(self, path, local_root):
|
|
"""Get the diff for a particular path."""
|
|
"""Get the diff for a particular path."""
|
|
@@ -927,8 +924,11 @@ class _DiffCache(object):
|
|
|
|
|
|
class _GitDiffCache(_DiffCache):
|
|
class _GitDiffCache(_DiffCache):
|
|
"""DiffCache implementation for git; gets all file diffs at once."""
|
|
"""DiffCache implementation for git; gets all file diffs at once."""
|
|
|
|
+
|
|
def __init__(self, upstream):
|
|
def __init__(self, upstream):
|
|
- super(_GitDiffCache, self).__init__(upstream=upstream)
|
|
|
|
|
|
+ """Stores the upstream revision against which all diffs are computed."""
|
|
|
|
+ super(_GitDiffCache, self).__init__()
|
|
|
|
+ self._upstream = upstream
|
|
self._diffs_by_file = None
|
|
self._diffs_by_file = None
|
|
|
|
|
|
def GetDiff(self, path, local_root):
|
|
def GetDiff(self, path, local_root):
|
|
@@ -1138,21 +1138,13 @@ class Change(object):
|
|
'^[ \t]*(?P<key>[A-Z][A-Z_0-9]*)[ \t]*=[ \t]*(?P<value>.*?)[ \t]*$')
|
|
'^[ \t]*(?P<key>[A-Z][A-Z_0-9]*)[ \t]*=[ \t]*(?P<value>.*?)[ \t]*$')
|
|
scm = ''
|
|
scm = ''
|
|
|
|
|
|
- def __init__(self,
|
|
|
|
- name,
|
|
|
|
- description,
|
|
|
|
- local_root,
|
|
|
|
- files,
|
|
|
|
- issue,
|
|
|
|
- patchset,
|
|
|
|
- author,
|
|
|
|
- upstream=None):
|
|
|
|
|
|
+ def __init__(self, name, description, local_root, files, issue, patchset,
|
|
|
|
+ author):
|
|
if files is None:
|
|
if files is None:
|
|
files = []
|
|
files = []
|
|
self._name = name
|
|
self._name = name
|
|
# Convert root into an absolute path.
|
|
# Convert root into an absolute path.
|
|
self._local_root = os.path.abspath(local_root)
|
|
self._local_root = os.path.abspath(local_root)
|
|
- self._upstream = upstream
|
|
|
|
self.issue = issue
|
|
self.issue = issue
|
|
self.patchset = patchset
|
|
self.patchset = patchset
|
|
self.author_email = author
|
|
self.author_email = author
|
|
@@ -1165,15 +1157,13 @@ class Change(object):
|
|
assert all((isinstance(f, (list, tuple)) and len(f) == 2)
|
|
assert all((isinstance(f, (list, tuple)) and len(f) == 2)
|
|
for f in files), files
|
|
for f in files), files
|
|
|
|
|
|
- diff_cache = self._AFFECTED_FILES.DIFF_CACHE(self._upstream)
|
|
|
|
self._affected_files = [
|
|
self._affected_files = [
|
|
self._AFFECTED_FILES(path, action.strip(), self._local_root,
|
|
self._AFFECTED_FILES(path, action.strip(), self._local_root,
|
|
- diff_cache) for action, path in files
|
|
|
|
|
|
+ self._diff_cache()) for action, path in files
|
|
]
|
|
]
|
|
|
|
|
|
- def UpstreamBranch(self):
|
|
|
|
- """Returns the upstream branch for the change."""
|
|
|
|
- return self._upstream
|
|
|
|
|
|
+ def _diff_cache(self):
|
|
|
|
+ return self._AFFECTED_FILES.DIFF_CACHE()
|
|
|
|
|
|
def Name(self):
|
|
def Name(self):
|
|
"""Returns the change name."""
|
|
"""Returns the change name."""
|
|
@@ -1310,29 +1300,22 @@ class Change(object):
|
|
Returns:
|
|
Returns:
|
|
[AffectedFile(path, action), AffectedFile(path, action)]
|
|
[AffectedFile(path, action), AffectedFile(path, action)]
|
|
"""
|
|
"""
|
|
- submodule_list = scm.GIT.ListSubmodules(self.RepositoryRoot())
|
|
|
|
- files = [
|
|
|
|
- af for af in self._affected_files
|
|
|
|
- if af.LocalPath() not in submodule_list
|
|
|
|
- ]
|
|
|
|
- affected = list(filter(file_filter, files))
|
|
|
|
-
|
|
|
|
|
|
+ affected = list(filter(file_filter, self._affected_files))
|
|
if include_deletes:
|
|
if include_deletes:
|
|
return affected
|
|
return affected
|
|
return list(filter(lambda x: x.Action() != 'D', affected))
|
|
return list(filter(lambda x: x.Action() != 'D', affected))
|
|
|
|
|
|
def AffectedSubmodules(self):
|
|
def AffectedSubmodules(self):
|
|
- """Returns a list of AffectedFile instances for submodules in the change."""
|
|
|
|
- submodule_list = scm.GIT.ListSubmodules(self.RepositoryRoot())
|
|
|
|
- return [
|
|
|
|
- af for af in self._affected_files
|
|
|
|
- if af.LocalPath() in submodule_list
|
|
|
|
- ]
|
|
|
|
|
|
+ """Returns a list of AffectedFile instances for submodules in the change.
|
|
|
|
+
|
|
|
|
+ There is no SCM and no submodules, so return an empty list.
|
|
|
|
+ """
|
|
|
|
+ return []
|
|
|
|
|
|
def AffectedTestableFiles(self, include_deletes=None, **kwargs):
|
|
def AffectedTestableFiles(self, include_deletes=None, **kwargs):
|
|
"""Return a list of the existing text files in a change."""
|
|
"""Return a list of the existing text files in a change."""
|
|
if include_deletes is not None:
|
|
if include_deletes is not None:
|
|
- warn('AffectedTeestableFiles(include_deletes=%s)'
|
|
|
|
|
|
+ warn('AffectedTestableFiles(include_deletes=%s)'
|
|
' is deprecated and ignored' % str(include_deletes),
|
|
' is deprecated and ignored' % str(include_deletes),
|
|
category=DeprecationWarning,
|
|
category=DeprecationWarning,
|
|
stacklevel=2)
|
|
stacklevel=2)
|
|
@@ -1386,11 +1369,38 @@ class Change(object):
|
|
files = self.AffectedFiles(file_filter=owners_file_filter)
|
|
files = self.AffectedFiles(file_filter=owners_file_filter)
|
|
return {f.LocalPath(): f.OldContents() for f in files}
|
|
return {f.LocalPath(): f.OldContents() for f in files}
|
|
|
|
|
|
|
|
+ def _repo_submodules(self):
|
|
|
|
+ """Returns submodule paths for current change's repo.
|
|
|
|
+
|
|
|
|
+ There is no SCM, so return an empty list.
|
|
|
|
+ """
|
|
|
|
+ return []
|
|
|
|
+
|
|
|
|
|
|
class GitChange(Change):
|
|
class GitChange(Change):
|
|
_AFFECTED_FILES = GitAffectedFile
|
|
_AFFECTED_FILES = GitAffectedFile
|
|
scm = 'git'
|
|
scm = 'git'
|
|
|
|
|
|
|
|
+ def __init__(self, *args, upstream, **kwargs):
|
|
|
|
+ self._upstream = upstream
|
|
|
|
+ super(GitChange, self).__init__(*args)
|
|
|
|
+
|
|
|
|
+ # List of submodule paths in the repo.
|
|
|
|
+ self._submodules = None
|
|
|
|
+
|
|
|
|
+ def _diff_cache(self):
|
|
|
|
+ return self._AFFECTED_FILES.DIFF_CACHE(self._upstream)
|
|
|
|
+
|
|
|
|
+ def _repo_submodules(self):
|
|
|
|
+ """Returns submodule paths for current change's repo."""
|
|
|
|
+ if not self._submodules:
|
|
|
|
+ self._submodules = scm.GIT.ListSubmodules(self.RepositoryRoot())
|
|
|
|
+ return self._submodules
|
|
|
|
+
|
|
|
|
+ def UpstreamBranch(self):
|
|
|
|
+ """Returns the upstream branch for the change."""
|
|
|
|
+ return self._upstream
|
|
|
|
+
|
|
def AllFiles(self, root=None):
|
|
def AllFiles(self, root=None):
|
|
"""List all files under source control in the repo."""
|
|
"""List all files under source control in the repo."""
|
|
root = root or self.RepositoryRoot()
|
|
root = root or self.RepositoryRoot()
|
|
@@ -1398,6 +1408,33 @@ class GitChange(Change):
|
|
['git', '-c', 'core.quotePath=false', 'ls-files', '--', '.'],
|
|
['git', '-c', 'core.quotePath=false', 'ls-files', '--', '.'],
|
|
cwd=root).decode('utf-8', 'ignore').splitlines()
|
|
cwd=root).decode('utf-8', 'ignore').splitlines()
|
|
|
|
|
|
|
|
+ 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.
|
|
|
|
+ file_filter: An additional filter to apply.
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ [AffectedFile(path, action), AffectedFile(path, action)]
|
|
|
|
+ """
|
|
|
|
+ files = [
|
|
|
|
+ af for af in self._affected_files
|
|
|
|
+ if af.LocalPath() not in self._repo_submodules()
|
|
|
|
+ ]
|
|
|
|
+ affected = list(filter(file_filter, files))
|
|
|
|
+
|
|
|
|
+ if include_deletes:
|
|
|
|
+ return affected
|
|
|
|
+ return list(filter(lambda x: x.Action() != 'D', affected))
|
|
|
|
+
|
|
|
|
+ def AffectedSubmodules(self):
|
|
|
|
+ """Returns a list of AffectedFile instances for submodules in the change."""
|
|
|
|
+ return [
|
|
|
|
+ af for af in self._affected_files
|
|
|
|
+ if af.LocalPath() in self._repo_submodules()
|
|
|
|
+ ]
|
|
|
|
+
|
|
|
|
|
|
def ListRelevantPresubmitFiles(files, root):
|
|
def ListRelevantPresubmitFiles(files, root):
|
|
"""Finds all presubmit files that apply to a given set of source files.
|
|
"""Finds all presubmit files that apply to a given set of source files.
|
|
@@ -1980,15 +2017,13 @@ def _parse_change(parser, options):
|
|
ignore_submodules=False)
|
|
ignore_submodules=False)
|
|
logging.info('Found %d file(s).', len(change_files))
|
|
logging.info('Found %d file(s).', len(change_files))
|
|
|
|
|
|
- change_class = GitChange if change_scm == 'git' else Change
|
|
|
|
- return change_class(options.name,
|
|
|
|
- options.description,
|
|
|
|
- options.root,
|
|
|
|
- change_files,
|
|
|
|
- options.issue,
|
|
|
|
- options.patchset,
|
|
|
|
- options.author,
|
|
|
|
- upstream=options.upstream)
|
|
|
|
|
|
+ change_args = [
|
|
|
|
+ options.name, options.description, options.root, change_files,
|
|
|
|
+ options.issue, options.patchset, options.author
|
|
|
|
+ ]
|
|
|
|
+ if change_scm == 'git':
|
|
|
|
+ return GitChange(*change_args, upstream=options.upstream)
|
|
|
|
+ return Change(*change_args)
|
|
|
|
|
|
|
|
|
|
def _parse_gerrit_options(parser, options):
|
|
def _parse_gerrit_options(parser, options):
|