[game-data-packager] 08/13: Check for external tools before using them

Simon McVittie smcv at debian.org
Sat Jan 17 01:20:21 UTC 2015


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

smcv pushed a commit to branch master
in repository game-data-packager.

commit 19af5c468c3343764ee98982209c1f70ff285415
Author: Simon McVittie <smcv at debian.org>
Date:   Sat Jan 17 00:54:40 2015 +0000

    Check for external tools before using them
    
    Unlike the shell scripts, we don't need unzip or tar, but we might
    still need lha (which is only a Suggests) and dynamite (which is
    a Depends but probably shouldn't be).
---
 lib/game_data_packager/__init__.py | 60 +++++++++++++++++++++++++++++++++++++-
 lib/game_data_packager/util.py     | 13 +++++++++
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/lib/game_data_packager/__init__.py b/lib/game_data_packager/__init__.py
index b5f5a45..a0c5875 100644
--- a/lib/game_data_packager/__init__.py
+++ b/lib/game_data_packager/__init__.py
@@ -44,7 +44,12 @@ from debian.deb822 import Deb822
 import yaml
 
 from .paths import DATADIR, ETCDIR
-from .util import TemporaryUmask, mkdir_p, rm_rf, human_size, MEBIBYTE
+from .util import (MEBIBYTE,
+        TemporaryUmask,
+        mkdir_p,
+        rm_rf,
+        human_size,
+        which)
 from .version import GAME_PACKAGE_VERSION
 
 logging.basicConfig()
@@ -478,6 +483,12 @@ class GameData(object):
         # Map from GameDataPackage name to whether we can do it
         self.package_status = defaultdict(lambda: FillResult.UNDETERMINED)
 
+        # Set of executables we wanted but don't have
+        self.missing_tools = set()
+
+        # Set of filenames we couldn't unpack
+        self.unpack_failed = set()
+
         self._populate_files(self.yaml.get('files'))
 
         assert 'packages' in self.yaml
@@ -1195,6 +1206,10 @@ class GameData(object):
         for provider_name in providers:
             provider = self.files[provider_name]
 
+            # don't bother if we wouldn't be able to unpack it anyway
+            if not self.check_unpacker(provider):
+                continue
+
             # recurse to unpack or (see whether we can) download the provider
             provider_status = self.fill_gap(package, provider,
                     download=download, log=log)
@@ -1528,6 +1543,11 @@ class GameData(object):
                     build_demos=args.demo)
         except NoPackagesPossible:
             logger.error('Unable to complete any packages.')
+            if self.unpack_failed and self.missing_tools:
+                # we already logged warnings about the files as they came up
+                self.log_missing_tools()
+                raise SystemExit(1)
+
             # probably not enough files supplied?
             # print the help text, maybe that helps the user to determine
             # what they should have added
@@ -1715,6 +1735,44 @@ class GameData(object):
         rm_rf(destdir)
         return outfile
 
+    def check_unpacker(self, wanted):
+        if not wanted.unpack:
+            return True
+
+        if wanted.name in self.unpack_failed:
+            return False
+
+        fmt = wanted.unpack['format']
+
+        if fmt in ('id-shr-extract', 'lha'):
+            if which(fmt) is None:
+                logger.warning('cannot unpack "%s": tool "%s" is not ' +
+                        'installed', wanted.name, fmt)
+                self.missing_tools.add(fmt)
+                self.unpack_failed.add(wanted.name)
+                return False
+
+        return True
+
+    def log_missing_tools(self):
+        if not self.missing_tools:
+            return False
+
+        package_map = {
+                'id-shr-extract': 'dynamite',
+                'lha': 'lhasa',
+        }
+        packages = set()
+
+        for t in self.missing_tools:
+            p = package_map.get(t)
+            if p is not None:
+                packages.add(p)
+
+        logger.warning('installing these packages might help:\n' +
+                'apt-get install %s',
+                ' '.join(sorted(packages)))
+
 def load_yaml_games(workdir=None):
     games = {}
 
diff --git a/lib/game_data_packager/util.py b/lib/game_data_packager/util.py
index 16553a7..f31b320 100644
--- a/lib/game_data_packager/util.py
+++ b/lib/game_data_packager/util.py
@@ -17,6 +17,7 @@
 
 import os
 import shutil
+import stat
 
 KIBIBYTE = 1024
 MEBIBYTE = KIBIBYTE * KIBIBYTE
@@ -49,6 +50,18 @@ def rm_rf(path):
     if os.path.exists(path):
         shutil.rmtree(path)
 
+def which(exe):
+    for path in os.environ.get('PATH', '/usr/bin:/bin').split(os.pathsep):
+        try:
+            abspath = os.path.join(path, exe)
+            statbuf = os.stat(abspath)
+        except:
+            continue
+        if stat.S_IMODE(statbuf.st_mode) & 0o111:
+            return abspath
+
+    return None
+
 def human_size(size):
     # 0.0 KiB up to 1024.0 KiB
     if size < MEBIBYTE:

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/game-data-packager.git



More information about the Pkg-games-commits mailing list