[game-data-packager] 34/51: make_template: Use a new dpkg-deb unpacker instead of reinventing it
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 c6f08b644a1b959d53e9aba6cb2f8d3991b197ba
Author: Simon McVittie <smcv at debian.org>
Date: Thu Dec 28 17:16:05 2017 +0000
make_template: Use a new dpkg-deb unpacker instead of reinventing it
Signed-off-by: Simon McVittie <smcv at debian.org>
---
game_data_packager/make_template.py | 151 +++++++++++++++++-----------------
game_data_packager/unpack/__init__.py | 72 ++++++++++++++++
2 files changed, 147 insertions(+), 76 deletions(-)
diff --git a/game_data_packager/make_template.py b/game_data_packager/make_template.py
index fcfc3dc..a836174 100644
--- a/game_data_packager/make_template.py
+++ b/game_data_packager/make_template.py
@@ -39,7 +39,7 @@ from .data import (FileGroup, HashedFile)
from .game import (GameData)
from .gog import GOG
from .steam import parse_acf
-from .unpack import TarUnpacker
+from .unpack import (DpkgDebUnpacker, TarUnpacker)
from .unpack.auto import automatic_unpacker
from .util import (
check_output,
@@ -475,85 +475,84 @@ class Template:
install_to = None
- with subprocess.Popen(['dpkg-deb', '--fsys-tarfile', deb],
- stdout=subprocess.PIPE) as fsys_process:
- with tarfile.open(deb + '//data.tar.*', mode='r|',
- fileobj=fsys_process.stdout) as fsys_tarfile:
- for entry in fsys_tarfile:
- name = entry.name
- if name.startswith('./'):
- name = name[2:]
+ with DpkgDebUnpacker(deb) as unpacker:
+ for entry in unpacker:
+ name = entry.name
+ if name.startswith('./'):
+ name = name[2:]
- if self.is_scummvm(name) or is_runtime(name):
- continue
- if (name.startswith('usr/share/doc/') and
- name.endswith('changelog.gz')):
- continue
- if (name.startswith('usr/share/doc/') and
- name.endswith('changelog.Debian.gz')):
- continue
+ if self.is_scummvm(name) or is_runtime(name):
+ continue
+ if (name.startswith('usr/share/doc/') and
+ name.endswith('changelog.gz')):
+ continue
+ if (name.startswith('usr/share/doc/') and
+ name.endswith('changelog.Debian.gz')):
+ continue
- if (name.startswith('usr/share/doc/') and
- name.endswith('copyright')):
- print('# data/%s.copyright' % control['package'])
- for line in fsys_tarfile.extractfile(entry):
- print(line.decode('utf-8'), end='')
- print('')
- continue
+ if (name.startswith('usr/share/doc/') and
+ name.endswith('copyright')):
+ print('# data/%s.copyright' % control['package'])
+ for line in unpacker.open(entry):
+ print(line.decode('utf-8'), end='')
+ print('')
+ continue
- if (entry.isfile() and install_to is None):
- # assume this is the place
- if name.startswith('usr/share/games/'):
- there = name[len('usr/share/games/'):]
- there = there.split('/', 1)[0]
- install_to = ('usr/share/games/' + there)
- elif name.startswith('opt/GOG Games/'):
- there = name[len('opt/GOG Games/'):]
- there = there.split('/', 1)[0]
- install_to = ('opt/GOG Games/' + there)
- self.gog['path'] = '"%s"' % there
-
- if entry.isfile():
- hf = HashedFile.from_file(deb + '//data.tar.*//' + name,
- fsys_tarfile.extractfile(entry))
- name_l = name.lower()
- basename_l = os.path.basename(name_l)
-
- if os.path.splitext(name_l)[1] in ('.exe', '.bat'):
- self.unwanted.group_members.add(name_l)
- elif 'support/gog' in name_l or os.path.basename(name_l) in (
- 'start.sh', 'uninstall.sh'):
- self.unwanted.group_members.add(name_l)
- elif name.startswith('opt/') and is_license(name):
- name = basename_l
- self.licenses.group_members.add(name)
- elif name.startswith('opt/') and is_doc(name):
- name = basename_l
- self.documentation.group_members.add(name)
- elif (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/'):]
- self.required.group_members.add(name)
- else:
- self.optional.group_members.add(name)
- self.file_data[name] = dict(install_to='.')
-
- self.size[name] = entry.size
- self.md5[name] = hf.md5
- self.sha1[name] = hf.sha1
- self.sha256[name] = hf.sha256
- elif entry.isdir():
- pass
- elif entry.issym():
- self.package.setdefault('symlinks', {})[name] = os.path.join(
- os.path.dirname(name), entry.linkname)
+ if entry.is_regular_file and install_to is None:
+ # assume this is the place
+ if name.startswith('usr/share/games/'):
+ there = name[len('usr/share/games/'):]
+ there = there.split('/', 1)[0]
+ install_to = ('usr/share/games/' + there)
+ elif name.startswith('opt/GOG Games/'):
+ there = name[len('opt/GOG Games/'):]
+ there = there.split('/', 1)[0]
+ install_to = ('opt/GOG Games/' + there)
+ self.gog['path'] = '"%s"' % there
+
+ target = entry.get_symbolic_link_target()
+
+ if entry.is_regular_file:
+ hf = HashedFile.from_file(deb + '//data.tar.*//' + name,
+ unpacker.open(entry), size=entry.size)
+ name_l = name.lower()
+ basename_l = os.path.basename(name_l)
+
+ if os.path.splitext(name_l)[1] in ('.exe', '.bat'):
+ self.unwanted.group_members.add(name_l)
+ elif 'support/gog' in name_l or os.path.basename(name_l) in (
+ 'start.sh', 'uninstall.sh'):
+ self.unwanted.group_members.add(name_l)
+ elif name.startswith('opt/') and is_license(name):
+ name = basename_l
+ self.licenses.group_members.add(name)
+ elif name.startswith('opt/') and is_doc(name):
+ name = basename_l
+ self.documentation.group_members.add(name)
+ elif (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/'):]
+ self.required.group_members.add(name)
else:
- logger.warning('unhandled data.tar entry type: %s: %s',
- name, entry.type)
+ self.optional.group_members.add(name)
+ self.file_data[name] = dict(install_to='.')
+
+ self.size[name] = hf.size
+ self.md5[name] = hf.md5
+ self.sha1[name] = hf.sha1
+ self.sha256[name] = hf.sha256
+ elif entry.is_directory:
+ pass
+ elif target is not None:
+ self.package.setdefault('symlinks', {})[name] = os.path.join(
+ os.path.dirname(name), target)
+ else:
+ logger.warning('unhandled data.tar entry type: %s: %s',
+ name, entry.type_indicator)
if self.plugin != 'scummvm_common' and install_to is not None:
self.package['install_to'] = os.path.join('/',
diff --git a/game_data_packager/unpack/__init__.py b/game_data_packager/unpack/__init__.py
index f08ff85..f0a7123 100644
--- a/game_data_packager/unpack/__init__.py
+++ b/game_data_packager/unpack/__init__.py
@@ -21,6 +21,7 @@ import errno
import os
import shlex
import shutil
+import subprocess
import tarfile
import time
import zipfile
@@ -50,6 +51,12 @@ class UnpackableEntry(metaclass=ABCMeta):
"""
return self.is_regular_file
+ def get_symbolic_link_target(self):
+ """Target of the symbolic link, or None if this is not a
+ symbolic link.
+ """
+ return None
+
@property
def mtime(self):
"""The last-modification time, or None if unspecified."""
@@ -74,6 +81,8 @@ class UnpackableEntry(metaclass=ABCMeta):
ret = 'd'
elif self.is_regular_file:
ret = '-'
+ elif self.get_symbolic_link_target() is not None:
+ ret = 'l'
else:
ret = '?'
@@ -230,6 +239,69 @@ class TarEntry(UnpackableEntry):
def size(self):
return self.impl.size
+ def get_symbolic_link_target(self):
+ if self.impl.issym():
+ return self.impl.linkname
+ else:
+ return None
+
+ @property
+ def type_indicator(self):
+ """One or more ASCII symbols indicating the file type."""
+ if self.impl.isdir():
+ ret = 'd'
+ elif self.impl.isfile():
+ ret = '-'
+ elif self.impl.issym():
+ ret = 'l'
+ else:
+ ret = '?<%s>' % self.impl.type
+
+ if self.is_extractable:
+ ret += 'r'
+ else:
+ ret += '-'
+
+ return ret
+
+class DpkgDebUnpacker(WrapperUnpacker):
+ def __init__(self, path):
+ self._path = path
+ self._fsys_process = None
+
+ def __enter__(self):
+ self._fsys_process = subprocess.Popen(
+ ['dpkg-deb', '--fsys-tarfile', self._path],
+ stdout=subprocess.PIPE,
+ ).__enter__()
+ self._impl = tarfile.open(
+ self._path, mode='r|', fileobj=self._fsys_process.stdout,
+ ).__enter__()
+ return self
+
+ def __exit__(self, ex_type, ex_value, ex_traceback):
+ if self._impl is not None:
+ self._impl.__exit__(ex_type, ex_value, ex_traceback)
+ self._impl = None
+
+ if self._fsys_process is not None:
+ self._fsys_process.__exit__(ex_type, ex_value, ex_traceback)
+ self._fsys_process = None
+
+ @property
+ def format(self):
+ return 'deb'
+
+ def open(self, entry):
+ assert isinstance(entry, TarEntry)
+ return self._impl.extractfile(entry.impl)
+
+ def _is_entry(self, entry):
+ return isinstance(entry, TarEntry)
+
+ def _wrap_entry(self, entry):
+ return TarEntry(entry)
+
class TarUnpacker(WrapperUnpacker):
def __init__(self, name, reader=None, compression='*', skip=0):
super(TarUnpacker, self).__init__()
--
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