Coverage for diffoscope/comparators/android.py: 98%

43 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 © 2017-2021 Chris Lamb <lamby@debian.org> 

5# 

6# diffoscope is free software: you can redistribute it and/or modify 

7# it under the terms of the GNU General Public License as published by 

8# the Free Software Foundation, either version 3 of the License, or 

9# (at your option) any later version. 

10# 

11# diffoscope is distributed in the hope that it will be useful, 

12# but WITHOUT ANY WARRANTY; without even the implied warranty of 

13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

14# GNU General Public License for more details. 

15# 

16# You should have received a copy of the GNU General Public License 

17# along with diffoscope. If not, see <https://www.gnu.org/licenses/>. 

18 

19import os 

20import re 

21import logging 

22import subprocess 

23 

24from diffoscope.tools import tool_required 

25from diffoscope.tempfiles import get_temporary_directory 

26from diffoscope.difference import Difference 

27 

28from .utils.file import File 

29from .utils.archive import Archive 

30from .utils.command import Command 

31 

32logger = logging.getLogger(__name__) 

33 

34 

35class AbootimgInfo(Command): 

36 @tool_required("abootimg") 

37 def cmdline(self): 

38 return ["abootimg", "-i", self.path] 

39 

40 def filter(self, line): 

41 if line.startswith(b"* file name = "): 

42 return b"" 

43 return line 

44 

45 

46class AndroidBootImgContainer(Archive): 

47 @property 

48 def path(self): 

49 return self._path 

50 

51 @tool_required("abootimg") 

52 def open_archive(self): 

53 self._members = [] 

54 self._unpacked = get_temporary_directory(suffix="android") 

55 

56 logger.debug( 

57 "Extracting Android boot image to %s", self._unpacked.name 

58 ) 

59 

60 subprocess.check_call( 

61 ["abootimg", "-x", os.path.abspath(self.source.path)], 

62 cwd=self._unpacked.name, 

63 stdout=subprocess.PIPE, 

64 ) 

65 

66 self._members = sorted(os.listdir(self._unpacked.name)) 

67 

68 return self 

69 

70 def close_archive(self): 

71 self._unpacked.cleanup() 

72 

73 def extract(self, member_name, dest_dir): 

74 return os.path.join(self._unpacked.name, member_name) 

75 

76 def get_member_names(self): 

77 return self._members 

78 

79 

80class AndroidBootImgFile(File): 

81 DESCRIPTION = "Android boot images" 

82 FILE_TYPE_RE = re.compile(r"^Android bootimg\b") 

83 CONTAINER_CLASSES = [AndroidBootImgContainer] 

84 

85 def compare_details(self, other, source=None): 

86 return [Difference.from_operation(AbootimgInfo, self.path, other.path)]