Skip to content
Snippets Groups Projects
Commit 6710868a authored by Chris Lamb's avatar Chris Lamb :eyes:
Browse files

Add support for alternative container types for a file, allowing for runtime...

Add support for alternative container types for a file, allowing for runtime (vs import time) control of fallbacks such as adding comments. (Re: #86)
parent c99cd9bd
No related branches found
No related tags found
No related merge requests found
Showing
with 43 additions and 37 deletions
......@@ -81,7 +81,7 @@ class AndroidBootImgContainer(Archive):
class AndroidBootImgFile(File):
DESCRIPTION = "Android boot images"
FILE_TYPE_RE = re.compile(r'^Android bootimg\b')
CONTAINER_CLASS = AndroidBootImgContainer
CONTAINER_CLASSES = [AndroidBootImgContainer]
def compare_details(self, other, source=None):
return [Difference.from_command(AbootimgInfo, self.path, other.path)]
......@@ -172,9 +172,9 @@ class ApkFile(File):
FILE_TYPE_HEADER_PREFIX = b"PK\x03\x04"
FILE_TYPE_RE = re.compile(r'^(Java|Zip) archive data.*\b')
FILE_EXTENSION_SUFFIX = '.apk'
CONTAINER_CLASS = (
CONTAINER_CLASSES = [
ApkContainer if find_executable('apktool') else ZipContainer
)
]
def compare_details(self, other, source=None):
return zipinfo_differences(self, other)
......
......@@ -60,7 +60,7 @@ class ArSymbolTableDumper(Command):
class ArFile(File):
DESCRIPTION = "ar(1) archives"
CONTAINER_CLASS = ArContainer
CONTAINER_CLASSES = [ArContainer]
FILE_TYPE_RE = re.compile(r'\bar archive\b')
def compare_details(self, other, source=None):
......
......@@ -67,7 +67,7 @@ class BinwalkFileContainer(Archive):
class BinwalkFile(File):
FILE_TYPE_RE = re.compile(r'\bcpio archive\b')
CONTAINER_CLASS = BinwalkFileContainer
CONTAINER_CLASSES = [BinwalkFileContainer]
@classmethod
def recognizes(cls, file):
......
......@@ -55,5 +55,5 @@ class Bzip2Container(Archive):
class Bzip2File(File):
DESCRIPTION = "bzip2 archives"
CONTAINER_CLASS = Bzip2Container
CONTAINER_CLASSES = [Bzip2Container]
FILE_TYPE_RE = re.compile(r'^bzip2 compressed data\b')
......@@ -125,7 +125,7 @@ def is_header_valid(buf, size, offset=0):
class CbfsFile(File):
DESCRIPTION = "Coreboot CBFS filesystem images"
CONTAINER_CLASS = CbfsContainer
CONTAINER_CLASSES = [CbfsContainer]
@classmethod
def recognizes(cls, file):
......
......@@ -28,7 +28,7 @@ from .utils.libarchive import LibarchiveContainer, list_libarchive
class CpioFile(File):
DESCRIPTION = "cpio archives"
CONTAINER_CLASS = LibarchiveContainer
CONTAINER_CLASSES = [LibarchiveContainer]
FILE_TYPE_RE = re.compile(r'\bcpio archive\b')
def compare_details(self, other, source=None):
......
......@@ -111,7 +111,7 @@ class DebContainer(LibarchiveContainer):
class DebFile(File):
CONTAINER_CLASS = DebContainer
CONTAINER_CLASSES = [DebContainer]
FILE_TYPE_RE = re.compile(r'^Debian binary package')
@property
......@@ -233,7 +233,7 @@ class DebTarContainer(TarContainer):
class DebDataTarFile(File):
CONTAINER_CLASS = DebTarContainer
CONTAINER_CLASSES = [DebTarContainer]
@classmethod
def recognizes(cls, file):
......
......@@ -109,7 +109,7 @@ class DebControlContainer(Container):
class DebControlFile(File):
CONTAINER_CLASS = DebControlContainer
CONTAINER_CLASSES = [DebControlContainer]
@property
def deb822(self):
......@@ -261,7 +261,7 @@ class DotBuildinfoContainer(DebControlContainer):
class DotBuildinfoFile(DebControlFile):
DESCRIPTION = "Debian .buildinfo files"
CONTAINER_CLASS = DotBuildinfoContainer
CONTAINER_CLASSES = [DotBuildinfoContainer]
FILE_EXTENSION_SUFFIX = '.buildinfo'
FILE_TYPE_RE = re.compile(r'^(ASCII text|UTF-8 Unicode text)')
......
......@@ -60,4 +60,4 @@ class DexContainer(Archive):
class DexFile(File):
DESCRIPTION = "Dalvik .dex files"
FILE_TYPE_RE = re.compile(r'^Dalvik dex file .*\b')
CONTAINER_CLASS = DexContainer
CONTAINER_CLASSES = [DexContainer]
......@@ -621,7 +621,7 @@ class ElfContainer(Container):
class ElfFile(File):
DESCRIPTION = "ELF binaries"
CONTAINER_CLASS = ElfContainer
CONTAINER_CLASSES = [ElfContainer]
FILE_TYPE_RE = re.compile(r'^ELF ')
def compare_details(self, other, source=None):
......
......@@ -88,7 +88,7 @@ class FsImageContainer(Archive):
class FsImageFile(File):
DESCRIPTION = "ext2/ext3/ext4/btrfs/fat filesystems"
CONTAINER_CLASS = FsImageContainer
CONTAINER_CLASSES = [FsImageContainer]
FILE_TYPE_RE = re.compile(r'^(Linux.*filesystem data|BTRFS Filesystem).*')
@classmethod
......
......@@ -56,7 +56,7 @@ class GzipContainer(Archive):
class GzipFile(File):
DESCRIPTION = "Gzipped files"
CONTAINER_CLASS = GzipContainer
CONTAINER_CLASSES = [GzipContainer]
FILE_TYPE_RE = re.compile(r'^gzip compressed data\b')
# Work around file(1) Debian bug #876316
......
......@@ -76,7 +76,7 @@ class ISO9660Listing(Command):
class Iso9660File(File):
DESCRIPTION = "ISO 9660 CD images"
CONTAINER_CLASS = LibarchiveContainerWithFilelist
CONTAINER_CLASSES = [LibarchiveContainerWithFilelist]
FILE_TYPE_RE = re.compile(r'\bISO 9660\b')
@classmethod
......
......@@ -56,7 +56,7 @@ class Lz4Container(Archive):
class Lz4File(File):
DESCRIPTION = "LZ4 compressed files"
CONTAINER_CLASS = Lz4Container
CONTAINER_CLASSES = [Lz4Container]
FILE_TYPE_RE = re.compile(r'^LZ4 compressed data \([^\)]+\)$')
# Work around file(1) Debian bug #876316
......
......@@ -109,7 +109,7 @@ class RpmContainer(Archive):
class RpmFile(AbstractRpmFile):
DESCRIPTION = "RPM archives"
CONTAINER_CLASS = RpmContainer
CONTAINER_CLASSES = [RpmContainer]
def compare_details(self, other, source=None):
return [compare_rpm_headers(self.path, other.path)]
......@@ -60,7 +60,7 @@ class RustObjectContainer(Archive):
class RustObjectFile(File):
DESCRIPTION = "Rust object files (.deflate)"
CONTAINER_CLASS = RustObjectContainer
CONTAINER_CLASSES = [RustObjectContainer]
FILE_TYPE_HEADER_PREFIX = b'RUST_OBJECT\x01\x00\x00\x00'
FILE_EXTENSION_SUFFIX = '.deflate'
......
......@@ -310,7 +310,7 @@ class SquashfsContainer(Archive):
class SquashfsFile(File):
DESCRIPTION = "SquashFS filesystems"
CONTAINER_CLASS = SquashfsContainer
CONTAINER_CLASSES = [SquashfsContainer]
FILE_TYPE_RE = re.compile(r'^Squashfs filesystem\b')
def compare_details(self, other, source=None):
......
......@@ -31,7 +31,7 @@ class TarContainer(LibarchiveContainer):
class TarFile(File):
DESCRIPTION = "tape archives (.tar)"
CONTAINER_CLASS = TarContainer
CONTAINER_CLASSES = [TarContainer]
FILE_TYPE_RE = re.compile(r'\btar archive\b')
def compare_details(self, other, source=None):
......
......@@ -225,37 +225,43 @@ class File(metaclass=abc.ABCMeta):
def container(self):
return self._container
CONTAINER_CLASSES = []
@property
def as_container(self):
if not hasattr(self.__class__, 'CONTAINER_CLASS'):
klasses = self.__class__.CONTAINER_CLASSES
if not klasses:
if hasattr(self, '_other_file'):
return self._other_file.__class__.CONTAINER_CLASS(self)
return self._other_file.__class__.CONTAINER_CLASSES[0](self)
return None
def type_name(klass):
return "{}.{}".format(klass.__module__, klass.__name__)
if not hasattr(self, '_as_container'):
if hasattr(self, '_as_container'):
return self._as_container
self._as_container = None
# Try each container class in turn, returning the first one that
# instantiates without error.
for klass in klasses:
logger.debug(
'Instantiating a %s for %s',
type_name(self.__class__.CONTAINER_CLASS),
self.name,
'Instantiating a %s for %s', type_name(klass), self.name,
)
try:
self._as_container = self.__class__.CONTAINER_CLASS(self)
self._as_container = klass(self)
logger.debug(
"Returning a %s for %s", type_name(klass), self.name,
)
return self._as_container
except RequiredToolNotFound as exc:
logger.debug(
"Cannot instantiate a %s; missing tool %s",
type_name(self.__class__.CONTAINER_CLASS),
type_name(klass),
exc.command,
)
return None
logger.debug(
"Returning a %s for %s",
type_name(self._as_container.__class__),
self.name,
)
return self._as_container
@property
def progress_name(self):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment