[game-data-packager] 38/51: make_template: Use the GameData's groups instead of reinventing them

Simon McVittie smcv at debian.org
Fri Dec 29 01:23:37 UTC 2017


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 739a5a00e45711cf6803287699d85b7c0d5bfe86
Author: Simon McVittie <smcv at debian.org>
Date:   Thu Dec 28 18:20:15 2017 +0000

    make_template: Use the GameData's groups instead of reinventing them
    
    Signed-off-by: Simon McVittie <smcv at debian.org>
---
 game_data_packager/game.py          |  10 +-
 game_data_packager/make_template.py | 288 ++++++++++++++++++++++--------------
 2 files changed, 180 insertions(+), 118 deletions(-)

diff --git a/game_data_packager/game.py b/game_data_packager/game.py
index f621776..48f0de3 100644
--- a/game_data_packager/game.py
+++ b/game_data_packager/game.py
@@ -205,7 +205,7 @@ class GameData(object):
             # encounter an entry that is not known to be a group in a
             # group's members, it is definitely a file.
             for group_name in groups:
-                self._ensure_group(group_name)
+                self.ensure_group(group_name)
 
             for group_name, group_data in groups.items():
                 group = self.groups[group_name]
@@ -595,7 +595,7 @@ class GameData(object):
                 if k in data:
                     setattr(f, k, data[k])
 
-    def _ensure_group(self, name):
+    def ensure_group(self, name):
         assert name not in self.files, (self.shortname, name)
 
         if name not in self.groups:
@@ -700,11 +700,11 @@ class GameData(object):
             # the data, is a group or a file.
             if stripped.startswith('*'):
                 assert current_group is None
-                self._ensure_group(stripped[1:])
+                self.ensure_group(stripped[1:])
             # After that, [Group] opens a section for each group
             elif stripped.startswith('['):
                 assert stripped.endswith(']'), repr(stripped)
-                current_group = self._ensure_group(stripped[1:-1])
+                current_group = self.ensure_group(stripped[1:-1])
                 attributes = {}
             # JSON metadata is on a line with {}
             elif stripped.startswith('{'):
@@ -738,7 +738,7 @@ class GameData(object):
 
             for group_name, group_data in sorted(
                     data.get('groups', {}).items()):
-                group = self._ensure_group(group_name)
+                group = self.ensure_group(group_name)
 
                 if isinstance(group_data, dict):
                     members = group_data['group_members']
diff --git a/game_data_packager/make_template.py b/game_data_packager/make_template.py
index 1eedb23..5f507c6 100644
--- a/game_data_packager/make_template.py
+++ b/game_data_packager/make_template.py
@@ -146,20 +146,18 @@ class Template:
 
         self.data = dict()
 
-        self.groups = {}
-        self.required = FileGroup('probably required')
-        self.optional = FileGroup('probably optional')
-        self.documentation = FileGroup('probably documentation')
-        self.licenses = FileGroup('probably licenses')
-        self.unwanted = FileGroup('probably unwanted')
-        self.archives = FileGroup('archives')
-
-        for group in (self.required, self.optional, self.documentation,
-                self.licenses, self.archives, self.unwanted):
-            self.groups[group.name] = group
-
         self.has_dosbox = False
 
+    def new_group(self, stem):
+        i = 0
+        name = stem
+
+        while name in self.game.files or name in self.game.groups:
+            i += 1
+            name = '%s (%d)' % (stem, i)
+
+        return self.game.ensure_group(name)
+
     def is_scummvm(self,path):
         dir_l = path.lower()
         if dir_l.endswith('/scummvm') or '/scummvm/' in dir_l:
@@ -167,63 +165,69 @@ class Template:
             return True
         return False
 
-    def add_archive(self, path, lower=False, reader=None):
+    def add_archive(self, path, lower=False, reader=None, unpack=True):
         out_name = os.path.basename(path)
 
         if lower:
             out_name = out_name.lower()
 
-        result = self.add_file(path, out_name=out_name, group=self.archives)
-
-        unpacker = automatic_unpacker(path)
-
-        if unpacker is not None:
-            with unpacker:
-                self.add_unpacker(path, result, unpacker)
-
-        return result
+        return self.add_file(path, out_name=out_name,
+                group=self.game.ensure_group('archives'),
+                unpack=unpack)
 
     def add_unpacker(self, path, result, unpacker):
-        result.provides = ['contents of %s' % result.name]
-
         if result.unpack is None:
             result.unpack = dict(format=unpacker.format)
 
         if isinstance(unpacker, TarUnpacker):
             result.unpack['skip'] = unpacker.skip
 
-        group = FileGroup('contents of %s' % result.name)
-        self.groups[group.name] = group
+        main_group = self.new_group('contents of %s' % result.name)
+        opt_group = self.new_group('contents of %s - optional' % result.name)
+        doc_group = self.new_group('contents of %s - documentation' % result.name)
+        doc_group.doc = True
+        license_group = self.new_group('contents of %s - licenses' % result.name)
+        license_group.license = True
 
         for entry in unpacker:
             if entry.is_regular_file and entry.is_extractable:
                 try:
                     self.add_file(entry.name, opened=unpacker.open(entry),
                         size=entry.size, parent_unpacker=unpacker,
-                        group=group)
+                        main_group=main_group,
+                        opt_group=opt_group,
+                        doc_group=doc_group,
+                        license_group=license_group)
                 except NotImplementedError as e:
                     logger.warning("Can't decompress %s from %s: %s" %
                                    (entry.name, result.name, e))
 
+        result.provides = set()
+
+        for g in (main_group, opt_group, doc_group, license_group):
+            if g.group_members:
+                result.provides.add(g.name)
+
     def add_file(self, path, out_name=None, group=None, opened=None, size=None,
-            lang=None, parent_unpacker=None):
+            lang=None, parent_unpacker=None,
+            opt_group=None, doc_group=None, license_group=None,
+            unpack=False):
+
         if out_name is None:
             out_name = path
 
         match_path = '/' + path.lower()
+        ignorable = False
 
-        if group is not None:
-            # we already know what sort of file it is, probably an archive
-            pass
-        elif is_dosbox(path):
+        if is_dosbox(path):
             self.has_dosbox = True
-            group = self.unwanted
+            ignorable = True
         elif os.path.splitext(path.lower())[1] in ('.exe', '.exe$0', '.ovl',
                 '.dll', '.dll$0', '.bat', '.386'):
-            group = self.unwanted
+            ignorable = True
         elif out_name.startswith('goggame-') or out_name in ('webcache.zip',
                                                          'gog.ico', 'gfw_high.ico'):
-            group = self.unwanted
+            ignorable = True
 
         if opened is None:
             is_plain_file = True
@@ -293,6 +297,12 @@ class Template:
             result.sha1 = hf.sha1
             result.sha256 = hf.sha256
 
+            if ignorable:
+                result.ignorable = True
+
+            if ignorable:
+                result.ignorable = True
+
             self.game.files[result.name] = result
 
         for lf in result.look_for:
@@ -305,7 +315,7 @@ class Template:
 
         unpacker = None
 
-        if parent_unpacker is None or parent_unpacker.seekable():
+        if unpack and (parent_unpacker is None or parent_unpacker.seekable()):
             # skip PK3s: we don't normally want to recurse into them
             if not path.endswith('.pk3'):
                 if is_plain_file:
@@ -315,19 +325,43 @@ class Template:
 
         ext = path.lower().split('.')[-1]
 
-        if group is not None:
-            group.group_members.add(out_name)
-        elif is_license(path):
-            self.licenses.group_members.add(out_name)
-        elif is_doc(path):
-            self.documentation.group_members.add(out_name)
-        # most of the times these files are not needed
-        elif ext in ('cfg', 'cmd', 'com', 'drv', 'ico', 'ini'):
-            self.optional.group_members.add(out_name)
+        if group is None:
+            group = self.game.ensure_group('miscellaneous')
+
+        if opt_group is None:
+            opt_group = group
+
+        if license_group is None:
+            license_group = group
+
+        if doc_group is None:
+            doc_group = group
+
+        if result is not existing and ignorable:
+            result.ignorable = True
+
+        if result is not existing and is_license(path):
+                result.license = True
+
+        if result is not existing and is_doc(path):
+            result.doc = True
+
+        if result.license and result.doc:
+            license_group.group_members.add(result.name)
+            doc_group.group_members.add(result.name)
+        elif result.license:
+            license_group.group_members.add(result.name)
+        elif result.doc:
+            doc_group.group_members.add(result.name)
+        elif (
+                # most of the times these files are not needed
+                ext in ('cfg', 'cmd', 'com', 'drv', 'ico', 'ini') or
+                result.ignorable):
+            opt_group.group_members.add(result.name)
         elif unpacker is not None or ext in ('umod', 'zip'):
-            self.archives.group_members.add(out_name)
+            self.game.ensure_group('archives').group_members.add(result.name)
         else:
-            self.required.group_members.add(out_name)
+            group.group_members.add(result.name)
 
         if unpacker is not None:
             with unpacker:
@@ -335,12 +369,30 @@ class Template:
 
         return result
 
-    def add_one_dir(self, destdir, lower=False, game=None, lang=None):
+    def add_one_dir(self, destdir, lower=False, game=None, lang=None,
+            main_group=None, opt_group=None, doc_group=None,
+            license_group=None):
+        basename = os.path.basename(os.path.abspath(destdir))
+
+        if main_group is None:
+            main_group = self.new_group('contents of %s' % basename)
+
+        if opt_group is None:
+            opt_group = self.new_group('contents of %s - optional' % basename)
+
+        if doc_group is None:
+            doc_group = self.new_group('contents of %s - documentation' % basename)
+            doc_group.doc = True
+
+        if license_group is None:
+            license_group = self.new_group('contents of %s - licenses' % basename)
+            license_group.license = True
+
         if destdir.startswith('/usr/local') or destdir.startswith('/opt/'):
             self.game.try_repack_from.append(destdir)
 
         if not game:
-            game = os.path.basename(os.path.abspath(destdir))
+            game = basename
         if game.endswith('-data'):
             game = game[:len(game) - 5]
 
@@ -369,10 +421,10 @@ class Template:
                 self.package['lang'] = lang
             self.package['provides'] = virtual
 
-        self.package['install'] = [self.required.name]
-        self.package['optional'] = [self.optional.name]
-        self.package['doc'] = [self.documentation.name]
-        self.package['license'] = [self.licenses.name]
+        self.package['install'] = [main_group.name]
+        self.package['optional'] = [opt_group.name]
+        self.package['doc'] = [doc_group.name]
+        self.package['license'] = [license_group.name]
 
         if steam > 0:
             self.package['steam'] = steam_dict
@@ -393,9 +445,13 @@ class Template:
                 if os.path.isdir(path):
                     continue
                 elif os.path.islink(path):
-                    self.package.setdefault('symlinks', {})[name] = os.path.realpath(path)
+                    self.package.setdefault('symlinks', {})[path] = os.path.realpath(path)
                 elif os.path.isfile(path):
-                    self.add_file(path, out_name=out_name, lang=lang)
+                    self.add_file(path, out_name=out_name, lang=lang,
+                            group=main_group,
+                            doc_group=doc_group,
+                            license_group=license_group,
+                            opt_group=opt_group)
                 else:
                     logger.warning('ignoring unknown file type at %s' % path)
 
@@ -420,7 +476,7 @@ class Template:
             del self.package['license']
 
     def add_one_gog_sh(self,archive):
-        self.add_archive(archive)
+        self.add_archive(archive, unpack=True)
 
         with zipfile.ZipFile(archive, 'r') as zf:
             if 'scripts/config.lua' in zf.namelist():
@@ -444,6 +500,8 @@ class Template:
 
         tmp = tempfile.mkdtemp(prefix='gdptmp.')
 
+        result = self.add_archive(exe, lower, unpack=False)
+
         command = ['innoextract', os.path.realpath(exe)]
         version = check_output(['innoextract', '-v', '-s'], universal_newlines=True)
         if Version(version.split('-')[0]) >= Version('1.5'):
@@ -457,17 +515,26 @@ class Template:
                  universal_newlines=True,
                  cwd=tmp)
         self.game.longname = log.split('\n')[0].split('"')[1]
-        self.add_one_dir(os.path.join(tmp, 'app'), game=game, lang=guess_lang(exe), lower=lower)
-        rm_rf(tmp)
 
-        result = self.add_archive(exe, lower)
+        main_group = self.new_group('contents of %s' % result.name)
+        opt_group = self.new_group('contents of %s - optional' % result.name)
+        doc_group = self.new_group('contents of %s - documentation' % result.name)
+        doc_group.doc = True
+        license_group = self.new_group('contents of %s - licenses' % result.name)
+        license_group.license = True
+
+        self.add_one_dir(os.path.join(tmp, 'app'), game=game,
+                lang=guess_lang(exe), lower=lower,
+                main_group=main_group, opt_group=opt_group, doc_group=doc_group,
+                license_group=license_group)
+        rm_rf(tmp)
 
         result.unpack = dict(format='innoextract')
-        result.provides = [
-            # FIXME: Fill in what it really provides
-            'file1',
-            'file2',
-        ]
+        result.provides = set()
+
+        for g in (main_group, opt_group, doc_group, license_group):
+            if g.group_members:
+                result.provides.add(g.name)
 
     def add_one_deb(self,deb,lower):
         if not ON_DEBIAN or not which('dpkg-deb'):
@@ -475,6 +542,16 @@ class Template:
 
         control = None
 
+        result = self.add_archive(deb, unpack=False)
+        main_group = self.new_group('contents of %s' % result.name)
+        ignorable_group = self.new_group('contents of %s - ignorable' % result.name)
+        abs_group = self.new_group('contents of %s - unusual install path' % result.name)
+        abs_group.install_to = '.'
+        doc_group = self.new_group('contents of %s - documentation' % result.name)
+        doc_group.doc = True
+        license_group = self.new_group('contents of %s - licenses' % result.name)
+        license_group.license = True
+
         version = None
         with subprocess.Popen(['dpkg-deb', '--ctrl-tarfile', deb],
                 stdout=subprocess.PIPE) as ctrl_process:
@@ -508,13 +585,21 @@ class Template:
         if control is None:
             logger.error('Could not find DEBIAN/control')
 
+        result.unpack = dict(format='deb')
+        result.provides = set()
+
+        for g in (main_group, ignorable_group, abs_group, doc_group,
+                license_group):
+            if g.group_members:
+                result.provides.add(g.name)
+
         self.data = dict(packages={ control['package']: {} })
         self.package = self.data['packages'][control['package']]
 
-        self.package['install'] = [self.required.name]
-        self.package['optional'] = [self.optional.name]
-        self.package['doc'] = [self.documentation.name]
-        self.package['license'] = [self.licenses.name]
+        self.package['install'] = [main_group.name]
+        self.package['optional'] = [ignorable_group.name, abs_group.name]
+        self.package['doc'] = [doc_group.name]
+        self.package['license'] = [license_group.name]
 
         if version:
             self.package['version'] = version
@@ -559,31 +644,36 @@ class Template:
                 target = entry.get_symbolic_link_target()
 
                 if entry.is_regular_file:
+                    group = main_group
+
+                    if name.startswith('usr/share/doc/'):
+                        name = name[len('usr/share/doc/'):]
+                        name = name.split('/', 1)[1]
+                        group = doc_group
+
                     name_l = name.lower()
                     basename_l = os.path.basename(name_l)
-                    install_absolute = False
 
                     if os.path.splitext(name_l)[1] in ('.exe', '.bat'):
-                        group = self.unwanted
+                        group = ignorable_group
                     elif 'support/gog' in name_l or os.path.basename(name_l) in (
                                                     'start.sh', 'uninstall.sh'):
-                        group = self.unwanted
+                        group = ignorable_group
                     elif name.startswith('opt/') and is_license(name):
                         name = basename_l
-                        group = self.licenses
+                        group = license_group
                     elif name.startswith('opt/') and is_doc(name):
-                        group = self.documentation
-                    elif (install_to is not None and
-                        name.startswith(install_to + '/')):
+                        group = doc_group
+                    elif (group is main_group and
+                            install_to is not None and
+                            name.startswith(install_to + '/')):
                         name = name[len(install_to) + 1:]
                         if lower:
                             name = name.lower()
                         if self.gog and name.startswith('data/'):
                             name = name[len('data/'):]
-                        group = self.required
                     else:
-                        group = self.optional
-                        install_absolute = True
+                        group = abs_group
 
                     result = self.add_file(
                         deb + '//data.tar.*//' + name,
@@ -592,9 +682,6 @@ class Template:
                         opened=unpacker.open(entry),
                         size=entry.size,
                         parent_unpacker=unpacker)
-
-                    if install_absolute:
-                        result.install_to = '.'
                 elif entry.is_directory:
                     pass
                 elif target is not None:
@@ -620,11 +707,6 @@ class Template:
     def print_yaml(self):
         print('---')
 
-        data = self.game.to_data(expand=False, include_ignorable=True)
-
-        if data:
-            yaml.dump(data, default_flow_style=False, stream=sys.stdout)
-
         if self.plugin:
             print('plugin: %s' % self.plugin)
 
@@ -634,33 +716,16 @@ class Template:
                 if k in self.gog:
                     print('  %s: %s' % (k, self.gog[k]))
 
-        print('')
         if self.data:
             yaml.safe_dump(self.data, stream=sys.stdout,
                     default_flow_style=False)
 
-        print('\ngroups:')
-
-        for group in self.groups.values():
-            if not group.group_members:
-                # skip empty group
-                continue
-
-            print('  %s:' % group.name)
-
-            if group == self.documentation:
-                print('    doc: True')
-            elif group == self.licenses:
-                print('    license: True')
+        print('')
 
-            print('    group_members: |')
-            for f in sorted(group.group_members):
-                wanted = self.game.files[f]
+        data = self.game.to_data(expand=False, include_ignorable=True)
 
-                if f in self.unwanted.group_members:
-                    print('      .%-9s %s %s' % (wanted.size, wanted.md5, f))
-                else:
-                    print('      %-9s %s %s' % (wanted.size, wanted.md5, f))
+        if data:
+            yaml.dump(data, default_flow_style=False, stream=sys.stdout)
 
         print('\n...')
 
@@ -790,13 +855,10 @@ def main():
     for arg in args.args:
         basename = os.path.basename(arg)
         if os.path.isdir(arg):
-            template.add_one_dir(arg.rstrip('/'), args.lower, lang=guess_lang(arg))
+            template.add_one_dir(arg.rstrip('/'), args.lower,
+                    lang=guess_lang(arg))
         elif arg.endswith('.deb'):
             template.add_one_deb(arg,args.lower)
-            if basename.startswith('gog_'):
-                template.add_archive(arg, lower=args.lower)
-                template.files['files'][basename] = dict(unpack=dict(format='deb'),
-                                                         provides=['<stuff>'])
         elif basename.startswith('setup_') and arg.endswith('.exe'):
             if not which('innoextract'):
                 exit('Install innoextract')
@@ -804,7 +866,7 @@ def main():
         elif basename.startswith('gog_') and arg.endswith('.sh'):
             template.add_one_gog_sh(arg)
         else:
-            template.add_archive(arg, lower=args.lower)
+            template.add_archive(arg, lower=args.lower, unpack=True)
 
     template.print_yaml()
 

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