Bug 1313194 - Add --outgoing argument to mozlint. r?alhal
Was: Replace mozlint's --rev with a --outgoing argument
MozReview-Commit-ID: 5YcRWbc1dR4
--- a/python/mozlint/mozlint/cli.py
+++ b/python/mozlint/mozlint/cli.py
@@ -1,18 +1,17 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import print_function, unicode_literals
import os
import sys
-from argparse import ArgumentParser, REMAINDER
-
+from argparse import REMAINDER, ArgumentParser
SEARCH_PATHS = []
class MozlintParser(ArgumentParser):
arguments = [
[['paths'],
{'nargs': '*',
@@ -41,16 +40,23 @@ class MozlintParser(ArgumentParser):
"testing a directory that otherwise wouldn't be run, "
"without needing to modify the config file.",
}],
[['-r', '--rev'],
{'default': None,
'help': "Lint files touched by the given revision(s). Works with "
"mercurial or git."
}],
+ [['-o', '--outgoing'],
+ {'const': 'default',
+ 'nargs': '?',
+ 'help': "Lint files touched by commits that are not on the remote repository."
+ "If you are using git please specify which remote you want to compare to."
+ "Works with mercurial or git."
+ }],
[['-w', '--workdir'],
{'default': False,
'action': 'store_true',
'help': "Lint files touched by changes in the working directory "
"(i.e haven't been committed yet). Works with mercurial or git.",
}],
[['extra_args'],
{'nargs': REMAINDER,
@@ -86,24 +92,25 @@ def find_linters(linters=None):
if linters and name not in linters:
continue
lints.append(os.path.join(search_path, f))
return lints
-def run(paths, linters, fmt, rev, workdir, **lintargs):
+def run(paths, linters, fmt, rev, outgoing, workdir, **lintargs):
from mozlint import LintRoller, formatters
lint = LintRoller(**lintargs)
lint.read(find_linters(linters))
# run all linters
- results = lint.roll(paths, rev=rev, workdir=workdir)
+ results = lint.roll(paths, rev=rev, outgoing=outgoing,
+ workdir=workdir)
formatter = formatters.get(fmt)
# Encode output with 'replace' to avoid UnicodeEncodeErrors on
# environments that aren't using utf-8.
print(formatter(results, failed=lint.failed).encode(
sys.stdout.encoding or 'ascii', 'replace'))
return 1 if results or lint.failed else 0
--- a/python/mozlint/mozlint/roller.py
+++ b/python/mozlint/mozlint/roller.py
@@ -4,26 +4,22 @@
from __future__ import unicode_literals
import os
import signal
import sys
import traceback
from collections import defaultdict
+from multiprocessing import Manager, Pool, cpu_count
from Queue import Empty
-from multiprocessing import (
- Manager,
- Pool,
- cpu_count,
-)
from .errors import LintersNotConfigured
+from .parser import Parser
from .types import supported_types
-from .parser import Parser
from .vcs import VCSFiles
def _run_linters(queue, paths, **lintargs):
parse = Parser()
results = defaultdict(list)
failed = []
@@ -93,21 +89,22 @@ class LintRoller(object):
:param paths: A path or iterable of paths to linter definitions.
"""
if isinstance(paths, basestring):
paths = (paths,)
for path in paths:
self.linters.append(self.parse(path))
- def roll(self, paths=None, rev=None, workdir=None, num_procs=None):
+ def roll(self, paths=None, rev=None, outgoing=None, workdir=None, num_procs=None):
"""Run all of the registered linters against the specified file paths.
:param paths: An iterable of files and/or directories to lint.
:param rev: Lint all files touched by the specified revision.
+ :param outgoing: Lint files touched by commits that are not on the remote repository.
:param workdir: Lint all files touched in the working directory.
:param num_procs: The number of processes to use. Default: cpu count
:return: A dictionary with file names as the key, and a list of
:class:`~result.ResultContainer`s as the value.
"""
paths = paths or []
if isinstance(paths, basestring):
paths = [paths]
@@ -115,16 +112,19 @@ class LintRoller(object):
if not self.linters:
raise LintersNotConfigured
# Calculate files from VCS
if rev:
paths.extend(self.vcs.by_rev(rev))
if workdir:
paths.extend(self.vcs.by_workdir())
+ if outgoing:
+ paths.extend(self.vcs.outgoing(outgoing))
+
paths = paths or ['.']
paths = map(os.path.abspath, paths)
# Set up multiprocessing
m = Manager()
queue = m.Queue()
for linter in self.linters:
--- a/python/mozlint/mozlint/vcs.py
+++ b/python/mozlint/mozlint/vcs.py
@@ -49,14 +49,27 @@ class VCSFiles(object):
def by_rev(self, rev):
if self.is_hg:
return self._run(['hg', 'log', '--template', '{files % "\\n{file}"}', '-r', rev])
elif self.is_git:
return self._run(['git', 'diff', '--name-only', rev])
return []
+ def outgoing(self, destination='default'):
+ if self.is_hg:
+ return self._run(['hg', 'outgoing', '--quiet', '-r .',
+ destination, '--template',
+ '{files % "\n{file}"}'])
+ elif self.is_git:
+ if destination == 'default':
+ comparing = 'origin/master..HEAD'
+ else:
+ comparing = '{}..HEAD'.format(destination)
+ return self._run(['git', 'log', '--name-only', comparing])
+ return []
+
def by_workdir(self):
if self.is_hg:
return self._run(['hg', 'status', '-amn'])
elif self.is_git:
return self._run(['git', 'diff', '--name-only'])
return []