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

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/>. 

20 

21import re 

22import logging 

23 

24from diffoscope.tools import tool_required 

25from diffoscope.difference import Difference 

26 

27from .utils.file import File 

28from .utils.command import Command 

29from .utils.libarchive import LibarchiveContainer, list_libarchive 

30 

31logger = logging.getLogger(__name__) 

32 

33 

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. 

37 

38 

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] 

53 

54 

55class ArSymbolTableDumper(Command): 

56 @tool_required("nm") 

57 def cmdline(self): 

58 return ["nm", "-s", self.path] 

59 

60 

61class ArFile(File): 

62 DESCRIPTION = "ar(1) archives" 

63 CONTAINER_CLASSES = [ArContainer] 

64 FILE_TYPE_RE = re.compile(r"\bar archive\b") 

65 

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 ]