[diffoscope] 01/01: Improved support for Android apk files

Reiner Herrmann reiner at reiner-h.de
Thu Dec 15 13:10:09 CET 2016


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

deki-guest pushed a commit to branch master
in repository diffoscope.

commit 3e748664a91b7ced412547a204e1473161425d4f
Author: Reiner Herrmann <reiner at reiner-h.de>
Date:   Thu Dec 15 13:04:28 2016 +0100

    Improved support for Android apk files
    
    Android packages/apps (.apk) are Java archvies, which were
    already handled by diffoscope to a certain extent.
    The collection of class files (classes.dex) was already converted
    by enjarify to proper class files.
    But there are additional important files like the AndroidManifest.xml
    (which is a binary XML format) and resources.arsc. Those are now also
    properly diffable by using apktool for dumping the apk contents.
---
 debian/control                     |  1 +
 diffoscope/comparators/__init__.py |  1 +
 diffoscope/comparators/apk.py      | 64 ++++++++++++++++++++++++++++++++++++++
 diffoscope/exc.py                  |  3 ++
 4 files changed, 69 insertions(+)

diff --git a/debian/control b/debian/control
index 7aa5412..f71e028 100644
--- a/debian/control
+++ b/debian/control
@@ -9,6 +9,7 @@ Uploaders:
  Reiner Herrmann <reiner at reiner-h.de>,
  Ximin Luo <infinity0 at debian.org>,
 Build-Depends:
+ apktool <!nocheck>,
  bash-completion,
  binutils-multiarch <!nocheck>,
  caca-utils <!nocheck>,
diff --git a/diffoscope/comparators/__init__.py b/diffoscope/comparators/__init__.py
index 4fc62a5..946c4ba 100644
--- a/diffoscope/comparators/__init__.py
+++ b/diffoscope/comparators/__init__.py
@@ -79,6 +79,7 @@ COMPARATORS = (
     ('ar.ArFile',),
     ('tar.TarFile',),
     ('xz.XzFile',),
+    ('apk.ApkFile',),
     ('zip.ZipFile',),
     ('zip.MozillaZipFile',),
     ('image.ImageFile',),
diff --git a/diffoscope/comparators/apk.py b/diffoscope/comparators/apk.py
new file mode 100644
index 0000000..eafa367
--- /dev/null
+++ b/diffoscope/comparators/apk.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+#
+# diffoscope: in-depth comparison of files, archives, and directories
+#
+# Copyright © 2016 Reiner Herrmann <reiner at reiner-h.de>
+#
+# diffoscope is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# diffoscope is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with diffoscope.  If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import os.path
+import subprocess
+
+from diffoscope import logger, tool_required, get_temporary_directory
+from diffoscope.comparators.binary import File
+from diffoscope.comparators.utils import Archive, get_compressed_content_name
+
+class ApkContainer(Archive):
+    @property
+    def path(self):
+        return self._path
+
+    @tool_required('apktool')
+    def open_archive(self):
+        self._members = []
+        self._unpacked = os.path.join(get_temporary_directory().name, self.source.name)
+        logger.debug("extracting %s to %s", self.source.name, self._unpacked)
+        subprocess.check_call(['apktool', 'd', '-k', '-m', '-o', self._unpacked, self.source.path],
+            shell=False, stderr=None, stdout=subprocess.PIPE)
+        for root, _, files in os.walk(self._unpacked):
+            for f in files:
+                abspath = os.path.join(root, f)
+                relpath = abspath[len(self._unpacked)+1:]
+                self._members.append(relpath)
+        return self
+
+    def close_archive(self):
+        pass
+
+    def get_member_names(self):
+        return self._members
+
+    def extract(self, member_name, dest_dir):
+        src_path = os.path.join(self._unpacked, member_name)
+        return src_path
+
+class ApkFile(File):
+    RE_FILE_TYPE = re.compile(r'^Java archive data .*\b')
+    RE_FILE_EXTENSION = re.compile(r'\.apk$')
+    CONTAINER_CLASS = ApkContainer
+
+    @staticmethod
+    def recognizes(file):
+        return ApkFile.RE_FILE_TYPE.match(file.magic_file_type) and ApkFile.RE_FILE_EXTENSION.search(file.name)
diff --git a/diffoscope/exc.py b/diffoscope/exc.py
index 116e813..b9fbaff 100644
--- a/diffoscope/exc.py
+++ b/diffoscope/exc.py
@@ -25,6 +25,9 @@ class OutputParsingError(Exception):
 
 class RequiredToolNotFound(Exception):
     PROVIDERS = {
+        'apktool': {
+            'debian': 'apktool',
+        },
         'bzip2': {
             'debian': 'bzip2',
             'arch': 'bzip2',

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


More information about the diffoscope mailing list