[diffoscope] 02/02: Add a --exclude-command CLI for filtering out long-running commands like "readelf --debug-dump=info"
Ximin Luo
infinity0 at debian.org
Mon May 29 23:31:50 CEST 2017
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch experimental
in repository diffoscope.
commit fe2d5dec866ca68e1086be8aadd4fb38f87d5e37
Author: Ximin Luo <infinity0 at debian.org>
Date: Mon May 29 23:29:11 2017 +0200
Add a --exclude-command CLI for filtering out long-running commands like "readelf --debug-dump=info"
---
diffoscope/comparators/utils/command.py | 5 +++++
diffoscope/config.py | 1 +
diffoscope/difference.py | 34 ++++++++++++++++++++-------------
diffoscope/excludes.py | 8 ++++++++
diffoscope/main.py | 12 ++++++++++--
5 files changed, 45 insertions(+), 15 deletions(-)
diff --git a/diffoscope/comparators/utils/command.py b/diffoscope/comparators/utils/command.py
index 2d6fd4f..5014140 100644
--- a/diffoscope/comparators/utils/command.py
+++ b/diffoscope/comparators/utils/command.py
@@ -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
diff --git a/diffoscope/config.py b/diffoscope/config.py
index 8f6a229..ccc744c 100644
--- a/diffoscope/config.py
+++ b/diffoscope/config.py
@@ -34,6 +34,7 @@ class Config(object):
fuzzy_threshold = 60
enforce_constraints = True
excludes = ()
+ exclude_commands = ()
compute_visual_diffs = False
max_container_depth = 50
diff --git a/diffoscope/difference.py b/diffoscope/difference.py
index 38853f1..cef38f3 100644
--- a/diffoscope/difference.py
+++ b/diffoscope/difference.py
@@ -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()
- else:
- command1 = klass(path1, *command_args)
- feeder1 = make_feeder_from_command(command1)
- command2 = None
- if path2 == '/dev/null':
- feeder2 = empty_file_feeder()
- else:
- 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()
+ else:
+ command = klass(path, *command_args)
+ feeder = make_feeder_from_command(command)
+ if command_excluded(command.shell_cmdline()):
+ return None, None
+ command.start()
+ 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
diff --git a/diffoscope/excludes.py b/diffoscope/excludes.py
index 2ce60ee..b95b71f 100644
--- a/diffoscope/excludes.py
+++ b/diffoscope/excludes.py
@@ -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 re.search(y, 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:
diff --git a/diffoscope/main.py b/diffoscope/main.py
index 74e26ba..8ce6e1c 100644
--- a/diffoscope/main.py
+++ b/diffoscope/main.py
@@ -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()
set_path()
set_locale()
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git
More information about the diffoscope
mailing list