Coverage for diffoscope/comparators/ar.py: 100%
27 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-07 13:38 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-07 13:38 +0000
1#
2# diffoscope: in-depth comparison of files, archives, and directories
3#
4# Copyright © 2014-2015 Jérémy Bobbio <lunar@debian.org>
5# Copyright © 2016 Ximin Luo <infinity0@pwned.gg>
6# Copyright © 2016-2020 Chris Lamb <lamby@debian.org>
7#
8# diffoscope is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# diffoscope is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with diffoscope. If not, see <https://www.gnu.org/licenses/>.
21import re
22import logging
24from diffoscope.tools import tool_required
25from diffoscope.difference import Difference
27from .utils.file import File
28from .utils.command import Command
29from .utils.libarchive import LibarchiveContainer, list_libarchive
31logger = logging.getLogger(__name__)
34# For Go archives this gives a readable plain diff of the __.PKGDEF
35# member which is just a text file containing the Go interface.
36# TODO: add Go tests and more recursion.
39class ArContainer(LibarchiveContainer):
40 def get_adjusted_members(self):
41 members = list(super().get_adjusted_members())
42 known_ignores = {
43 "/": "this is the symbol table, already accounted for in other output",
44 "//": "this is the table for GNU long names, already accounted for in the archive filelist",
45 }
46 filtered_out = [p for p in members if p[0] in known_ignores]
47 if filtered_out:
48 for k, v in filtered_out:
49 logger.debug(
50 "ignored ar member '%s' because %s", k, known_ignores[k]
51 )
52 return [p for p in members if p[0] not in known_ignores]
55class ArSymbolTableDumper(Command):
56 @tool_required("nm")
57 def cmdline(self):
58 return ["nm", "-s", self.path]
61class ArFile(File):
62 DESCRIPTION = "ar(1) archives"
63 CONTAINER_CLASSES = [ArContainer]
64 FILE_TYPE_RE = re.compile(r"\bar archive\b")
66 def compare_details(self, other, source=None):
67 return [
68 Difference.from_operation(
69 ArSymbolTableDumper, self.path, other.path
70 ),
71 Difference.from_text_readers(
72 list_libarchive(self.path),
73 list_libarchive(other.path),
74 self.path,
75 other.path,
76 source="file list",
77 ),
78 ]