Newer
Older
if self._size is None or self._md5 is None:
debug("Check is called on payload with nothing to check")
return True
fileobj = PipeFile(self.path, "r")
fileobj.consume()
fileobj.close()
if self._size != fileobj.read_size:
raise ISError(u"Invalid size of payload %s" % self.name)
if self._md5 != fileobj.md5:
raise ISError(u"Invalid MD5 of payload %s" % self._md5)
def download(self, dest, force=False):
'''
Download payload in directory
'''
# if dest is a directory try to create file inside
if os.path.isdir(dest):
dest = os.path.join(dest, self.filename)
# try to create leading directories
elif not os.path.exists(os.path.dirname(dest)):
istools.mkdir(os.path.dirname(dest))
# check validity of dest
if os.path.exists(dest):
if os.path.isdir(dest):
raise ISError(u"Destination %s is a directory" % dest)
raise ISError(u"File %s already exists" % dest)
debug(u"Downloading payload %s from %s" % (self.filename, self.path))
fs = PipeFile(self.path, progressbar=True)
# check if announced file size is good
if fs.size is not None and self.size != fs.size:
raise ISError(u"Downloading payload %s failed: Invalid announced size" %
fs.consume(fd)
# checking download size
if self.size != fs.read_size:
raise ISError(u"Downloading payload %s failed: Invalid size" % self.name)
raise ISError(u"Downloading payload %s failed: Invalid MD5" % self.name)
def extract(self, dest, force=False, filelist=None):
'''
Extract payload into dest
filelist is a filter of file in tarball
force will overwrite existing file if exists
'''
try:
if self.isdir:
self.extract_tar(dest, force=force, filelist=filelist)
else:
self.extract_file(dest, force=force)
except Exception as e:
raise ISError(u"Extracting payload %s failed" % self.name, e)
def extract_tar(self, dest, force=False, filelist=None):
'''
Extract a payload which is a tarball.
This is used mainly to extract payload from a directory
'''
# check validity of dest
if os.path.exists(dest):
if not os.path.isdir(dest):
raise ISError(u"Destination %s is not a directory" % dest)
raise ISError(u"Directory %s is not empty (need force)" % dest)
fo = PipeFile(self.path, progressbar=True)
raise ISError(u"Unable to open %s" % self.path)
# check if announced file size is good
if fo.size is not None and self.size != fo.size:
raise ISError(u"Invalid announced size on %s" % self.path)
# get compressor argv (first to escape file creation if not found)
a_comp = istools.get_compressor_path(self.compressor, compress=False)
a_tar = ["tar", "--extract", "--numeric-owner", "--ignore-zeros",
"--preserve-permissions", "--directory", dest]
# add optionnal selected filename for decompression
if filelist is not None:
a_tar += filelist
p_tar = subprocess.Popen(a_tar, shell=False, close_fds=True,
stdin=subprocess.PIPE)
p_comp = subprocess.Popen(a_comp, shell=False, close_fds=True,
stdin=subprocess.PIPE, stdout=p_tar.stdin)
# close tar fd
p_tar.stdin.close()
# push data into compressor
fo.consume(p_comp.stdin)
# close source fd
if self.size != fo.read_size:
# close compressor pipe
p_comp.stdin.close()
# check compressor return 0
if p_comp.wait() != 0:
raise ISError(u"Compressor %s return is not zero" % a_comp[0])
# check tar return 0
if p_tar.wait() != 0:
raise ISError("Tar return is not zero")
def extract_file(self, dest, force=False):
'''
Copy a payload directly to a file
Check md5 on the fly
'''
# if dest is a directory try to create file inside
if os.path.isdir(dest):
dest = os.path.join(dest, self.name)
# try to create leading directories
elif not os.path.exists(os.path.dirname(dest)):
istools.mkdir(os.path.dirname(dest))
if os.path.isdir(dest):
raise ISError(u"Destination %s is a directory" % dest)
raise ISError(u"File %s already exists" % dest)
# get compressor argv (first to escape file creation if not found)
a_comp = istools.get_compressor_path(self.compressor, compress=False)
# try to open payload file (source)
f_src = PipeFile(self.path, "r", progressbar=True)
raise ISError(u"Unable to open payload file %s" % self.path, e)
# check if announced file size is good
if f_src.size is not None and self.size != f_src.size:
raise ISError(u"Invalid announced size on %s" % self.path)
raise ISError(u"Unable to open destination file %s" % dest, e)
# run compressor process
p_comp = subprocess.Popen(a_comp, shell=False, close_fds=True,
stdin=subprocess.PIPE, stdout=f_dst)
# close destination file
# push data into compressor
f_src.consume(p_comp.stdin)
# closing source fo
if self.size != f_src.read_size:
# checking downloaded md5
if self.md5 != f_src.md5:
# close compressor pipe
p_comp.stdin.close()
# check compressor return 0
if p_comp.wait() != 0:
raise ISError(u"Compressor %s return is not zero" % a_comp[0])
# settings file orginal rights
istools.chrights(dest, self.uid, self.gid, self.mode, self.mtime)
'''
Object representing a changelog in memory
'''
self.load(data)
def load(self, data):
'''
Load a changelog file
'''
# ensure data are correct UTF-8
if isinstance(data, str):
try:
data = unicode(data, "UTF-8")
except UnicodeDecodeError:
raise ISError("Invalid character encoding in changelog")
version = None
lines = data.split("\n")
for line in lines:
# ignore empty lines
if len(line.strip()) == 0:
continue
# ignore comments
if line.lstrip().startswith("#"):
continue
# try to match a new version
m = re.match("\[(\d+)\]", line.lstrip())
if m is not None:
version = int(m.group(1))
self[version] = []
continue
# if line are out of a version => invalid format
if version is None:
raise ISError("Invalid format: Line outside version")
# add line to version changelog
self[version] += [line]
# save original
self.verbatim = data
def show(self, version=None, verbose=False):
'''
Show changelog for a given version or all
'''
out('#light##yellow#Changelog:#reset#')
# if no version take the hightest
if version is None:
version = max(self)
# display asked version
if version in self:
self._show_version(version)
# display all version in verbose mode
if verbose:
for ver in sorted((k for k in self if k < version), reverse=True):
self._show_version(ver)
def _show_version(self, version):
'''
Display a version content
'''
out(u' #yellow#Version:#reset# %s' % version)
out(os.linesep.join(self[version]))