Commit fe2d5dec authored by Ximin Luo's avatar Ximin Luo

Add a --exclude-command CLI for filtering out long-running commands like...

Add a --exclude-command CLI for filtering out long-running commands like "readelf --debug-dump=info"
parent 98275e3f
......@@ -30,6 +30,8 @@ logger = logging.getLogger(__name__)
class Command(object, metaclass=abc.ABCMeta):
def __init__(self, path):
self._path = path
def start(self):
logger.debug("Executing %s", ' '.join([shlex.quote(x) for x in self.cmdline()]))
self._process = subprocess.Popen(self.cmdline(),
shell=False, close_fds=True,
......@@ -58,6 +60,9 @@ class Command(object, metaclass=abc.ABCMeta):
def cmdline(self):
raise NotImplementedError()
def shell_cmdline(self):
return ' '.join(map(lambda x: '{}' if x == self.path else shlex.quote(x), self.cmdline()))
def env(self):
return None # inherit parent environment by default
......@@ -34,6 +34,7 @@ class Config(object):
fuzzy_threshold = 60
enforce_constraints = True
excludes = ()
exclude_commands = ()
compute_visual_diffs = False
max_container_depth = 50
......@@ -23,6 +23,7 @@ import logging
import subprocess
from .exc import RequiredToolNotFound
from .excludes import command_excluded
from .diff import diff, reverse_unified_diff
from .config import Config
from .profiling import profile
......@@ -131,21 +132,28 @@ class Difference(object):
if 'command_args' in kwargs:
command_args = kwargs['command_args']
del kwargs['command_args']
command1 = None
if path1 == '/dev/null':
feeder1 = empty_file_feeder()
command1 = klass(path1, *command_args)
feeder1 = make_feeder_from_command(command1)
command2 = None
if path2 == '/dev/null':
feeder2 = empty_file_feeder()
command2 = klass(path2, *command_args)
feeder2 = make_feeder_from_command(command2)
def command_and_feeder(path):
command = None
if path == '/dev/null':
feeder = empty_file_feeder()
command = klass(path, *command_args)
feeder = make_feeder_from_command(command)
if command_excluded(command.shell_cmdline()):
return None, None
return feeder, command
feeder1, command1 = command_and_feeder(path1)
feeder2, command2 = command_and_feeder(path2)
if not feeder1 or not feeder2:
return None
if 'source' not in kwargs:
source_cmd = command1 or command2
kwargs['source'] = ' '.join(map(lambda x: '{}' if x == source_cmd.path else x, source_cmd.cmdline()))
kwargs['source'] = source_cmd.shell_cmdline()
difference = Difference.from_feeder(feeder1, feeder2, path1, path2, *args, **kwargs)
if not difference:
return None
......@@ -19,12 +19,20 @@
import fnmatch
import logging
import re
from diffoscope.config import Config
logger = logging.getLogger(__name__)
def command_excluded(command):
for y in Config().exclude_commands:
if, command):
logger.debug("Excluding command '%s' as it matches pattern '%s'", command, y)
return True
return False
def filter_excludes(filenames):
for x in filenames:
for y in Config().excludes:
......@@ -159,9 +159,16 @@ def create_parser():
group3 = parser.add_argument_group('diff calculation')
group3.add_argument('--new-file', action='store_true',
help='Treat absent files as empty')
group3.add_argument('--exclude', dest='excludes', nargs='?',
metavar='PATTERN', action='append', default=[],
group3.add_argument('--exclude', dest='excludes',
metavar='GLOB_PATTERN', action='append', default=[],
help='Exclude files that match %(metavar)s')
group3.add_argument('--exclude-command', dest='exclude_commands',
metavar='REGEX_PATTERN', action='append', default=[],
help='Exclude commands that match %(metavar)s. For '
"example, '^readelf.*\s--debug-dump=info' takes by far "
'the longest time, and differences here are probably '
'only secondary differences caused by something that '
'is already represented elsewhere in the diff.')
group3.add_argument('--fuzzy-threshold', type=int,
help='Threshold for fuzzy-matching '
'(0 to disable, %(default)s is default, 400 is high fuzziness)',
......@@ -291,6 +298,7 @@ def run_diffoscope(parsed_args):
Config().fuzzy_threshold = parsed_args.fuzzy_threshold
Config().new_file = parsed_args.new_file
Config().excludes = parsed_args.excludes
Config().exclude_commands = parsed_args.exclude_commands
Config().compute_visual_diffs = PresenterManager().compute_visual_diffs()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment