def __init__(self, config = None, db=None): self.config = config self.modules = {} self.raise_exception_on_warning=False if db is None: legacy_pkgdb_path = os.path.join(self.config.prefix, 'share', 'icbuild', 'packagedb.xml') new_pkgdb_path = os.path.join(self.config.top_builddir, 'packagedb.xml') if os.path.isfile(legacy_pkgdb_path): fileutils.rename(legacy_pkgdb_path, new_pkgdb_path) self.packagedb = packagedb.PackageDB(new_pkgdb_path, config) else: self.packagedb = db
def unpack_archive(buildscript, localfile, target_directory, checkoutdir=None): """ Unpack @localfile to @target_directory; if @checkoutdir is specified make sure the unpacked content gets into a directory by that name """ if checkoutdir: final_target_directory = target_directory target_directory = tempfile.mkdtemp(dir=final_target_directory) ext = os.path.splitext(localfile)[-1] if ext == '.lzma' and has_command('lzcat.exe') and has_command('tar.exe'): buildscript.execute('lzcat -d "%s" | tar xf -' % localfile, cwd=target_directory) elif ext == '.xz' and has_command('xzcat.exe') and has_command('tar.exe'): buildscript.execute('xzcat -d "%s" | tar xf -' % localfile, cwd=target_directory) elif ext == '.bz2' and has_command('bunzip2.exe') and has_command('tar.exe'): buildscript.execute('bunzip2 -dc "%s" | tar xf -' % localfile, cwd=target_directory) elif ext in ('.gz', '.tgz') and has_command('gzip.exe') and has_command('tar.exe'): buildscript.execute('gzip -dc "%s" | tar xf -' % localfile, cwd=target_directory) elif ext == '.zip' and has_command('unzip.exe'): buildscript.execute('unzip "%s"' % localfile, cwd=target_directory) else: try: if tarfile.is_tarfile(localfile): unpack_tar_file(localfile, target_directory) elif zipfile.is_zipfile(localfile): unpack_zip_file(localfile, target_directory) else: raise CommandError('Failed to unpack %s (unknown archive type)' % localfile) except: raise CommandError('Failed to unpack %s' % localfile) if checkoutdir: # tarball has been extracted in $destdir/$tmp/, check, then move the # content of that directory if len(os.listdir(target_directory)) == 0: raise CommandError('Failed to unpack %s (empty file?)' % localfile) if len(os.listdir(target_directory)) == 1: # a single directory, just move it tmpdirname = os.path.join(target_directory, os.listdir(target_directory)[0]) fileutils.rename(tmpdirname, os.path.join(final_target_directory, checkoutdir)) os.rmdir(target_directory) else: # more files, just rename the temporary directory to the final name fileutils.rename(target_directory, os.path.join(final_target_directory, checkoutdir))
def _process_install_files(self, installroot, curdir, prefix, errors): """Strip the prefix from all files in the install root, and move them into the prefix.""" assert os.path.isdir(installroot) and os.path.isabs(installroot) assert os.path.isdir(curdir) and os.path.isabs(curdir) assert os.path.isdir(prefix) and os.path.isabs(prefix) if prefix.endswith('/'): prefix = prefix[:-1] num_copied = 0 names = os.listdir(curdir) for filename in names: src_path = os.path.join(curdir, filename) assert src_path.startswith(installroot) dest_path = src_path[len(installroot):] try: if os.path.islink(src_path): linkto = os.readlink(src_path) if os.path.islink(dest_path) or os.path.isfile(dest_path): os.unlink(dest_path) os.symlink(linkto, dest_path) os.unlink(src_path) num_copied += 1 elif os.path.isdir(src_path): if os.path.exists(dest_path): if not os.path.isdir(dest_path): os.unlink(dest_path) os.mkdir(dest_path) else: os.mkdir(dest_path) num_copied += self._process_install_files(installroot, src_path, prefix, errors) try: os.rmdir(src_path) except OSError: # files remaining in buildroot, errors reported below pass else: try: fileutils.rename(src_path, dest_path) num_copied += 1 except OSError as e: errors.append("%s: '%s'" % (str(e), dest_path)) except OSError as e: errors.append(str(e)) return num_copied
def process_install(self, buildscript, revision): assert self.supports_install_destdir destdir = self.get_destdir(buildscript) self._clean_la_files(buildscript, destdir) self._clean_texinfo_dir_files(buildscript, destdir) prefix_without_drive = os.path.splitdrive(buildscript.config.prefix)[1] stripped_prefix = prefix_without_drive[1:] install_succeeded = False save_broken_tree = False broken_name = destdir + '-broken' destdir_prefix = os.path.join(destdir, stripped_prefix) new_contents = fileutils.accumulate_dirtree_contents(destdir_prefix) errors = [] if os.path.isdir(destdir_prefix): destdir_install = True logging.info('Moving temporary DESTDIR %r into build prefix' % (destdir, )) num_copied = self._process_install_files(destdir, destdir_prefix, buildscript.config.prefix, errors) # Now the destdir should have a series of empty directories: # $JHBUILD_PREFIX/_icbuild/root-foo/$JHBUILD_PREFIX # Remove them one by one to clean the tree to the state we expect, # so we can better spot leftovers or broken things. prefix_dirs = filter(lambda x: x != '', stripped_prefix.split(os.sep)) while len(prefix_dirs) > 0: dirname = prefix_dirs.pop() subprefix = os.path.join(*([destdir] + prefix_dirs)) target = os.path.join(subprefix, dirname) assert target.startswith(buildscript.config.prefix) try: os.rmdir(target) except OSError as e: pass remaining_files = os.listdir(destdir) if len(remaining_files) > 0: logging.warn("Files remaining in buildroot %(dest)r; module may have installed files outside of prefix." % {'num': len(remaining_files), 'dest': broken_name}) save_broken_tree = True # Even if there are some files outside the DESTDIR, count that as success for now; we just warn install_succeeded = True else: save_broken_tree = True if save_broken_tree: if os.path.exists(broken_name): assert broken_name.startswith(buildscript.config.top_builddir) shutil.rmtree(broken_name) fileutils.rename(destdir, broken_name) else: assert destdir.startswith(buildscript.config.prefix) os.rmdir(destdir) if not install_succeeded: raise CommandError("Module failed to install into DESTDIR %(dest)r" % {'dest': broken_name}) else: to_delete = set() previous_entry = buildscript.moduleset.packagedb.get(self.name) if previous_entry: previous_contents = previous_entry.get_manifest() if previous_contents: to_delete.update(fileutils.filter_files_by_prefix(self.config, previous_contents)) for filename in new_contents: to_delete.discard (os.path.join(self.config.prefix, filename)) if to_delete: # paranoid double-check assert to_delete == set(fileutils.filter_files_by_prefix(self.config, to_delete)) logging.info('%d files remaining from previous build' % (len(to_delete),)) for (path, was_deleted, error_string) in fileutils.remove_files_and_dirs(to_delete, allow_nonempty_dirs=True): if was_deleted: logging.info('Deleted: %(file)r' % { 'file': path, }) elif error_string is None: # We don't warn on not-empty directories pass else: logging.warn("Failed to delete no longer installed file %(file)r: %(msg)s" % { 'file': path, 'msg': error_string}) buildscript.moduleset.packagedb.add(self.name, revision or '', new_contents, self.configure_cmd) if errors: raise CommandError('Install encountered errors: %(num)d ' 'errors raised, %(files)d files copied. ' 'The errors are:\n %(err)s' % {'num' : len(errors), 'files' : num_copied, 'err' : '\n '.join(errors)}) else: logging.info('Install complete: %d files copied' % (num_copied, ))