class Installer: "Installer class, provides install routines for pisi packages" def __init__(self, package_fname): "initialize from a file name" self.package = Package(package_fname) self.package.read() self.metadata = self.package.metadata self.files = self.package.files self.pkginfo = self.metadata.package def install(self, ask_reinstall = True): "entry point" ctx.ui.info('Installing %s, version %s, release %s, build %s' % (self.pkginfo.name, self.pkginfo.version, self.pkginfo.release, self.pkginfo.build)) self.ask_reinstall = ask_reinstall self.check_requirements() self.check_relations() self.reinstall() self.extract_install() self.store_pisi_files() if ctx.comard: self.register_comar_scripts() self.update_databases() def check_requirements(self): """check system requirements""" #TODO: IS THERE ENOUGH SPACE? # what to do if / is split into /usr, /var, etc. pass def check_relations(self): # check if package is in database # If it is not, put it into 3rd party packagedb if not packagedb.has_package(self.pkginfo.name): db = packagedb.thirdparty_packagedb db.add_package(self.pkginfo) # check conflicts for pkg in self.metadata.package.conflicts: if ctx.installdb.is_installed(self.pkginfo): raise InstallError("Package conflicts " + pkg) # check dependencies if not ctx.config.get_option('ignore_dependency'): if not dependency.installable(self.pkginfo.name): ctx.ui.error('Dependencies for ' + self.pkginfo.name + ' not satisfied') raise InstallError("Package not installable") def reinstall(self): "check reinstall, confirm action, and remove package if reinstall" pkg = self.pkginfo if ctx.installdb.is_installed(pkg.name): # is this a reinstallation? (iversion, irelease, ibuild) = ctx.installdb.get_version(pkg.name) # determine if same version same_ver = False ignore_build = ctx.config.options and ctx.config.options.ignore_build_no if (not ibuild) or (not pkg.build) or ignore_build: # we don't look at builds to compare two package versions if pkg.version == iversion and pkg.release == irelease: same_ver = True else: if pkg.build == ibuild: same_ver = True if same_ver: if self.ask_reinstall: if not ctx.ui.confirm('Re-install same version package?'): raise InstallError('Package re-install declined') else: upgrade = False # is this an upgrade? # determine and report the kind of upgrade: version, release, build if pkg.version > iversion: ctx.ui.info('Upgrading to new upstream version') upgrade = True elif pkg.release > irelease: ctx.ui.info('Upgrading to new distribution release') upgrade = True elif ((not ignore_build) and ibuild and pkg.build and pkg.build > ibuild): ctx.ui.info('Upgrading to new distribution build') upgrade = True # is this a downgrade? confirm this action. if self.ask_reinstall and (not upgrade): if pkg.version < iversion: x = 'Downgrade to old upstream version?' elif pkg.release < irelease: x = 'Downgrade to old distribution release?' else: x = 'Downgrade to old distribution build?' if not ctx.ui.confirm(x): raise InstallError('Package downgrade declined') # remove old package then operations.remove_single(pkg.name) def extract_install(self): "unzip package in place" ctx.ui.info('Extracting files,') self.package.extract_dir_flat('install', ctx.config.destdir) def store_pisi_files(self): """put files.xml, metadata.xml, actions.py and COMAR scripts somewhere in the file system. We'll need these in future...""" ctx.ui.info('Storing %s, ' % ctx.const.files_xml) self.package.extract_file(ctx.const.files_xml, self.package.pkg_dir()) ctx.ui.info('%s.' % ctx.const.metadata_xml) self.package.extract_file(ctx.const.metadata_xml, self.package.pkg_dir()) for pcomar in self.metadata.package.providesComar: fpath = os.path.join(ctx.const.comar_dir, pcomar.script) # comar prefix is added to the pkg_dir while extracting comar # script file. so we'll use pkg_dir as destination. ctx.ui.info('Storing %s' % fpath) self.package.extract_file(fpath, self.package.pkg_dir()) def register_comar_scripts(self): "register COMAR scripts" com = ctx.comard for pcomar in self.metadata.package.providesComar: scriptPath = os.path.join(self.package.comar_dir(),pcomar.script) ctx.ui.info("Registering COMAR script %s" % pcomar.script) com.register(pcomar.om, self.metadata.package.name, scriptPath) while 1: reply = com.read_cmd() if reply[0] == com.RESULT: break elif reply[1] == com.ERROR: raise InstallError, "COMAR.register failed!" def update_databases(self): "update databases" # installdb ctx.installdb.install(self.metadata.package.name, self.metadata.package.version, self.metadata.package.release, self.metadata.package.build, self.metadata.package.distribution) # installed packages packagedb.inst_packagedb.add_package(self.pkginfo)
class Install(AtomicOperation): "Install class, provides install routines for pisi packages" def __init__(self, package_fname, ignore_dep = None): "initialize from a file name" super(Install, self).__init__(ignore_dep) self.package = Package(package_fname) self.package.read() self.metadata = self.package.metadata self.files = self.package.files self.pkginfo = self.metadata.package def install(self, ask_reinstall = True): "entry point" ctx.ui.status(_('Installing %s, version %s, release %s, build %s') % (self.pkginfo.name, self.pkginfo.version, self.pkginfo.release, self.pkginfo.build)) ctx.ui.notify(pisi.ui.installing, package = self.pkginfo, files = self.files) self.ask_reinstall = ask_reinstall self.check_requirements() self.check_relations() self.check_reinstall() self.extract_install() self.store_pisi_files() if ctx.comar: import pisi.comariface as comariface self.register_comar_scripts() comariface.run_postinstall(self.pkginfo.name) self.update_databases() self.update_environment() ctx.ui.status() if self.upgrade: event = pisi.ui.upgraded else: event = pisi.ui.installed ctx.ui.notify(event, package = self.pkginfo, files = self.files) def check_requirements(self): """check system requirements""" #TODO: IS THERE ENOUGH SPACE? # what to do if / is split into /usr, /var, etc. pass def check_relations(self): # check conflicts for pkg in self.metadata.package.conflicts: if ctx.installdb.is_installed(self.pkginfo): raise Error(_("Package conflicts %s") % pkg) # check dependencies if not ctx.config.get_option('ignore_dependency'): if not self.pkginfo.installable(): ctx.ui.error(_('Dependencies for %s not satisfied') % self.pkginfo.name) raise Error(_("Package not installable")) # check if package is in database # If it is not, put it into 3rd party packagedb if not packagedb.has_package(self.pkginfo.name): db = packagedb.thirdparty_packagedb db.add_package(self.pkginfo) def check_reinstall(self): "check reinstall, confirm action, and schedule reinstall" pkg = self.pkginfo self.reinstall = False self.upgrade = False if ctx.installdb.is_installed(pkg.name): # is this a reinstallation? (iversion, irelease, ibuild) = ctx.installdb.get_version(pkg.name) # determine if same version same_ver = False ignore_build = ctx.config.options and ctx.config.options.ignore_build_no if (not ibuild) or (not pkg.build) or ignore_build: # we don't look at builds to compare two package versions if pkg.version == iversion and pkg.release == irelease: same_ver = True else: if pkg.build == ibuild: same_ver = True if same_ver: if self.ask_reinstall: if not ctx.ui.confirm(_('Re-install same version package?')): raise Error(_('Package re-install declined')) else: upgrade = False # is this an upgrade? # determine and report the kind of upgrade: version, release, build if pkg.version > iversion: ctx.ui.info(_('Upgrading to new upstream version')) upgrade = True elif pkg.release > irelease: ctx.ui.info(_('Upgrading to new distribution release')) upgrade = True elif ((not ignore_build) and ibuild and pkg.build and pkg.build > ibuild): ctx.ui.info(_('Upgrading to new distribution build')) upgrade = True self.upgrade = upgrade # is this a downgrade? confirm this action. if self.ask_reinstall and (not upgrade): if pkg.version < iversion: x = _('Downgrade to old upstream version?') elif pkg.release < irelease: x = _('Downgrade to old distribution release?') else: x = _('Downgrade to old distribution build?') if not ctx.ui.confirm(x): raise Error(_('Package downgrade declined')) # schedule for reinstall self.old_files = ctx.installdb.files(pkg.name) self.old_path = ctx.installdb.pkg_dir(pkg.name, iversion, irelease) self.reinstall = True Remove(pkg.name).run_preremove() def extract_install(self): "unzip package in place" ctx.ui.info(_('Extracting files')) self.package.extract_dir_flat('install', ctx.config.dest_dir()) if self.reinstall: # remove left over files new = set(map(lambda x: str(x.path), self.files.list)) old = set(map(lambda x: str(x.path), self.old_files.list)) leftover = old - new old_fileinfo = {} for fileinfo in self.old_files.list: old_fileinfo[str(fileinfo.path)] = fileinfo for path in leftover: Remove.remove_file( old_fileinfo[path] ) def store_pisi_files(self): """put files.xml, metadata.xml, actions.py and COMAR scripts somewhere in the file system. We'll need these in future...""" ctx.ui.info(_('Storing %s, ') % ctx.const.files_xml) self.package.extract_file(ctx.const.files_xml, self.package.pkg_dir()) ctx.ui.info(_('Storing %s.') % ctx.const.metadata_xml) self.package.extract_file(ctx.const.metadata_xml, self.package.pkg_dir()) for pcomar in self.metadata.package.providesComar: fpath = os.path.join(ctx.const.comar_dir, pcomar.script) # comar prefix is added to the pkg_dir while extracting comar # script file. so we'll use pkg_dir as destination. ctx.ui.info(_('Storing %s') % fpath) self.package.extract_file(fpath, self.package.pkg_dir()) def register_comar_scripts(self): "register COMAR scripts" for pcomar in self.metadata.package.providesComar: scriptPath = os.path.join(self.package.comar_dir(),pcomar.script) import pisi.comariface pisi.comariface.register(pcomar, self.metadata.package.name, scriptPath) def update_databases(self): "update databases" if self.reinstall: Remove(self.metadata.package.name).remove_db() Remove.remove_pisi_files(self.old_path) # installdb ctx.installdb.install(self.metadata.package.name, self.metadata.package.version, self.metadata.package.release, self.metadata.package.build, self.metadata.package.distribution) # filesdb ctx.filesdb.add_files(self.metadata.package.name, self.files) # installed packages packagedb.inst_packagedb.add_package(self.pkginfo) def update_environment(self): # check if we have any shared objects or anything under # /etc/env.d shared = False for x in self.files.list: if x.path.endswith('.so') or x.path.startswith('/etc/env.d'): shared = True break if not ctx.get_option('bypass_ldconfig'): if shared: ctx.ui.info(_("Regenerating /etc/ld.so.cache...")) util.env_update() else: ctx.ui.warning(_("Bypassing ldconfig"))