зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1401309 - [mozversioncontrol] Add ability to get outgoing files, r=gps
This adds 'get_outgoing_files'. First it automatically attempts to find the upstream remote the current change is based on, then returns all files changed in the local branch. If an upstream remote can't be detected, it raises MissingUpstreamRepo MozReview-Commit-ID: 9zSB9EdwVU8 --HG-- extra : rebase_source : e352d6d471644ef9eda76b972b789d6b54449471
This commit is contained in:
Родитель
13b127e919
Коммит
8bee138c46
|
@ -18,6 +18,22 @@ class MissingVCSTool(Exception):
|
|||
"""Represents a failure to find a version control tool binary."""
|
||||
|
||||
|
||||
class MissingVCSInfo(Exception):
|
||||
"""Represents a general failure to resolve a VCS interface."""
|
||||
|
||||
|
||||
class MissingConfigureInfo(MissingVCSInfo):
|
||||
"""Represents error finding VCS info from configure data."""
|
||||
|
||||
|
||||
class InvalidRepoPath(Exception):
|
||||
"""Represents a failure to find a VCS repo at a specified path."""
|
||||
|
||||
|
||||
class MissingUpstreamRepo(Exception):
|
||||
"""Represents a failure to automatically detect an upstream repo."""
|
||||
|
||||
|
||||
def get_tool_path(tool):
|
||||
"""Obtain the path of `tool`."""
|
||||
if os.path.isabs(tool) and os.path.exists(tool):
|
||||
|
@ -98,6 +114,10 @@ class Repository(object):
|
|||
Returns a bool.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_upstream(self):
|
||||
"""Reference to the upstream remote."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_changed_files(self, diff_filter, mode='unstaged'):
|
||||
"""Return a list of files that are changed in this repository's
|
||||
|
@ -116,6 +136,16 @@ class Repository(object):
|
|||
affect on git. Defaults to 'unstaged'.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_outgoing_files(self, diff_filter, upstream='default'):
|
||||
"""Return a list of changed files compared to upstream.
|
||||
|
||||
``diff_filter`` works the same as `get_changed_files`.
|
||||
``upstream`` is a remote ref to compare against. If unspecified,
|
||||
this will be determined automatically. If there is no remote ref,
|
||||
a MissingUpstreamRepo exception will be raised.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def add_remove_files(self, path):
|
||||
'''Add and remove files under `path` in this repository's working copy.
|
||||
|
@ -205,6 +235,9 @@ class HgRepository(Repository):
|
|||
|
||||
return False
|
||||
|
||||
def get_upstream(self):
|
||||
return 'default'
|
||||
|
||||
def _format_diff_filter(self, diff_filter):
|
||||
df = diff_filter.lower()
|
||||
assert all(f in self._valid_diff_filter for f in df)
|
||||
|
@ -221,6 +254,20 @@ class HgRepository(Repository):
|
|||
# Use --no-status to print just the filename.
|
||||
return self._run('status', '--no-status', '-{}'.format(df)).splitlines()
|
||||
|
||||
def get_outgoing_files(self, diff_filter='ADM', upstream='default'):
|
||||
df = self._format_diff_filter(diff_filter)
|
||||
|
||||
template = ''
|
||||
if 'a' in df:
|
||||
template += "{file_adds % '\\n{file}'}"
|
||||
if 'd' in df:
|
||||
template += "{file_dels % '\\n{file}'}"
|
||||
if 'm' in df:
|
||||
template += "{file_mods % '\\n{file}'}"
|
||||
|
||||
return self._run('outgoing', '-r', '.', '--quiet',
|
||||
'--template', template, upstream).split()
|
||||
|
||||
def add_remove_files(self, path):
|
||||
args = ['addremove', path]
|
||||
if self.tool_version >= b'3.9':
|
||||
|
@ -262,6 +309,15 @@ class GitRepository(Repository):
|
|||
# Not yet implemented.
|
||||
return False
|
||||
|
||||
def get_upstream(self):
|
||||
ref = self._run('symbolic-ref', '-q', 'HEAD').strip()
|
||||
upstream = self._run('for-each-ref', '--format=%(upstream:short)', ref).strip()
|
||||
|
||||
if not upstream:
|
||||
raise MissingUpstreamRepo("Could not detect an upstream repository.")
|
||||
|
||||
return upstream
|
||||
|
||||
def get_changed_files(self, diff_filter='ADM', mode='unstaged'):
|
||||
assert all(f.lower() in self._valid_diff_filter for f in diff_filter)
|
||||
|
||||
|
@ -273,6 +329,16 @@ class GitRepository(Repository):
|
|||
|
||||
return self._run(*cmd).splitlines()
|
||||
|
||||
def get_outgoing_files(self, diff_filter='ADM', upstream='default'):
|
||||
assert all(f.lower() in self._valid_diff_filter for f in diff_filter)
|
||||
|
||||
if upstream == 'default':
|
||||
upstream = self.get_upstream()
|
||||
|
||||
compare = '{}..HEAD'.format(upstream)
|
||||
return self._run('log', '--name-only', '--diff-filter={}'.format(diff_filter.upper()),
|
||||
'--oneline', '--pretty=format:', compare).splitlines()
|
||||
|
||||
def add_remove_files(self, path):
|
||||
self._run('add', path)
|
||||
|
||||
|
@ -292,10 +358,6 @@ class GitRepository(Repository):
|
|||
return not len(self._run(*args).strip())
|
||||
|
||||
|
||||
class InvalidRepoPath(Exception):
|
||||
"""Represents a failure to find a VCS repo at a specified path."""
|
||||
|
||||
|
||||
def get_repository_object(path, hg='hg', git='git'):
|
||||
'''Get a repository object for the repository at `path`.
|
||||
If `path` is not a known VCS repository, raise an exception.
|
||||
|
@ -309,14 +371,6 @@ def get_repository_object(path, hg='hg', git='git'):
|
|||
path)
|
||||
|
||||
|
||||
class MissingVCSInfo(Exception):
|
||||
"""Represents a general failure to resolve a VCS interface."""
|
||||
|
||||
|
||||
class MissingConfigureInfo(MissingVCSInfo):
|
||||
"""Represents error finding VCS info from configure data."""
|
||||
|
||||
|
||||
def get_repository_from_build_config(config):
|
||||
"""Obtain a repository from the build configuration.
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче