[diffoscope] 01/01: Add a --tool-prefix-binutils CLI flag. (Closes: #869868)

Ximin Luo infinity0 at debian.org
Wed Aug 16 15:35:44 CEST 2017


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository diffoscope.

commit 1de693d11d0d08d2127b40c6e7f3265f7ba9ab34
Author: Ximin Luo <infinity0 at debian.org>
Date:   Wed Aug 16 15:35:24 2017 +0200

    Add a --tool-prefix-binutils CLI flag. (Closes: #869868)
---
 diffoscope/comparators/elf.py | 16 ++++++++--------
 diffoscope/exc.py             |  4 ++--
 diffoscope/external_tools.py  |  5 +++++
 diffoscope/main.py            |  7 ++++++-
 diffoscope/tools.py           | 15 +++++++++++++--
 5 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/diffoscope/comparators/elf.py b/diffoscope/comparators/elf.py
index d1a0862..0e633c8 100644
--- a/diffoscope/comparators/elf.py
+++ b/diffoscope/comparators/elf.py
@@ -24,7 +24,7 @@ import subprocess
 import collections
 
 from diffoscope.exc import OutputParsingError
-from diffoscope.tools import tool_required
+from diffoscope.tools import get_tool_name, tool_required
 from diffoscope.tempfiles import get_named_temporary_file
 from diffoscope.difference import Difference
 
@@ -62,7 +62,7 @@ class Readelf(Command):
 
     @tool_required('readelf')
     def cmdline(self):
-        return ['readelf', '--wide'] + self.readelf_options() + [self.path]
+        return [get_tool_name('readelf'), '--wide'] + self.readelf_options() + [self.path]
 
     def readelf_options(self):
         return []  # noqa
@@ -168,7 +168,7 @@ class ReadElfSection(Readelf):
     def base_options():
         if not hasattr(ReadElfSection, '_base_options'):
             output = subprocess.check_output(
-                ['readelf', '--help'],
+                [get_tool_name('readelf'), '--help'],
                 shell=False,
                 stderr=subprocess.DEVNULL,
             ).decode('us-ascii', errors='replace')
@@ -208,7 +208,7 @@ class ObjdumpSection(Command):
     @tool_required('objdump')
     def cmdline(self):
         return [
-            'objdump',
+            get_tool_name('objdump'),
         ] + self.objdump_options() + [
             '--section={}'.format(self._section_name),
             self.path,
@@ -344,7 +344,7 @@ class ElfStringSection(ElfSection):
 def get_build_id(path):
     try:
         output = subprocess.check_output(
-            ['readelf', '--notes', path],
+            [get_tool_name('readelf'), '--notes', path],
             stderr=subprocess.DEVNULL,
         )
     except subprocess.CalledProcessError as e:
@@ -362,7 +362,7 @@ def get_build_id(path):
 def get_debug_link(path):
     try:
         output = subprocess.check_output(
-            ['readelf', '--string-dump=.gnu_debuglink', path],
+            [get_tool_name('readelf'), '--string-dump=.gnu_debuglink', path],
             stderr=subprocess.DEVNULL,
         )
     except subprocess.CalledProcessError as e:
@@ -388,7 +388,7 @@ class ElfContainer(Container):
         super().__init__(*args, **kwargs)
         logger.debug("Creating ElfContainer for %s", self.source.path)
 
-        cmd = ['readelf', '--wide', '--section-headers', self.source.path]
+        cmd = [get_tool_name('readelf'), '--wide', '--section-headers', self.source.path]
         output = subprocess.check_output(cmd, shell=False, stderr=subprocess.DEVNULL)
         has_debug_symbols = False
 
@@ -489,7 +489,7 @@ class ElfContainer(Container):
 
         def objcopy(*args):
             subprocess.check_call(
-                ('objcopy',) + args,
+                (get_tool_name('objcopy'),) + args,
                 shell=False,
                 stderr=subprocess.DEVNULL,
         )
diff --git a/diffoscope/exc.py b/diffoscope/exc.py
index 4b3910d..efb581b 100644
--- a/diffoscope/exc.py
+++ b/diffoscope/exc.py
@@ -18,7 +18,7 @@
 # You should have received a copy of the GNU General Public License
 # along with diffoscope.  If not, see <https://www.gnu.org/licenses/>.
 
-from .tools import get_package_provider
+from .tools import get_tool_name, get_package_provider
 
 
 class OutputParsingError(Exception):
@@ -28,7 +28,7 @@ class OutputParsingError(Exception):
 
 class RequiredToolNotFound(Exception):
     def __init__(self, command):
-        self.command = command
+        self.command = get_tool_name(command)
 
     def get_package(self):
         return get_package_provider(self.command)
diff --git a/diffoscope/external_tools.py b/diffoscope/external_tools.py
index 9bfd1ab..a4b6975 100644
--- a/diffoscope/external_tools.py
+++ b/diffoscope/external_tools.py
@@ -251,3 +251,8 @@ EXTERNAL_TOOLS = {
         'FreeBSD': 'unzip',
     },
 }
+
+# May be populated at runtime by remapped names like
+# readelf -> arm-none-eabi-readelf, etc
+# diff -> gdiff, etc
+REMAPPED_TOOL_NAMES = {}
diff --git a/diffoscope/main.py b/diffoscope/main.py
index 60e6600..da79560 100644
--- a/diffoscope/main.py
+++ b/diffoscope/main.py
@@ -29,7 +29,7 @@ import traceback
 
 from . import VERSION
 from .path import set_path
-from .tools import tool_required, OS_NAMES, get_current_os
+from .tools import tool_prepend_prefix, tool_required, OS_NAMES, get_current_os
 from .config import Config
 from .locale import set_locale
 from .logging import setup_logging
@@ -197,6 +197,10 @@ def create_parser():
                         help='Threshold for fuzzy-matching '
                         '(0 to disable, %(default)s is default, 400 is high fuzziness)',
                         default=Config().fuzzy_threshold).completer=RangeCompleter(400)
+    group3.add_argument('--tool-prefix-binutils', metavar='PREFIX',
+                        help='Prefix for binutils program names, e.g. '
+                        '"aarch64-linux-gnu-" for a foreign-arch binary or "g" '
+                        'if you\'re on a non-GNU system.')
     group3.add_argument('--max-diff-input-lines', metavar='LINES', type=int,
                         help='Maximum number of lines fed to diff(1) '
                         '(0 to disable, default: %d)' %
@@ -354,6 +358,7 @@ def run_diffoscope(parsed_args):
     Config().exclude_directory_metadata = parsed_args.exclude_directory_metadata
     Config().compute_visual_diffs = PresenterManager().compute_visual_diffs()
     Config().check_constraints()
+    tool_prepend_prefix(parsed_args.tool_prefix_binutils, *"ar as ld ld.bfd nm objcopy objdump ranlib readelf strip".split())
     set_path()
     set_locale()
     path1, path2 = parsed_args.path1, parsed_args.path2
diff --git a/diffoscope/tools.py b/diffoscope/tools.py
index fd483b4..370d39e 100644
--- a/diffoscope/tools.py
+++ b/diffoscope/tools.py
@@ -29,7 +29,7 @@ except ImportError:
 from distutils.spawn import find_executable
 
 from .profiling import profile
-from .external_tools import EXTERNAL_TOOLS
+from .external_tools import EXTERNAL_TOOLS, REMAPPED_TOOL_NAMES
 
 # Memoize calls to ``distutils.spawn.find_executable`` to avoid excessive stat
 # calls
@@ -44,6 +44,17 @@ OS_NAMES = collections.OrderedDict([
 ])
 
 
+def get_tool_name(tool):
+    return REMAPPED_TOOL_NAMES.get(tool, tool)
+
+
+def tool_prepend_prefix(prefix, *tools):
+    if not prefix:
+        return
+    for tool in tools:
+        REMAPPED_TOOL_NAMES[tool] = prefix + tool
+
+
 def tool_required(command):
     """
     Decorator that checks if the specified tool is installed
@@ -67,7 +78,7 @@ def tool_required(command):
             performed prior to the `find_executable` tests.
             """
 
-            if not find_executable(command):
+            if not find_executable(get_tool_name(command)):
                 raise RequiredToolNotFound(command)
 
             with profile('command', command):

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git


More information about the diffoscope mailing list