def run(self): """ Go, go, go! """ ### Sanity checks for pkg in self.args.packages: if not self.pm.installed(recipe.get_recipe(pkg)): self.log.error("Package {0} is not installed into current prefix. Aborting.".format(pkg)) exit(1) ### Make install tree rb_tree = dep_manager.DepManager().make_dep_tree( self.args.packages, lambda x: bool( (x in self.args.packages) or \ (self.args.deps and self.pm.installed(recipe.get_recipe(x))) ) ) self.log.debug("Install tree:") if self.log.getEffectiveLevel() <= 20 or self.args.print_tree: rb_tree.pretty_print() ### Recursively rebuild, starting at the leaf nodes while not rb_tree.empty(): pkg = rb_tree.pop_leaf_node() rec = recipe.get_recipe(pkg) self.log.info("Rebuilding package: {0}".format(pkg)) if not self.pm.rebuild( rec, make_clean=self.args.clean, nuke_builddir=not self.args.keep_build ): self.log.error("Error rebuilding package {0}. Aborting.".format(pkg)) exit(1) self.log.info("Rebuild successful.")
def _add_deps_recursive(self, install_tree, pkg, filter_callback): """ Recursively add dependencies to the install tree. """ # Load deps: deps = recipe.get_recipe(pkg).get_local_package_data()['depends'] or [] # Filter for illegal stuff: for dep in deps: if not self.pm.exists(pkg): self.log.error("Package does not exist: {0} (declared as dependency for package {1})".format(dep, pkg)) exit(1) # Filter all packages either already in the tree, or not wanted: deps_to_install = filter( lambda pkg: pkg is not None and filter_callback(pkg) and pkg not in install_tree.get_nodes(), deps ) if len(deps_to_install) == 0: return # First, add all dependencies into the install tree: install_tree.insert_at(deps_to_install, pkg) # Then, extend the tree if the dependencies have dependencies themselves: for dep in deps_to_install: if isinstance(dep, list): # I honestly have no clue why this happens, yet sometimes # it does. continue self._add_deps_recursive(install_tree, dep, filter_callback)
def __init__(self, package_name): super(ModuleInfoDialog, self).__init__() self.moduleinfo_dialogui = Ui_ModuleInfoDialog() self.moduleinfo_dialogui.setupUi(self) self.moduleinfo_dialogui.plainTextEdit.setFrameStyle(QFrame.NoFrame) self.moduleinfo_dialogui.plainTextEdit.setContentsMargins(0, 0, 0, 0) self.moduleinfo_dialogui.plainTextEdit.readOnly = True self.moduleinfo_dialogui.plainTextEdit.clear() rec = recipe.get_recipe(package_name, target='package') pkg = 'Package Name: {}'.format(package_name) self.moduleinfo_dialogui.plainTextEdit.appendPlainText(pkg) self.moduleinfo_dialogui.plainTextEdit.appendPlainText('Dependencies:') for item in rec.depends: depends = '-{}'.format(item) self.moduleinfo_dialogui.plainTextEdit.appendPlainText(depends) self.moduleinfo_dialogui.plainTextEdit.appendPlainText('Source') source = '{}'.format(rec.get_dict()['source']) self.moduleinfo_dialogui.plainTextEdit.appendPlainText(source) self.moduleinfo_dialogui.plainTextEdit.appendPlainText('Category') self.moduleinfo_dialogui.plainTextEdit.appendPlainText(rec.category) if 'description' in rec.get_dict(): self.moduleinfo_dialogui.plainTextEdit.appendPlainText( 'Module Description') self.moduleinfo_dialogui.plainTextEdit.appendPlainText( rec.description) if 'forcebuild' in rec.get_dict(): self.moduleinfo_dialogui.plainTextEdit.appendPlainText( 'Forcebuild') self.moduleinfo_dialogui.plainTextEdit.appendPlainText('True')
def exists(self, name, return_pkgr_name=False): """ Check to see if this package is available on this platform. Returns True or a version string if yes, False if not. If return_pkgr_name is True, it'll return a list of packagers that can install this package. """ if not return_pkgr_name and name in self.pmc.known_installable: self.log.trace("{0} has cached installable-status: {1}".format( name, self.pmc.known_installable.get(name) )) return True self.log.debug("Checking if package {0} is installable...".format(name)) if self.check_package_flag(name, 'forceinstalled'): self.log.debug("Package {0} is forced to state 'installed'.".format(name)) return ['force-installed'] if return_pkgr_name else True r = recipe.get_recipe(name) pkgrs = [] for pkgr in self.get_packagers(name): pkg_version = pkgr.exists(r) if pkg_version is None or not pkg_version: continue else: self.pmc.known_installable[name] = True if return_pkgr_name: pkgrs.append(pkgr.name) else: return pkg_version if return_pkgr_name and len(pkgrs): self.pmc.known_installable[name] = True return pkgrs self.log.debug("Package {0} is not installable.".format(name)) self.pmc.known_installable[name] = False return False
def get_dependees(self, pkgs): """ From a list of pkgs, return a list that also includes packages which depend on them. """ self.log.debug("Resolving dependency list for clean removal.") other_installed_pkgs = [ x for x in self.inventory.get_packages() if not x in pkgs ] new_pkgs = [] for other_installed_pkg in other_installed_pkgs: self.log.obnoxious( "Checking if {0} is a dependee...".format(other_installed_pkg)) try: deps = recipe.get_recipe(other_installed_pkg).depends or [] except PBException: continue for pkg in pkgs: if pkg in deps: self.log.obnoxious("Yup, it is.") new_pkgs.append(other_installed_pkg) break if len(new_pkgs) > 0: pkgs = pkgs + new_pkgs return self.get_dependees(pkgs) return pkgs
def exists(self, name, return_pkgr_name=False): """ Check to see if this package is available on this platform. Returns True or a version string if yes, False if not. If return_pkgr_name is True, it'll return a list of packagers that can install this package. """ if not return_pkgr_name and name in self.pmc.known_installable: self.log.trace("{0} has cached installable-status: {1}".format( name, self.pmc.known_installable.get(name))) return True self.log.debug( "Checking if package {0} is installable...".format(name)) if self.check_package_flag(name, 'forceinstalled'): self.log.debug( "Package {0} is forced to state 'installed'.".format(name)) return ['force-installed'] if return_pkgr_name else True r = recipe.get_recipe(name) pkgrs = [] for pkgr in self.get_packagers(name): pkg_version = pkgr.exists(r) if pkg_version is None or not pkg_version: continue else: self.pmc.known_installable[name] = True if return_pkgr_name: pkgrs.append(pkgr.name) else: return pkg_version if return_pkgr_name and len(pkgrs): self.pmc.known_installable[name] = True return pkgrs self.log.debug("Package {0} is not installable.".format(name)) self.pmc.known_installable[name] = False return False
def installed(self, name, return_pkgr_name=False): """ Check to see if this recipe is installed (identified by its name). If not, return False. If yes, return value depends on return_pkgr_name and is either a list of packager name that installed it, or a version string (if the version string can't be determined, returns True instead). """ if not return_pkgr_name and name in self.pmc.known_installed: self.log.obnoxious("{0} is cached and known to be installed.".format(name)) return True self.log.debug("Checking if package {} is installed.".format(name)) if self.check_package_flag(name, 'forceinstalled'): self.log.debug("Package {} is forced to state 'installed'.".format(name)) # TODO maybe we can figure out a version string return ['force-installed'] if return_pkgr_name else True r = recipe.get_recipe(name) self.current_prefix = self.cfg.get_active_prefix() virtualenv = config_manager.extract_cfg_items(self.current_prefix.cfg_file, 'virtualenv') self.log.debug("Checking if the prefix has a virtualenv") if virtualenv and 'python' in r.depends: try: if 'pip' in r.satisfy: #This pip list is specific to virtualenv pip_output = subproc.check_output(["pip", "list"]) pip_list = [x.split(' ')[0] for x in str(pip_output).strip(). lower().split("\n")] if not name in pip_list: return False except AttributeError: self.log.debug("Package depends on python, but isn't pip installable") pkgrs = [] for pkgr in self.get_packagers(name): pkg_version = pkgr.installed(r) if pkg_version is None or not pkg_version: continue else: self.pmc.known_installed.add(name) if return_pkgr_name: pkgrs.append(pkgr.name) else: return pkg_version else: pkgrs = [] for pkgr in self.get_packagers(name): pkg_version = pkgr.installed(r) if pkg_version is None or not pkg_version: continue else: self.pmc.known_installed.add(name) if return_pkgr_name: pkgrs.append(pkgr.name) else: return pkg_version if return_pkgr_name and len(pkgrs): return pkgrs return False
def _std_package_operation(self, name, operation, pkgrs, verify=False, **kwargs): """ Standard package operation: Try an operation on all packagers. """ rec = recipe.get_recipe(name) for pkgr in pkgrs: self.log.debug("Using packager {0}".format(pkgr.name)) try: result = getattr(pkgr, operation)(rec, **kwargs) if result: if verify and not pkgr.verify(rec): self.log.warn( "Package reported successful {0}, but verification failed." .format(operation)) continue return True except PBException as ex: self.log.error( "Something went wrong while trying to {0} {1} using {2}: {3}" .format(operation, name, pkgr.name, str(ex).strip())) return False
def _add_deps_recursive(self, install_tree, pkg, filter_callback): """ Recursively add dependencies to the install tree. """ # Load deps: deps = recipe.get_recipe(pkg).get_local_package_data()['depends'] or [] # Filter for illegal stuff: for dep in deps: if not self.pm.exists(pkg) and dep is not None: self.log.error("Package does not exist: {0} (declared as dependency for package {1})".format(dep, pkg)) exit(1) # Filter all packages either already in the tree, or not wanted: deps_to_install = filter( lambda pkg: filter_callback(pkg) and pkg not in install_tree.get_nodes(), deps ) if len(deps_to_install) == 0: return # First, add all dependencies into the install tree: install_tree.insert_at(deps_to_install, pkg) # Then, extend the tree if the dependencies have dependencies themselves: for dep in deps_to_install: if isinstance(dep, list): # I honestly have no clue why this happens, yet sometimes # it does. continue self._add_deps_recursive(install_tree, dep, filter_callback)
def exists(self, name, return_pkgr_name=False): """ Check to see if this package is available on this platform. Returns True or a version string if yes, False if not. """ if not return_pkgr_name and name in self.pmc.known_installable: self.log.obnoxious("{0} is cached and known to be installable.".format(name)) return True self.log.debug("Checking if package {} is installable.".format(name)) if self.check_package_flag(name, 'forceinstalled'): self.log.debug("Package {} is forced to state 'installed'.".format(name)) return ['force-installed'] if return_pkgr_name else True r = recipe.get_recipe(name) pkgrs = [] for pkgr in self.get_packagers(name): pkg_version = pkgr.exists(r) if pkg_version is None or not pkg_version: continue else: self.pmc.known_installable.add(name) if return_pkgr_name: pkgrs.append(pkgr.name) else: return pkg_version if return_pkgr_name and len(pkgrs): return pkgrs return False
def installed(self, name, return_pkgr_name=False): """ Check to see if this recipe is installed (identified by its name). If not, return False. If yes, return value depends on return_pkgr_name and is either a list of packager name that installed it, or a version string (if the version string can't be determined, returns True instead). """ self.log.debug("Checking if package {} is installed.".format(name)) if self.check_package_flag(name, 'forceinstalled'): self.log.debug("Package {} is forced to state 'installed'.".format(name)) # TODO maybe we can figure out a version string return ['force-installed'] if return_pkgr_name else True r = recipe.get_recipe(name) pkgrs = [] for pkgr in self.get_packagers(name): pkg_version = pkgr.installed(r) if pkg_version is None or not pkg_version: continue else: if return_pkgr_name: pkgrs.append(pkgr.name) else: return True if return_pkgr_name and len(pkgrs): return pkgrs return False
def graphviz(self, packages, dotfile, pngfile): """ Create the graphviz file """ self.log.info("Creating digraph file {0}".format(dotfile)) f = open(dotfile, "w") f.write("digraph g {\n") for pkg in packages: pkg_safe = pkg.replace("-", "_") f.write('{pkg} [label="{pkg}"]\n'.format(pkg=pkg_safe)) rec = recipe.get_recipe(pkg, fail_easy=True) if rec is None: continue for dep in rec.depends: if dep in packages: f.write(" {pkg} -> {dep}\n".format(pkg=pkg_safe, dep=dep.replace( "-", "_"))) f.write("}\n") f.close() self.log.debug("{0} written".format(dotfile)) if pngfile is None: return self.log.info("Creating png file {0}".format(pngfile)) subproc.monitor_process( ['dot', dotfile, '-Tpng', '-o{0}'.format(pngfile)], env=os.environ, )
def run(self): """ Go, go, go! """ ### Sanity checks for pkg in self.args.packages: if not self.is_installed(pkg): self.log.error("Package {0} is not installed into current prefix. Aborting.".format(pkg)) return -1 ### Make install tree rb_tree = dep_manager.DepManager().make_dep_tree( self.args.packages, lambda x: bool( (x in self.args.packages) or \ (self.args.deps and self.is_installed(x)) ) ) if self.log.getEffectiveLevel() <= 10 or self.args.print_tree: print("Rebuild tree:") rb_tree.pretty_print() ### Recursively rebuild, starting at the leaf nodes node_cache = [] while not rb_tree.empty(): pkg = rb_tree.pop_leaf_node() if pkg in node_cache: continue rec = recipe.get_recipe(pkg) self.log.info("Rebuilding package: {0}".format(pkg)) if not self.pm.rebuild( rec, make_clean=self.args.clean, nuke_builddir=not (self.args.keep_build or bool(self.cfg.get('keep_builddir', False))) ): self.log.error("Error rebuilding package {0}. Aborting.".format(pkg)) return 1 self.log.info("Rebuild successful.")
def exists(self, name, return_pkgr_name=False): """ Check to see if this package is available on this platform. Returns True or a version string if yes, False if not. """ if not return_pkgr_name and name in self.pmc.known_installable: self.log.obnoxious( "{0} is cached and known to be installable.".format(name)) return True self.log.debug( "Checking if package {0} is installable...".format(name)) if self.check_package_flag(name, 'forceinstalled'): self.log.debug( "Package {0} is forced to state 'installed'.".format(name)) return ['force-installed'] if return_pkgr_name else True r = recipe.get_recipe(name) pkgrs = [] for pkgr in self.get_packagers(name): pkg_version = pkgr.exists(r) if pkg_version is None or not pkg_version: continue else: self.pmc.known_installable.add(name) if return_pkgr_name: pkgrs.append(pkgr.name) else: return pkg_version if return_pkgr_name and len(pkgrs): return pkgrs self.log.debug("Package {0} is not installable.".format(name)) return False
def graphviz(self, packages, dotfile, pngfile): """ Create the graphviz file """ self.log.info("Creating digraph file {0}".format(dotfile)) f = open(dotfile, "w") f.write("digraph g {\n") for pkg in packages: pkg_safe = pkg.replace("-", "_") f.write('{pkg} [label="{pkg}"]\n'.format(pkg=pkg_safe)) rec = recipe.get_recipe(pkg, fail_easy=True) if rec is None: continue for dep in rec.depends: if dep in packages: f.write(" {pkg} -> {dep}\n".format( pkg=pkg_safe, dep=dep.replace("-", "_") )) f.write("}\n") f.close() self.log.debug("{0} written".format(dotfile)) if pngfile is None: return self.log.info("Creating png file {0}".format(pngfile)) subproc.monitor_process( ['dot', dotfile, '-Tpng', '-o{0}'.format(pngfile)], env=os.environ, )
def make_tree_recursive(self, pkg, filter_callback): """ Make a dependency tree for one package """ if not filter_callback(pkg): return None tree = TreeNode(pkg) deps = recipe.get_recipe(pkg).get_local_package_data()['depends'] or [] for dep in deps: if dep is not None and not self.pm.exists(pkg): self.log.error( "Package does not exist: {0} (declared as dependency for package {1})".format( dep, pkg ) ) exit(1) deps_to_install = set([ dep for dep in deps \ if dep is not None and filter_callback(dep) and not isinstance(dep, list) \ ]) for dep in deps_to_install: subtree = self.make_tree_recursive(dep, filter_callback) if subtree is not None: tree.add_child(subtree) return tree
def _install_sdk_to_prefix(self, sdkname): """ Read recipe for sdkname, and install the SDK to the prefix. """ from pybombs import recipe src_dir = self.prefix.src_dir cfg_file = self.prefix.cfg_file ### Get the recipe r = recipe.get_recipe(sdkname, target='sdk') try: self.log.trace("Switching CWD to {0}".format(src_dir)) if not op.isdir(src_dir): os.mkdir(src_dir) os.chdir(src_dir) except: self.log.error("Source dir required to install SDK.") return False ### Install the actual SDK file self.log.debug("Fetching SDK `{sdk}'".format(sdk=sdkname)) fetcher.Fetcher().fetch(r) self.log.info("Installing SDK `{sdk}'".format(sdk=sdkname)) # Install command cmd = r.var_replace_all(r.get_command('install')) if subproc.monitor_process(cmd, shell=True, env=os.environ) == 0: self.log.debug("Installation successful") else: self.log.error("Error installing SDK. Aborting.") return False # Clean up files_to_delete = [op.normpath(op.join(src_dir, r.var_replace_all(x))) for x in r.clean] if len(files_to_delete): self.log.info("Cleaning up files...") for ftd in files_to_delete: if op.commonprefix((src_dir, ftd)) != src_dir: self.log.warn("Not removing {ftd} -- outside source dir!".format(ftd=ftd)) continue self.log.debug("Removing {ftd}...".format(ftd=ftd)) if op.isdir(ftd): shutil.rmtree(ftd) elif op.isfile(ftd): os.remove(ftd) else: self.log.error("Not sure what this is: {ftd}".format(ftd=ftd)) return False ### Update the prefix-local config file self.log.debug("Updating config file with SDK recipe info.") try: old_cfg_data = PBConfigFile(cfg_file).get() except IOError: self.log.debug("There doesn't seem to be a config file yet for this prefix.") old_cfg_data = {} # Filter out keys we don't care about: sdk_recipe_keys_for_config = ('config', 'packages', 'categories', 'env') sdk_cfg_data = {k: v for k, v in iteritems(r.get_dict()) if k in sdk_recipe_keys_for_config} self.log.trace("New data: {new}".format(new=sdk_cfg_data)) cfg_data = dict_merge(old_cfg_data, sdk_cfg_data) self.log.debug("Writing updated prefix config to `{0}'".format(cfg_file)) PBConfigFile(cfg_file).save(cfg_data) return True
def check_package_flag(self, pkgname, flag): """ See if package 'pkgname' has 'flag' set (return the boolean value of that flag if yes, or None otherwise). """ return bool( self.cfg.get_package_flags( pkgname, recipe.get_recipe(pkgname).category).get(flag))
def run_list(self): """ Print a list of recipes. """ pkgmgr = PackageManager() recmgr = RecipeListManager() self.log.debug("Loading all package names") all_recipes = recmgr.list_all() if self.args.list is not None: all_recipes = [x for x in all_recipes if re.search(self.args.list, x)] not_installed_string = '-' format_pkg_list = lambda x: [not_installed_string] if not x else x rows = [] row_titles = { 'id': "Package Name", 'path': "Recipe Filename", 'installed_by': "Installed By", 'available_from': "Available From", } self.args.format = [x for x in self.args.format.split(",") if len(x)] if any(map(lambda x: x not in row_titles, self.args.format)): self.log.error("Invalid column formatting: {0}".format(self.args.format)) return -1 print("Loading package information...", end="") sys.stdout.flush() home_dir = os.path.expanduser("~") for pkg in all_recipes: rec = recipe.get_recipe(pkg, target=None, fail_easy=True) if rec is None: print() self.log.warn("Recipe for `{0}' is invalid.".format(pkg)) continue if rec.target != 'package': continue print(".", end="") sys.stdout.flush() row = { 'id': pkg, 'path': recmgr.get_recipe_filename(pkg).replace(home_dir, "~"), 'installed_by': format_pkg_list(pkgmgr.installed(pkg, return_pkgr_name=True)), 'available_from': ",".join(format_pkg_list(pkgmgr.exists(pkg, return_pkgr_name=True))), } if self.args.in_prefix and 'source' not in row['installed_by']: continue if row['installed_by'] == [not_installed_string] and (self.args.installed or self.args.in_prefix): continue row['installed_by'] = ",".join(row['installed_by']) rows.append(row) print("") tables.print_table( row_titles, rows, self.args.format, sort_by=self.args.sort_by, )
def run_list(self): """ Print a list of recipes. """ pkgmgr = PackageManager() recmgr = RecipeListManager() self.log.debug("Loading all package names") all_recipes = recmgr.list_all() if self.args.list is not None: all_recipes = [x for x in all_recipes if re.search(self.args.list, x)] not_installed_string = '-' format_pkg_list = lambda x: [not_installed_string] if not x else x rows = [] row_titles = { 'id': "Package Name", 'path': "Recipe Filename", 'installed_by': "Installed By", 'available_from': "Available From", } self.args.format = [x for x in self.args.format.split(",") if len(x)] if any((x not in row_titles for x in self.args.format)): self.log.error("Invalid column formatting: {0}".format(self.args.format)) return -1 print("Loading package information...", end="") sys.stdout.flush() home_dir = os.path.expanduser("~") for pkg in all_recipes: rec = recipe.get_recipe(pkg, target=None, fail_easy=True) if rec is None: print() self.log.warn("Recipe for `{0}' is invalid.".format(pkg)) continue if rec.target != 'package': continue print(".", end="") sys.stdout.flush() row = { 'id': pkg, 'path': recmgr.get_recipe_filename(pkg).replace(home_dir, "~"), 'installed_by': format_pkg_list(pkgmgr.installed(pkg, return_pkgr_name=True)), 'available_from': ",".join(format_pkg_list(pkgmgr.exists(pkg, return_pkgr_name=True))), } if self.args.in_prefix and 'source' not in row['installed_by']: continue if row['installed_by'] == [not_installed_string] and (self.args.installed or self.args.in_prefix): continue row['installed_by'] = ",".join(row['installed_by']) rows.append(row) print("") tables.print_table( row_titles, rows, self.args.format, sort_by=self.args.sort_by, )
def check_package_flag(self, pkgname, flag): """ See if package 'pkgname' has 'flag' set (return the boolean value of that flag if yes, or None otherwise). """ return bool( self.cfg.get_package_flags( pkgname, recipe.get_recipe(pkgname).category ).get(flag) )
def exists(self, name): """ Check to see if this package is available on this platform. Returns True or a version string if yes, False if not. """ if self.check_package_flag(name, 'forceinstalled'): return True r = recipe.get_recipe(name) for pkgr in self.get_packagers(name): pkg_version = pkgr.exists(r) if pkg_version is None or not pkg_version: continue return pkg_version return False
def make_tree_recursive(self, pkg, filter_callback): """ Make a dependency tree for one package. Assumption is that pkg actually needs to go into the tree, it will not get checked by filter_callback again. """ assert pkg is not None tree = TreeNode(pkg) all_deps = recipe.get_recipe(pkg).depends or [] deps_to_install = set([dep for dep in all_deps if filter_callback(dep)]) for dep in deps_to_install: tree.add_child(self.make_tree_recursive(dep, filter_callback)) return tree
def _write_env_file(self, path): prefix_recipe = recipe.get_recipe('default_prefix', target='prefix', fail_easy=True) #if prefix_recipe is None: #self.log.error("Could not find recipe for `{0}'".format(self.args.recipe)) #return False if not sysutils.dir_is_writable(path): pass try: for fname, content in prefix_recipe.files.items(): sysutils.write_file_in_subdir( path, fname, prefix_recipe.var_replace_all(content)) except: pass return True
def _get_git_remotes(packages): """ Return a dict pkgname -> git remote for every package that has a git remote given. """ the_fetcher = fetcher.Fetcher() recipes = {pkg: recipe.get_recipe(pkg, fail_easy=True) for pkg in packages} sources = {pkg: recipes[pkg].source for pkg in recipes if recipes[pkg] is not None} git_sources = {} for pkg in sources: try: for src in sources[pkg]: url_type, url = the_fetcher.parse_uri(src) if url_type == 'git': git_sources[pkg] = url break except PBException: pass return git_sources
def installed(self, name, return_pkgr_name=False, install_type=None, ignore_pkg_flag=False): """ Check to see if this recipe is installed (identified by its name). If not, return False. If yes, return value depends on return_pkgr_name and is either a list of packager name that installed it, or a version string (if the version string can't be determined, returns True instead). ignore_pkg_flag is passed to get_packagers(). """ install_type = _get_valid_install_type(install_type) if not return_pkgr_name and name in self.pmc.known_installed.get( install_type, {}): self.log.trace("{0} has cached installed-status: {1}".format( name, self.pmc.known_installed.get(install_type, {}).get(name))) return self.pmc.known_installed.get(install_type, {}).get(name) self.log.debug("Checking if package {0} is installed...".format(name)) if self.check_package_flag(name, 'forceinstalled'): self.log.debug( "Package {0} is forced to state 'installed'.".format(name)) # TODO maybe we can figure out a version string return ['force-installed'] if return_pkgr_name else True r = recipe.get_recipe(name) pkgrs = [] for pkgr in self.get_packagers(name, install_type, ignore_pkg_flag): pkg_version = pkgr.installed(r) if pkg_version is None or not pkg_version: continue else: self.pmc.known_installed[install_type][name] = True if return_pkgr_name: pkgrs.append(pkgr.name) else: return pkg_version if return_pkgr_name and len(pkgrs): return pkgrs self.pmc.known_installed[install_type][name] = False self.log.debug("Package {0} is not installed.".format(name)) return False
def make_tree_recursive(self, pkg, filter_callback): """ Make a dependency tree for one package """ if not filter_callback(pkg): return None tree = TreeNode(pkg) deps = recipe.get_recipe(pkg).depends or [] for dep in deps: if not self.pm.exists(pkg): raise PBException( "Package does not exist: {0} (declared as dependency for package {1})" .format(dep, pkg)) deps_to_install = set([dep for dep in deps if filter_callback(dep)]) for dep in deps_to_install: subtree = self.make_tree_recursive(dep, filter_callback) if subtree is not None: tree.add_child(subtree) return tree
def get_dependees(self, pkgs): """ From a list of pkgs, return a list that also includes packages which depend on them. """ self.log.debug("Resolving dependency list for clean removal.") other_installed_pkgs = [x for x in self.inventory.get_packages() if not x in pkgs] new_pkgs = [] for other_installed_pkg in other_installed_pkgs: self.log.obnoxious("Checking if {0} is a dependee...".format(other_installed_pkg)) deps = recipe.get_recipe(other_installed_pkg).get_local_package_data()['depends'] or [] for pkg in pkgs: if pkg in deps: self.log.obnoxious("Yup, it is.") new_pkgs.append(other_installed_pkg) break if len(new_pkgs) > 0: pkgs = pkgs + new_pkgs return self.get_dependees(pkgs) return pkgs
def make_tree_recursive(self, pkg, filter_callback): """ Make a dependency tree for one package """ if not filter_callback(pkg): return None tree = TreeNode(pkg) deps = recipe.get_recipe(pkg).depends or [] for dep in deps: if not self.pm.exists(pkg): raise PBException( "Package does not exist: {0} (declared as dependency for package {1})".format( dep, pkg ) ) deps_to_install = set([dep for dep in deps if filter_callback(dep)]) for dep in deps_to_install: subtree = self.make_tree_recursive(dep, filter_callback) if subtree is not None: tree.add_child(subtree) return tree
def _std_package_operation(self, name, operation, pkgrs, verify=False, **kwargs): """ Standard package operation: Try an operation on all packagers. """ rec = recipe.get_recipe(name) for pkgr in pkgrs: self.log.debug("Using packager {0}".format(pkgr.name)) try: result = getattr(pkgr, operation)(rec, **kwargs) if result: if verify and not pkgr.verify(rec): self.log.warn("Package reported successful {0}, but verification failed.".format(operation)) continue return True except PBException as ex: self.log.error( "Something went wrong while trying to {0} {1} using {2}: {3}".format( operation, name, pkgr.name, str(ex).strip() ) ) return False
def installed(self, name, return_pkgr_name=False, install_type=None, ignore_pkg_flag=False): """ Check to see if this recipe is installed (identified by its name). If not, return False. If yes, return value depends on return_pkgr_name and is either a list of packager name that installed it, or a version string (if the version string can't be determined, returns True instead). ignore_pkg_flag is passed to get_packagers(). """ install_type = _get_valid_install_type(install_type) if not return_pkgr_name and name in self.pmc.known_installed.get(install_type, {}): self.log.trace("{0} has cached installed-status: {1}".format( name, self.pmc.known_installed.get(install_type, {}).get(name) )) return self.pmc.known_installed.get(install_type, {}).get(name) self.log.debug("Checking if package {0} is installed...".format(name)) if self.check_package_flag(name, 'forceinstalled'): self.log.debug("Package {0} is forced to state 'installed'.".format(name)) # TODO maybe we can figure out a version string return ['force-installed'] if return_pkgr_name else True r = recipe.get_recipe(name) pkgrs = [] for pkgr in self.get_packagers(name, install_type, ignore_pkg_flag): pkg_version = pkgr.installed(r) if pkg_version is None or not pkg_version: continue else: self.pmc.known_installed[install_type][name] = True if return_pkgr_name: pkgrs.append(pkgr.name) else: return pkg_version if return_pkgr_name and len(pkgrs): return pkgrs self.pmc.known_installed[install_type][name] = False self.log.debug("Package {0} is not installed.".format(name)) return False
def get_prefix_recipe(recipe_name): " Return the prefix recipe or None " from pybombs import recipe return recipe.get_recipe(recipe_name, target='prefix', fail_easy=True)
def run(self): """This is where we generate our data and provide a signal it to the GUI """ self.indicator.emit("Collecting packages for PyBOMBS") #Init lists required to hold our data app_package_list = [] sdk_package_list = [] app_package_data = [] sdk_package_data = [] base_package_data = [] pm = package_manager.PackageManager() #cfg = config_manager.config_manager #TODO Correctly list out recipes based on the prefix selected list_recipes = sorted(list(recipe_manager.recipe_manager.list_all())) for pkg_name in list_recipes: module = Recipe(recipe_manager.recipe_manager. get_recipe_filename(pkg_name)) if module.target == 'prefix': sdk_package_list.append(pkg_name) elif module.target == 'sdk': sdk_package_list.append(pkg_name) elif module.target == 'package': app_package_list.append(pkg_name) self.indicator.emit("Preparing SDK packages") self.log.info("Preparing SDK packages") for pkg in sdk_package_list: rec = Recipe(recipe_manager.recipe_manager.get_recipe_filename(pkg)) if rec.target == 'prefix': sdk_package_data.append([pkg, 'Prefix Specific Packages']) elif rec.target == 'sdk': sdk_package_data.append([pkg, 'SDK Packages']) self.log.info("Loading SDK packages - successful !") self.indicator.emit("Preparing application and baseline packages") self.log.info("Preparing application and baseline packages") for oot_module in app_package_list: rec = recipe.get_recipe(oot_module, target='package', fail_easy=True) if rec.category == 'baseline': if pm.installed(oot_module): base_package_data.append([oot_module, 'Installed']) else: base_package_data.append([oot_module, 'Not Installed']) else: if 'description' in rec.get_dict(): if pm.installed(oot_module): app_package_data.append([oot_module, rec.get_dict()['category'], 'Installed', rec.get_dict()['description']]) else: app_package_data.append([oot_module, rec.get_dict()['category'], 'Not Installed', rec.get_dict()['description']]) else: if pm.installed(oot_module): app_package_data.append([oot_module, rec.get_dict()['category'], 'Installed', 'No description available']) else: app_package_data.append([oot_module, rec.get_dict()['category'], 'Not Installed', 'No description available']) self.data_generator.emit(app_package_data, base_package_data, sdk_package_data) self.log.info("Loading application and baseline packages - Successful !") self.data_done.emit("Data successfully loaded") return
def _list_recipes(self): """ Print a list of recipes. """ pkgmgr = PackageManager() recmgr = RecipeListManager() self.log.debug("Loading all package names") all_recipes = recmgr.list_all() if self.args.list is not None: all_recipes = [ x for x in all_recipes if re.search(self.args.list, x) ] not_installed_string = '-' format_installed_by = lambda x: [not_installed_string] if not x else x rows = [] row_titles = { 'id': "Package Name", 'path': "Recipe Filename", 'installed_by': "Installed By", } self.args.format = [x for x in self.args.format.split(",") if len(x)] if any(map(lambda x: x not in row_titles, self.args.format)): self.log.error("Invalid column formatting: {0}".format( self.args.format)) return -1 widths = {k: len(row_titles[k]) for k in row_titles.keys()} print("Loading package information...", end="") sys.stdout.flush() home_dir = os.path.expanduser("~") for pkg in all_recipes: if recipe.get_recipe(pkg, target=None).target != 'package': continue print(".", end="") sys.stdout.flush() row = { 'id': pkg, 'path': recmgr.get_recipe_filename(pkg).replace(home_dir, "~"), 'installed_by': format_installed_by( pkgmgr.installed(pkg, return_pkgr_name=True)), } if self.args.in_prefix and 'source' not in row['installed_by']: continue if row['installed_by'] == [ not_installed_string ] and (self.args.installed or self.args.in_prefix): continue row['installed_by'] = ",".join(row['installed_by']) widths = {k: max(widths[k], len(row[k])) for k in row.iterkeys()} rows.append(row) print("\n") # Sort rows if self.args.sort_by is not None and self.args.sort_by in row_titles.keys( ): rows = sorted(rows, key=lambda k: k[self.args.sort_by]) # Print Header hdr_len = 0 for col_id in self.args.format: format_string = "{0:" + str(widths[col_id]) + "} " hdr_title = format_string.format(row_titles[col_id]) print(hdr_title, end="") hdr_len += len(hdr_title) print("") print("-" * hdr_len) # Print Table for row in rows: for col_id in self.args.format: format_string = "{{0:{width}}} ".format(width=widths[col_id]) print(format_string.format(row[col_id]), end="") print("") print("")
def prefix_init(self): """ pybombs prefix init """ prefix_path = str(self.prefixconfig_dialogui.lineEdit_2.text()) alias = str(self.prefixconfig_dialogui.lineEdit.text()) if not self.check_alias(alias): return False else: prefix_alias = alias print(prefix_alias, prefix_path) self.prefixconfig_dialogui.lineEdit.clear() self.prefixconfig_dialogui.lineEdit_2.clear() # Check alias and prefix dir validity prefix_recipe = recipe.get_recipe('default_prefix', target='prefix', fail_easy=True) # Make sure the directory is writable path = os.path.abspath(os.path.normpath(prefix_path)) if not sysutils.mkdir_writable(path): dir_msg = "Choose a prefix directory with write access" self.color_strips(dir_msg, 'red') return False # Make sure that a pybombs directory doesn't already exist if os.path.exists(os.path.join(path, config_manager.PrefixInfo.prefix_conf_dir)): dir_exists = "Prefix directory already exists. Choose a new one" self.color_strips(dir_exists, 'red') return False # Add subdirs sysutils.require_subdirs(path, [k for k, v in prefix_recipe.dirs.items() if v]) self.cfg.load(select_prefix=path) self.prefix = self.cfg.get_active_prefix() # Create files for fname, content in prefix_recipe.files.items(): sysutils.write_file_in_subdir(path, fname, prefix_recipe.var_replace_all(content)) # If there is no default prefix, make this the default if len(self.cfg.get('default_prefix')) == 0: if prefix_alias is not None: new_default_prefix = prefix_alias else: new_default_prefix = prefix_path self.cfg.update_cfg_file({'config': {'default_prefix': new_default_prefix}}) # Create virtualenv if so desired if self.prefixconfig_dialogui.checkBox.isChecked(): #self.log.info("Creating Python virtualenv in prefix...") venv_args = ['virtualenv'] venv_args.append(path) subproc.monitor_process(args=venv_args) # Update config section if len(prefix_recipe.config): if self.prefixconfig_dialogui.checkBox.isChecked(): prefix_recipe.config = dict_merge( {'virtualenv': True}, prefix_recipe.config) self.cfg.update_cfg_file(prefix_recipe.config, self.prefix.cfg_file) else: prefix_recipe.config = dict_merge( {'virtualenv': False}, prefix_recipe.config) self.cfg.update_cfg_file(prefix_recipe.config, self.prefix.cfg_file) self.cfg.load(select_prefix=prefix_path) self.prefix = self.cfg.get_active_prefix() self.cfg.update_cfg_file({'prefix_aliases':{prefix_alias: prefix_path}}, self.cfg.local_cfg) success_msg = 'Successfully created prefix in {}'.format(prefix_path) self.color_strips(success_msg, 'blue') self.close() return True
def _std_package_operation(self, name, operation, pkgrs, verify=False, **kwargs): """ Standard package operation: Try an operation on all packagers. """ rec = recipe.get_recipe(name) virtualenv = config_manager.extract_cfg_items(self.current_prefix.cfg_file, 'virtualenv') #If the following condition is satisfied, pybombs uses pip explicity #to install those packages specific to the virtualenv if virtualenv and 'python' in rec.depends: try: if 'pip' in rec.satisfy: pkgr = pkgrs[0] self.log.debug("Using packager {}".format(pkgr.name)) try: result = getattr(pkgr, operation)(rec, **kwargs) if result: if verify and not pkgr.verify(rec): self.log.warn("Package reported successful {0},' \ 'but verification failed.".format(operation)) return True except PBException as ex: self.log.error( "Something went wrong while trying to {} {} using {}: {}".format( operation, name, pkgr.name, str(ex).strip())) except: for pkgr in pkgrs: self.log.debug("Using packager {}".format(pkgr.name)) try: result = getattr(pkgr, operation)(rec, **kwargs) if result: if verify and not pkgr.verify(rec): self.log.warn("Package reported successful {0},' \ 'but verification failed.".format(operation)) continue return True except PBException as ex: self.log.error( "Something went wrong while trying to {} {} using {}: {}".format( operation, name, pkgr.name, str(ex).strip())) #This works exactly like the above piece of code, but with all the #available packagers else: for pkgr in pkgrs: self.log.debug("Using packager {}".format(pkgr.name)) try: result = getattr(pkgr, operation)(rec, **kwargs) if result: if verify and not pkgr.verify(rec): self.log.warn("Package reported successful {0},' \ 'but verification failed.".format(operation)) continue return True except PBException as ex: self.log.error( "Something went wrong while trying to {} {} using {}: {}".format( operation, name, pkgr.name, str(ex).strip())) return False
def _list_recipes(self): """ Print a list of recipes. """ pkgmgr = PackageManager() recmgr = RecipeListManager() self.log.debug("Loading all package names") all_recipes = recmgr.list_all() if self.args.list is not None: all_recipes = [x for x in all_recipes if re.search(self.args.list, x)] not_installed_string = '-' format_installed_by = lambda x: [not_installed_string] if not x else x rows = [] row_titles = { 'id': "Package Name", 'path': "Recipe Filename", 'installed_by': "Installed By", } self.args.format = [x for x in self.args.format.split(",") if len(x)] if any(map(lambda x: x not in row_titles, self.args.format)): self.log.error("Invalid column formatting: {0}".format(self.args.format)) return -1 widths = {k: len(row_titles[k]) for k in row_titles.keys()} print("Loading package information...", end="") sys.stdout.flush() home_dir = os.path.expanduser("~") for pkg in all_recipes: if recipe.get_recipe(pkg, target=None).target != 'package': continue print(".", end="") sys.stdout.flush() row = { 'id': pkg, 'path': recmgr.get_recipe_filename(pkg).replace(home_dir, "~"), 'installed_by': format_installed_by(pkgmgr.installed(pkg, return_pkgr_name=True)), } if self.args.in_prefix and 'source' not in row['installed_by']: continue if row['installed_by'] == [not_installed_string] and (self.args.installed or self.args.in_prefix): continue row['installed_by'] = ",".join(row['installed_by']) widths = {k: max(widths[k], len(row[k])) for k in row.iterkeys()} rows.append(row) print("\n") # Sort rows if self.args.sort_by is not None and self.args.sort_by in row_titles.keys(): rows = sorted(rows, key=lambda k: k[self.args.sort_by]) # Print Header hdr_len = 0 for col_id in self.args.format: format_string = "{0:" + str(widths[col_id]) + "} " hdr_title = format_string.format(row_titles[col_id]) print(hdr_title, end="") hdr_len += len(hdr_title) print("") print("-" * hdr_len) # Print Table for row in rows: for col_id in self.args.format: format_string = "{{0:{width}}} ".format(width=widths[col_id]) print(format_string.format(row[col_id]), end="") print("") print("")