hack support for .tar.xz in (code from ftpadmin)
This commit is contained in:
parent
52293b880c
commit
efce501b5f
|
@ -366,10 +366,6 @@ class Lgo(App):
|
|||
href.startswith('http://ftp.gnome.org/')):
|
||||
continue
|
||||
filename = self.download(href)
|
||||
# FIXME: there's no support for .xz on the webapps vm used for
|
||||
# library-web, fallback to the .bz2 archive.
|
||||
if filename.endswith('.xz'):
|
||||
filename = os.path.splitext(filename)[0] + '.bz2'
|
||||
if not filename:
|
||||
continue
|
||||
logging.info('extracting module %s (from %s moduleset)' % (
|
||||
|
|
89
src/utils.py
89
src/utils.py
|
@ -22,6 +22,9 @@ import re
|
|||
import time
|
||||
import urllib2
|
||||
import sys
|
||||
import tarfile
|
||||
import lzma # pyliblzma
|
||||
|
||||
|
||||
class FakeTarFile:
|
||||
'''
|
||||
|
@ -104,3 +107,89 @@ class LogFormatter(logging.Formatter):
|
|||
sys.stdout.flush()
|
||||
return '%c:[%s] %s' % (record.levelname[0], time.strftime('%Y%m%d %H:%M:%S'), record.msg)
|
||||
|
||||
|
||||
class _LZMAProxy(object):
|
||||
"""Small proxy class that enables external file object
|
||||
support for "r:lzma" and "w:lzma" modes. This is actually
|
||||
a workaround for a limitation in lzma module's LZMAFile
|
||||
class which (unlike gzip.GzipFile) has no support for
|
||||
a file object argument.
|
||||
"""
|
||||
|
||||
blocksize = 16 * 1024
|
||||
|
||||
def __init__(self, fileobj, mode):
|
||||
self.fileobj = fileobj
|
||||
self.mode = mode
|
||||
self.name = getattr(self.fileobj, "name", None)
|
||||
self.init()
|
||||
|
||||
def init(self):
|
||||
self.pos = 0
|
||||
if self.mode == "r":
|
||||
self.lzmaobj = lzma.LZMADecompressor()
|
||||
self.fileobj.seek(0)
|
||||
self.buf = ""
|
||||
else:
|
||||
self.lzmaobj = lzma.LZMACompressor()
|
||||
|
||||
def read(self, size):
|
||||
b = [self.buf]
|
||||
x = len(self.buf)
|
||||
while x < size:
|
||||
raw = self.fileobj.read(self.blocksize)
|
||||
if not raw:
|
||||
break
|
||||
try:
|
||||
data = self.lzmaobj.decompress(raw)
|
||||
except EOFError:
|
||||
break
|
||||
b.append(data)
|
||||
x += len(data)
|
||||
self.buf = "".join(b)
|
||||
|
||||
buf = self.buf[:size]
|
||||
self.buf = self.buf[size:]
|
||||
self.pos += len(buf)
|
||||
return buf
|
||||
|
||||
def seek(self, pos):
|
||||
if pos < self.pos:
|
||||
self.init()
|
||||
self.read(pos - self.pos)
|
||||
|
||||
|
||||
class XzTarFile(tarfile.TarFile):
|
||||
|
||||
OPEN_METH = tarfile.TarFile.OPEN_METH.copy()
|
||||
OPEN_METH["xz"] = "xzopen"
|
||||
|
||||
@classmethod
|
||||
def xzopen(cls, name, mode="r", fileobj=None, **kwargs):
|
||||
"""Open gzip compressed tar archive name for reading or writing.
|
||||
Appending is not allowed.
|
||||
"""
|
||||
if len(mode) > 1 or mode not in "rw":
|
||||
raise ValueError("mode must be 'r' or 'w'")
|
||||
|
||||
if fileobj is not None:
|
||||
fileobj = _LMZAProxy(fileobj, mode)
|
||||
else:
|
||||
fileobj = lzma.LZMAFile(name, mode)
|
||||
|
||||
try:
|
||||
# lzma doesn't immediately return an error
|
||||
# try and read a bit of data to determine if it is a valid xz file
|
||||
fileobj.read(_LZMAProxy.blocksize)
|
||||
fileobj.seek(0)
|
||||
t = cls.taropen(name, mode, fileobj, **kwargs)
|
||||
except IOError:
|
||||
raise tarfile.ReadError("not a xz file")
|
||||
except lzma.error:
|
||||
raise tarfile.ReadError("not a xz file")
|
||||
t._extfileobj = False
|
||||
return t
|
||||
|
||||
if not hasattr(tarfile.TarFile, 'xvopen'):
|
||||
tarfile.open = XzTarFile.open
|
||||
|
||||
|
|
Reference in New Issue