def _updates(self, entropy_client): """ Solo Query Updates command. """ quiet = self._nsargs.quiet verbose = self._nsargs.verbose if not quiet: entropy_client.output(brown(_("Available Updates")), header=darkred(" @@ ")) outcome = entropy_client.calculate_updates(quiet=True) update, remove = outcome["update"], outcome["remove"] fine, critical_f = outcome["fine"], outcome["critical_found"] if quiet: entropy_client.output("%d" % (len(update),), level="generic") return 0 toc = [] toc.append((darkgreen(_("Packages to update:")), bold(const_convert_to_unicode(len(update))))) toc.append((darkred(_("Packages to remove:")), bold(const_convert_to_unicode(len(remove))))) if verbose: toc.append((blue(_("Packages already up-to-date:")), bold(const_convert_to_unicode(len(fine))))) toc.append((purple(_("Critical updates found:")), teal(const_convert_to_unicode(str(critical_f))))) print_table(entropy_client, toc) return 0
def _selfile(self, entropy_client): entropy_client.output( darkred( _("Please choose a file to update by typing " "its identification number."))) entropy_client.output(darkred(_("Other options are:"))) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("-1")), darkgreen(_("Exit")), )) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("-3")), brown(_("Automerge all the files asking you one by one")), )) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("-5")), darkred(_("Automerge all the files without questioning")), )) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("-7")), brown(_("Discard all the files asking you one by one")), )) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("-9")), darkred(_("Discard all the files without questioning")), )) # wait user interaction try: action = readtext( _("Your choice (type a number and press enter):") + " ") except EOFError: action = None return action
def _advise_packages_update(self, entropy_client): """ Warn user about critical package updates, if any. """ client_settings = entropy_client.ClientSettings() misc_settings = client_settings['misc'] splitdebug = misc_settings['splitdebug'] forced_updates = misc_settings.get('forcedupdates') if forced_updates: crit_atoms, crit_matches = \ entropy_client.calculate_critical_updates() if crit_atoms: entropy_client.output("") entropy_client.output("") update_msg = _("Please update the following " "critical packages") entropy_client.output("%s:" % (purple(update_msg),), level="warning") for name in sorted(crit_atoms): entropy_client.output( brown(name), header=darkred(" # "), level="warning") entropy_client.output( darkgreen(_("You should install them as " "soon as possible")), header=darkred(" !!! "), level="warning") entropy_client.output("") entropy_client.output("")
def _edit_file(self, idx, entropy_client, root, source, dest, paths_map, scandata): """ Edit the given source file. """ source_path = root + source dest_path = root + dest entropy_client.output("%s: %s" % ( darkred(_("Editing file")), darkgreen(source_path), )) entropy_client.edit_file(source_path) entropy_client.output( "%s: %s, %s" % (darkred(_("Edited file")), darkgreen(source_path), darkred(_("showing difference")))) diff = self._showdiff(entropy_client, dest_path, source_path) if not diff: entropy_client.output("%s: %s" % ( darkred(_("Automerging")), teal(source_path), )) scandata.merge(source) del paths_map[idx] return True, False return False, True
def _restore(self, entropy_client, inst_repo): """ Solo Smart Restore command. """ path = entropy_client.installed_repository_path() repo_list = entropy_client.installed_repository_backups() if not repo_list: entropy_client.output(darkred(_("No backups found")), header=brown(" @@ "), level="warning", importance=1) return 1 repo_list_new = [] repo_data = [] for repo_path in repo_list: try: ts = os.path.getmtime(repo_path) except OSError as err: entropy.tools.print_traceback() continue h_ts = entropy.tools.convert_unix_time_to_human_time(ts) repo_list_new.append("[%s] %s" % ( h_ts, repo_path, )) repo_data.append(repo_path) def fake_cb(s): return s input_params = [('db', ( 'combo', (_('Select the repository to restore'), repo_list_new), ), fake_cb, True)] while True: data = entropy_client.input_box(darkred( _("Entropy Installed Packages Repository backups")), input_params, cancel_button=True) if data is None: return 1 myid, dbx = data['db'] try: backup_path = repo_data.pop(myid - 1) except IndexError: continue if not os.path.isfile(backup_path): continue break inst_repo.commit() status, err_msg = entropy_client.restore_repository( backup_path, path, inst_repo.repository_id()) if status: return 0 return 1
def _description(self, entropy_client, inst_repo): """ Solo Query Description command. """ quiet = self._nsargs.quiet verbose = self._nsargs.verbose descriptions = self._nsargs.descriptions settings = entropy_client.Settings() found = False if not quiet: entropy_client.output(darkgreen(_("Description Search")), header=darkred(" @@ ")) repo_number = 0 for repo_id in entropy_client.repositories(): repo_number += 1 repo_data = settings["repositories"]["available"][repo_id] if not quiet: header = ( const_convert_to_unicode(" #") + const_convert_to_unicode(repo_number) + const_convert_to_unicode(" ") ) entropy_client.output("%s" % (bold(repo_data["description"]),), header=blue(header)) repo = entropy_client.open_repository(repo_id) found = self._search_descriptions(descriptions, entropy_client, repo, quiet, verbose) if not quiet and not found: entropy_client.output(darkgreen("%s." % (_("No matches"),)), header=darkred(" @@ ")) return 0
def _read_lic_selection(): entropy_client.output( darkred(_("Please select an option")), header=" ") entropy_client.output( "(%d) %s" % ( 1, darkgreen(_("Read the license"))), header=" ") entropy_client.output( "(%d) %s" % ( 2, brown(_("Accept the license (I've read it)"))), header=" ") entropy_client.output( "(%d) %s" % ( 3, darkred(_("Accept the license and don't " "ask anymore (I've read it)"))), header=" ") entropy_client.output( "(%d) %s" % (0, bold(_("Quit"))), header=" ") # wait user interaction try: action = readtext( " %s: " % ( _("Your choice (type a number and press enter)"),) ) except EOFError: action = None return action
def _advise_packages_update(self, entropy_client): """ Warn user about critical package updates, if any. """ client_settings = entropy_client.ClientSettings() misc_settings = client_settings['misc'] splitdebug = misc_settings['splitdebug'] forced_updates = misc_settings.get('forcedupdates') if forced_updates: crit_atoms, crit_matches = \ entropy_client.calculate_critical_updates() if crit_atoms: entropy_client.output("") entropy_client.output("") update_msg = _("Please update the following " "critical packages") entropy_client.output("%s:" % (purple(update_msg), ), level="warning") for name in sorted(crit_atoms): entropy_client.output(brown(name), header=darkred(" # "), level="warning") entropy_client.output(darkgreen( _("You should install them as " "soon as possible")), header=darkred(" !!! "), level="warning") entropy_client.output("") entropy_client.output("")
def _edit_file(self, idx, entropy_client, root, source, dest, paths_map, scandata): """ Edit the given source file. """ source_path = root + source dest_path = root + dest entropy_client.output( "%s: %s" % ( darkred(_("Editing file")), darkgreen(source_path),)) entropy_client.edit_file(source_path) entropy_client.output( "%s: %s, %s" % ( darkred(_("Edited file")), darkgreen(source_path), darkred(_("showing difference"))) ) diff = self._showdiff( entropy_client, dest_path, source_path) if not diff: entropy_client.output( "%s: %s" % ( darkred(_("Automerging")), teal(source_path),) ) scandata.merge(source) del paths_map[idx] return True, False return False, True
def _needed(self, entropy_client, inst_repo): """ Solo Query Needed command. """ quiet = self._nsargs.quiet verbose = self._nsargs.verbose packages = self._nsargs.packages if not quiet: entropy_client.output(darkgreen(_("Needed Libraries Search")), header=darkred(" @@ ")) for package in packages: pkg_id, pkg_rc = inst_repo.atomMatch(package) if pkg_id == -1: continue atom = inst_repo.retrieveAtom(pkg_id) neededs = inst_repo.retrieveNeededLibraries(pkg_id) for usr_path, usr_soname, soname, elfclass, rpath in neededs: out_str = "%s:%s" % (soname, elfclass) if verbose: out_str = "%s:%s:%s:%s:%s" % (usr_path, usr_soname, soname, elfclass, rpath) if quiet: entropy_client.output(out_str, level="generic") else: entropy_client.output(darkred(const_convert_to_unicode(out_str)), header=blue(" # ")) if not quiet: toc = [] toc.append(("%s:" % (blue(_("Package")),), purple(atom))) toc.append(("%s:" % (blue(_("Found")),), "%s %s" % (len(neededs), brown(_("libraries"))))) print_table(entropy_client, toc) return 0
def _read_lic_selection(): entropy_client.output(darkred(_("Please select an option")), header=" ") entropy_client.output("(%d) %s" % (1, darkgreen(_("Read the license"))), header=" ") entropy_client.output( "(%d) %s" % (2, brown(_("Accept the license (I've read it)"))), header=" ") entropy_client.output("(%d) %s" % (3, darkred( _("Accept the license and don't " "ask anymore (I've read it)"))), header=" ") entropy_client.output("(%d) %s" % (0, bold(_("Quit"))), header=" ") # wait user interaction try: action = readtext( " %s: " % (_("Your choice (type a number and press enter)"), )) except EOFError: action = None return action
def show_successful_download(down_list, data_transfer): for _pkg_id, repository_id, fname, _cksum, _signatures in down_list: best_mirror = get_best_mirror(repository_id) mirrorcount = repo_uris[repository_id].index(best_mirror) + 1 basef = os.path.basename(fname) txt = "( mirror #%s ) [%s] %s %s %s" % ( mirrorcount, brown(basef), darkred(_("success")), blue("@"), red(self._get_url_name(best_mirror)), ) self._entropy.output( txt, importance = 1, level = "info", header = red(" ## ") ) if data_transfer: txt = " %s: %s%s%s" % ( blue(_("Aggregated transfer rate")), bold(entropy.tools.bytes_into_human(data_transfer)), darkred("/"), darkblue(_("second")), ) self._entropy.output( txt, importance = 1, level = "info", header = red(" ## ") )
def __pull_repo(self, entropy_server, repository_id): sts = self.__sync_repo(entropy_server, repository_id) if sts != 0: entropy_server.output(red(_("Aborting !")), importance=1, level="error", header=darkred(" !!! ")) return sts mirrors_tainted, mirrors_errors, successfull_mirrors, \ broken_mirrors, check_data = \ entropy_server.Mirrors.sync_packages( repository_id, ask = self._ask, pretend = self._pretend) if mirrors_errors and not successfull_mirrors: entropy_server.output(red(_("Aborting !")), importance=1, level="error", header=darkred(" !!! ")) return 1 if not successfull_mirrors: return 0 if self._ask: q_rc = entropy_server.ask_question( _("Should I cleanup old packages on mirrors ?")) if q_rc == _("No"): return 0 # fall through done = entropy_server.Mirrors.tidy_mirrors( repository_id, ask = self._ask, pretend = self._pretend) if not done: return 1 return 0
def _execute_package_phase(self, action_metadata, package_metadata, action_name, phase_name): """ Wrapper against Source Package Manager's execute_package_phase. This method handles both fatal and non-fatal exceptions. """ self._entropy.output( "%s: %s" % (brown(_("Package phase")), teal(phase_name),), importance = 0, header = red(" ## ")) spm = self._spm try: spm.execute_package_phase( action_metadata, package_metadata, action_name, phase_name) except spm.PhaseFailure as err: txt = "%s: %s %s, %s. %s." % ( bold(_("QA")), brown(_("Cannot run phase")), bold(phase_name), err.message, brown(_("Please report it")), ) self._entropy.output( txt, importance = 1, header = red(" ## "), level = "warning") return 0 # non-fatal except spm.OutdatedPhaseError as err: err_msg = "%s: %s" % ( brown(_("Source Package Manager is too old, " "please update it")), err) self._entropy.output( err_msg, importance = 1, header = darkred(" ## "), level = "error" ) return 1 except spm.PhaseError as err: err_msg = "%s: %s" % ( brown(_("Source Package Manager phase error")), err) self._entropy.output( err_msg, importance = 1, header = darkred(" ## "), level = "error" ) return 1 return 0
def _status(self, entropy_server): """ Actual Eit lock|unlock --status code. Just show repo status. """ repositories = entropy_server.repositories() if self._repository_id not in repositories: entropy_server.output( "%s: %s" % ( _("Invalid Repository"), self._repository_id), level="error", importance=1) return 1 if not self._quiet: entropy_server.output( "%s:" % (darkgreen(_("Mirrors status")),), header=brown(" * ")) dbstatus = entropy_server.Mirrors.mirrors_status( self._repository_id) for uri, server_lock, client_lock in dbstatus: host = EntropyTransceiver.get_uri_name(uri) if not self._quiet: entropy_server.output( "[%s]" % (purple(host),), header=darkgreen(" @@ ")) if server_lock: lock_str = darkred(_("Locked")) quiet_lock_str = "locked" else: lock_str = darkgreen(_("Unlocked")) quiet_lock_str = "unlocked" if self._quiet: entropy_server.output( "%s server %s" % (host, quiet_lock_str), level="generic") else: entropy_server.output( "%s: %s" % (blue(_("server")), lock_str), header=brown(" # ")) if client_lock: lock_str = darkred(_("Locked")) quiet_lock_str = "locked" else: lock_str = darkgreen(_("Unlocked")) quiet_lock_str = "unlocked" if self._quiet: entropy_server.output( "%s client %s" % (host, quiet_lock_str), level="generic") else: entropy_server.output( "%s: %s" % (blue(_("client")), lock_str), header=brown(" # ")) return 0
def _restore(self, entropy_client): """ Solo Smart Restore command. """ inst_repo = entropy_client.installed_repository() path = entropy_client.installed_repository_path() repo_list = entropy_client.installed_repository_backups() if not repo_list: entropy_client.output( darkred(_("No backups found")), header=brown(" @@ "), level="warning", importance=1) return 1 repo_list_new = [] repo_data = [] for repo_path in repo_list: try: ts = os.path.getmtime(repo_path) except OSError as err: entropy.tools.print_traceback() continue h_ts = entropy.tools.convert_unix_time_to_human_time(ts) repo_list_new.append("[%s] %s" % (h_ts, repo_path,)) repo_data.append(repo_path) def fake_cb(s): return s input_params = [ ('db', ('combo', (_('Select the repository to restore'), repo_list_new),), fake_cb, True) ] while True: data = entropy_client.input_box( darkred( _("Entropy Installed Packages Repository backups")), input_params, cancel_button = True) if data is None: return 1 myid, dbx = data['db'] try: backup_path = repo_data.pop(myid-1) except IndexError: continue if not os.path.isfile(backup_path): continue break inst_repo.commit() status, err_msg = entropy_client.restore_repository( backup_path, path, inst_repo.repository_id()) if status: return 0 return 1
def _fetch_phase(self): """ Execute the fetch phase. """ m_fetch_len = len(self._meta['multi_fetch_list']) / 2 xterm_title = "%s: %s %s" % ( _("Downloading"), m_fetch_len, ngettext("package", "packages", m_fetch_len), ) self._entropy.set_title(xterm_title) m_fetch_len = len(self._meta['multi_fetch_list']) txt = "%s: %s %s" % ( blue(_("Downloading")), darkred("%s" % (m_fetch_len, )), ngettext("package", "packages", m_fetch_len), ) self._entropy.output(txt, importance=1, level="info", header=red(" ## ")) exit_st, err_list = self._download_packages( self._meta['multi_fetch_list']) if exit_st == 0: return 0 txt = _("Some packages cannot be fetched") txt2 = _("Try to update your repositories and retry") for txt in ( txt, txt2, ): self._entropy.output("%s." % (darkred(txt), ), importance=0, level="info", header=red(" ## ")) self._entropy.output("%s: %s" % ( brown(_("Error")), exit_st, ), importance=0, level="info", header=red(" ## ")) for _pkg_id, repo, fname, cksum, _signatures in err_list: self._entropy.output("[%s|%s] %s" % ( blue(repo), darkgreen(cksum), darkred(fname), ), importance=1, level="error", header=darkred(" # ")) return exit_st
def _install(self, entropy_client): """ Solo Security Install command. """ quiet = self._nsargs.quiet pretend = self._nsargs.pretend ask = self._nsargs.ask fetch = self._nsargs.fetch sec = entropy_client.Security() entropy_client.output("%s..." % (blue(_("Calculating security updates")), ), header=darkred(" @@ ")) inst_repo = entropy_client.installed_repository() with inst_repo.shared(): affected_deps = set() for advisory_id in sec.list(): affected_deps.update(sec.affected_id(advisory_id)) valid_matches = set() for atom in affected_deps: inst_package_id, pkg_rc = inst_repo.atomMatch(atom) if pkg_rc != 0: continue key_slot = inst_repo.retrieveKeySlotAggregated(inst_package_id) package_id, repository_id = entropy_client.atom_match(key_slot) if package_id != -1: valid_matches.add((package_id, repository_id)) if not valid_matches: entropy_client.output("%s." % (blue( _("All the available updates " "have been already installed")), ), header=darkred(" @@ ")) return 0 exit_st, _show_cfgupd = self._install_action( entropy_client, True, True, pretend, ask, False, quiet, False, False, False, fetch, False, False, False, 1, [], package_matches=list(valid_matches)) return exit_st
def _list(self, entropy_client): """ Solo Security List command. """ affected = self._nsargs.affected unaffected = self._nsargs.unaffected sec = entropy_client.Security() if not (affected or unaffected): advisory_ids = sec.list() elif affected: advisory_ids = sec.vulnerabilities() else: advisory_ids = sec.fixed_vulnerabilities() if not advisory_ids: entropy_client.output( "%s." % ( darkgreen(_("No advisories available or applicable")), ), header=brown(" :: ")) return 0 for advisory_id in sorted(advisory_ids): affected_deps = sec.affected_id(advisory_id) if affected and not affected_deps: continue if unaffected and affected_deps: continue if affected_deps: affection_string = darkred("A") else: affection_string = darkgreen("N") advisory = sec.advisory(advisory_id) if advisory is None: continue affected_data = advisory['affected'] if not affected_data: continue for a_key in list(affected_data.keys()): k_data = advisory['affected'][a_key] vulnerables = ', '.join(k_data[0]['vul_vers']) description = "[Id:%s:%s][%s] %s: %s" % ( darkgreen(advisory_id), affection_string, brown(vulnerables), darkred(a_key), blue(advisory['title'])) entropy_client.output(description) return 0
def _list(self, entropy_client, inst_repo): """ Solo PreservedLibs List command. """ quiet = self._nsargs.quiet verbose = self._nsargs.verbose preserved_mgr = preservedlibs.PreservedLibraries( inst_repo, None, frozenset(), root=etpConst['systemroot']) preserved = preserved_mgr.list() if not preserved: if not quiet: entropy_client.output( darkgreen(_("No preserved libraries found")), header=darkred(" @@ ")) return 0 for library, elfclass, path, atom in preserved: if quiet: entropy_client.output(path, level="generic") continue needed_by_str = const_convert_to_unicode("") if verbose: needed_by_str += ", %s:" % ( darkgreen(_("needed by")), ) entropy_client.output( "%s [%s:%s -> %s]%s" % ( darkred(path), purple(library), teal(const_convert_to_unicode(elfclass)), enlightenatom(atom), needed_by_str, )) if verbose: package_ids = inst_repo.searchNeeded( library, elfclass=elfclass) for package_id in package_ids: atom = inst_repo.retrieveAtom(package_id) if atom is None: continue entropy_client.output( "%s" % (enlightenatom(atom),), header=brown(" -> "), importance=0) return 0
def _changelog(self, entropy_client, inst_repo): """ Solo Query Changelog command. """ quiet = self._nsargs.quiet verbose = self._nsargs.verbose packages = self._nsargs.packages if not quiet: entropy_client.output(darkgreen(_("ChangeLog Search")), header=darkred(" @@ ")) for package in packages: repo = inst_repo if inst_repo is not None: pkg_id, rc = inst_repo.atomMatch(package) if rc != 0: entropy_client.output("%s: %s" % (darkred(_("No match for")), bold(package))) continue else: pkg_id, r_id = entropy_client.atom_match(package) if pkg_id == -1: entropy_client.output("%s: %s" % (darkred(_("No match for")), bold(package))) continue repo = entropy_client.open_repository(r_id) repo_atom = repo.retrieveAtom(pkg_id) if repo_atom is None: continue if quiet: entropy_client.output("%s :" % (repo_atom,), level="generic") else: entropy_client.output("%s: %s" % (blue(_("Package")), bold(repo_atom)), header=" ") changelog = repo.retrieveChangelog(pkg_id) if not changelog or (changelog == "None"): # == "None" is a bug, see: # 685b865453d552d37ce3a9559f4cefb9a88f8beb entropy_client.output(_("No ChangeLog available"), level="generic") else: entropy_client.output(changelog, level="generic") entropy_client.output("=" * 80) if not quiet: # check developer repo mode repo_conf = entropy_client.Settings().get_setting_files_data()["repositories"] dev_repo = entropy_client.Settings()["repositories"]["developer_repo"] if not dev_repo: entropy_client.output( "%s ! [%s]" % (brown(_("Attention: developer-repo " "option not enabled")), blue(repo_conf)), level=bold(" !!! "), ) return 0
def _search_mimetype(self, entropy_client, inst_repo, associate=False): """ Solo Query Mimetype command. """ installed = self._nsargs.installed quiet = self._nsargs.quiet verbose = self._nsargs.verbose settings = entropy_client.Settings() inst_repo_id = inst_repo.repository_id() if associate: mimetypes = self._nsargs.files else: mimetypes = self._nsargs.mimes if not quiet: entropy_client.output(darkgreen(_("Searching Mimetype")), header=darkred(" @@ ")) found = False for mimetype in mimetypes: if associate: # consider mimetype a file path mimetype = get_file_mime(mimetype) if mimetype is None: continue if not quiet: entropy_client.output(bold(mimetype), header=blue(" # ")) if installed: matches = [(x, inst_repo_id) for x in entropy_client.search_installed_mimetype(mimetype)] else: matches = entropy_client.search_available_mimetype(mimetype) if matches: found = True key_sorter = lambda x: entropy_client.open_repository(x[1]).retrieveAtom(x[0]) for pkg_id, pkg_repo in sorted(matches, key=key_sorter): repo = entropy_client.open_repository(pkg_repo) print_package_info(pkg_id, entropy_client, repo, extended=verbose, quiet=quiet) if not quiet: entry_str = ngettext("entry", "entries", len(matches)) toc = [] toc.append(("%s:" % (blue(_("Keyword")),), purple(mimetype))) toc.append(("%s:" % (blue(_("Found")),), "%s %s" % (len(matches), brown(entry_str)))) print_table(entropy_client, toc) if not quiet and not found: entropy_client.output(darkgreen("%s." % (_("No matches"),)), header=darkred(" @@ ")) return 0
def _execute_package_phase(self, action_metadata, package_metadata, action_name, phase_name): """ Wrapper against Source Package Manager's execute_package_phase. This method handles both fatal and non-fatal exceptions. """ self._entropy.output("%s: %s" % ( brown(_("Package phase")), teal(phase_name), ), importance=0, header=red(" ## ")) spm = self._spm try: spm.execute_package_phase(action_metadata, package_metadata, action_name, phase_name) except spm.PhaseFailure as err: txt = "%s: %s %s, %s. %s." % ( bold(_("QA")), brown(_("Cannot run phase")), bold(phase_name), err.message, brown(_("Please report it")), ) self._entropy.output(txt, importance=1, header=red(" ## "), level="warning") return 0 # non-fatal except spm.OutdatedPhaseError as err: err_msg = "%s: %s" % (brown( _("Source Package Manager is too old, " "please update it")), err) self._entropy.output(err_msg, importance=1, header=darkred(" ## "), level="error") return 1 except spm.PhaseError as err: err_msg = "%s: %s" % (brown( _("Source Package Manager phase error")), err) self._entropy.output(err_msg, importance=1, header=darkred(" ## "), level="error") return 1 return 0
def _execute_action(cls, entropy_client, inst_repo, removal_queue, remove_config_files): """ Execute the actual packages removal activity. """ final_queue = collections.deque() with inst_repo.shared(): for package_id in removal_queue: if not inst_repo.isPackageIdAvailable(package_id): continue atom = inst_repo.retrieveAtom(package_id) if atom is None: continue final_queue.append((atom, package_id)) action_factory = entropy_client.PackageActionFactory() for count, (atom, package_id) in enumerate(final_queue, 1): metaopts = {} metaopts['removeconfig'] = remove_config_files pkg = None try: pkg = action_factory.get( action_factory.REMOVE_ACTION, (package_id, inst_repo.repository_id()), opts=metaopts) xterm_header = "equo (%s) :: %d of %d ::" % ( _("removal"), count, len(final_queue)) pkg.set_xterm_header(xterm_header) entropy_client.output( darkgreen(atom), count=(count, len(final_queue)), header=darkred(" --- ") + ">>> ") exit_st = pkg.start() if exit_st != 0: return 1 finally: if pkg is not None: pkg.finalize() entropy_client.output( "%s." % (blue(_("All done")),), header=darkred(" @@ ")) return 0
def _list(self, entropy_client, inst_repo): """ Solo PreservedLibs List command. """ quiet = self._nsargs.quiet verbose = self._nsargs.verbose preserved_mgr = preservedlibs.PreservedLibraries( inst_repo, None, frozenset(), root=etpConst['systemroot']) preserved = preserved_mgr.list() if not preserved: if not quiet: entropy_client.output(darkgreen( _("No preserved libraries found")), header=darkred(" @@ ")) return 0 for library, elfclass, path, atom in preserved: if quiet: entropy_client.output(path, level="generic") continue needed_by_str = const_convert_to_unicode("") if verbose: needed_by_str += ", %s:" % (darkgreen(_("needed by")), ) entropy_client.output("%s [%s:%s -> %s]%s" % ( darkred(path), purple(library), teal(const_convert_to_unicode(elfclass)), enlightenatom(atom), needed_by_str, )) if verbose: package_ids = inst_repo.searchNeeded(library, elfclass=elfclass) for package_id in package_ids: atom = inst_repo.retrieveAtom(package_id) if atom is None: continue entropy_client.output("%s" % (enlightenatom(atom), ), header=brown(" -> "), importance=0) return 0
def _license(self, entropy_client): """ Solo Query License command. """ quiet = self._nsargs.quiet verbose = self._nsargs.verbose licenses = self._nsargs.licenses settings = entropy_client.Settings() if not quiet: entropy_client.output(darkgreen(_("License Search")), header=darkred(" @@ ")) found = False repo_number = 0 for repo_id in entropy_client.repositories(): repo_number += 1 repo_data = settings["repositories"]["available"][repo_id] if not quiet: header = ( const_convert_to_unicode(" #") + const_convert_to_unicode(repo_number) + const_convert_to_unicode(" ") ) entropy_client.output("%s" % (bold(repo_data["description"]),), header=blue(header)) repo = entropy_client.open_repository(repo_id) key_sorter = lambda x: repo.retrieveAtom(x) for mylicense in licenses: results = repo.searchLicense(mylicense, just_id=True) if not results: continue found = True for pkg_id in sorted(results, key=key_sorter): print_package_info(pkg_id, entropy_client, repo, extended=verbose, strict_output=quiet, quiet=quiet) if not quiet: res_txt = ngettext("entry", "entries", len(results)) toc = [] toc.append(("%s:" % (blue(_("Keyword")),), purple(mylicense))) toc.append(("%s:" % (blue(_("Found")),), "%s %s" % (len(results), brown(res_txt)))) print_table(entropy_client, toc) if not quiet and not found: entropy_client.output(darkgreen("%s." % (_("No matches"),)), header=darkred(" @@ ")) return 0
def _status(self, entropy_server): """ Actual Eit lock|unlock --status code. Just show repo status. """ repositories = entropy_server.repositories() if self._repository_id not in repositories: entropy_server.output( "%s: %s" % (_("Invalid Repository"), self._repository_id), level="error", importance=1) return 1 if not self._quiet: entropy_server.output("%s:" % (darkgreen(_("Mirrors status")), ), header=brown(" * ")) dbstatus = entropy_server.Mirrors.mirrors_status(self._repository_id) for uri, server_lock, client_lock in dbstatus: host = EntropyTransceiver.get_uri_name(uri) if not self._quiet: entropy_server.output("[%s]" % (purple(host), ), header=darkgreen(" @@ ")) if server_lock: lock_str = darkred(_("Locked")) quiet_lock_str = "locked" else: lock_str = darkgreen(_("Unlocked")) quiet_lock_str = "unlocked" if self._quiet: entropy_server.output("%s server %s" % (host, quiet_lock_str), level="generic") else: entropy_server.output("%s: %s" % (blue(_("server")), lock_str), header=brown(" # ")) if client_lock: lock_str = darkred(_("Locked")) quiet_lock_str = "locked" else: lock_str = darkgreen(_("Unlocked")) quiet_lock_str = "unlocked" if self._quiet: entropy_server.output("%s client %s" % (host, quiet_lock_str), level="generic") else: entropy_server.output("%s: %s" % (blue(_("client")), lock_str), header=brown(" # ")) return 0
def _prompt_final_removal(self, entropy_client, inst_repo, removal_queue): """ Prompt some final information to User with respect to the removal queue. """ total = len(removal_queue) mytxt = "%s: %s" % ( blue(_("Packages that would be removed")), darkred(const_convert_to_unicode(total)), ) entropy_client.output( mytxt, header=darkred(" @@ ")) total_removal_size = 0 total_pkg_size = 0 for package_id in set(removal_queue): on_disk_size = inst_repo.retrieveOnDiskSize(package_id) if on_disk_size is None: on_disk_size = 0 pkg_size = inst_repo.retrieveSize(package_id) if pkg_size is None: pkg_size = 0 extra_downloads = inst_repo.retrieveExtraDownload(package_id) for extra_download in extra_downloads: pkg_size += extra_download['size'] on_disk_size += extra_download['disksize'] total_removal_size += on_disk_size total_pkg_size += pkg_size human_removal_size = entropy.tools.bytes_into_human( total_removal_size) human_pkg_size = entropy.tools.bytes_into_human(total_pkg_size) mytxt = "%s: %s" % ( blue(_("Freed disk space")), bold(const_convert_to_unicode(human_removal_size)), ) entropy_client.output( mytxt, header=darkred(" @@ ")) mytxt = "%s: %s" % ( blue(_("Total bandwidth wasted")), bold(str(human_pkg_size)), ) entropy_client.output( mytxt, header=darkred(" @@ "))
def _discard(self, cmd, entropy_client, root, paths_map, idx, scandata): """ Execute the config file discard action. """ try: source = paths_map[idx] except KeyError: # idiot return data = scandata.get(source) if data is None: return source_path = root + source destination_path = root + data['destination'] entropy_client.output( "%s: %s" % ( darkred(_("Source file")), teal(source_path),) ) entropy_client.output( "%s: %s" % ( darkred(_("Destination file")), purple(destination_path),) ) if cmd == -7: rc = entropy_client.ask_question( _("Discard ?")) if rc == _("No"): return entropy_client.output( "%s: %s" % ( darkred(_("Discarding")), teal(source_path),) ) removed = scandata.remove(source) del paths_map[idx] if not removed: entropy_client.output( "%s: %s" % ( darkred(_("Cannot remove")), brown(source_path),), level="warning") entropy_client.output("--")
def _show_removal_info(self, entropy_client, package_ids, manual=False): """ Show packages removal information. """ if manual: entropy_client.output( "%s:" % ( blue(_("These are the packages that " "should be MANUALLY removed")),), header=darkred(" @@ ")) else: entropy_client.output( "%s:" % ( blue(_("These are the packages that " "would be removed")),), header=darkred(" @@ ")) total = len(package_ids) inst_repo = entropy_client.installed_repository() for count, package_id in enumerate(package_ids, 1): atom = inst_repo.retrieveAtom(package_id) installedfrom = inst_repo.getInstalledPackageRepository( package_id) if installedfrom is None: installedfrom = _("Not available") on_disk_size = inst_repo.retrieveOnDiskSize(package_id) pkg_size = inst_repo.retrieveSize(package_id) extra_downloads = inst_repo.retrieveExtraDownload(package_id) for extra_download in extra_downloads: pkg_size += extra_download['size'] on_disk_size += extra_download['disksize'] disksize = entropy.tools.bytes_into_human(on_disk_size) disksize_info = "%s%s%s" % ( bold("["), brown("%s" % (disksize,)), bold("]")) repo_info = bold("[") + brown(installedfrom) + bold("]") mytxt = "%s %s %s" % ( repo_info, enlightenatom(atom), disksize_info) entropy_client.output(mytxt, header=darkred(" ## "))
def _config_phase(self): """ Execute the config phase. """ inst_repo = self._entropy.installed_repository() with inst_repo.shared(): exit_st = self._config_phase_unlocked(inst_repo) if exit_st == 1: txt = _("An error occurred while trying to configure the package") txt2 = "%s. %s: %s" % ( red(_("Make sure that your system is healthy")), blue(_("Error")), exit_st, ) self._entropy.output( darkred(txt), importance = 1, level = "error", header = red(" ## ") ) self._entropy.output( txt2, importance = 1, level = "error", header = red(" ## ") ) elif exit_st == 2: txt = _("An error occurred while trying to configure the package") txt2 = "%s. %s: %s" % ( red(_("It seems that Source Package Manager entry is missing")), blue(_("Error")), exit_st, ) self._entropy.output( darkred(txt), importance = 1, level = "error", header = red(" ## ") ) self._entropy.output( txt2, importance = 1, level = "error", header = red(" ## ") ) return exit_st
def _install(self, entropy_client): """ Solo Security Install command. """ quiet = self._nsargs.quiet pretend = self._nsargs.pretend ask = self._nsargs.ask fetch = self._nsargs.fetch sec = entropy_client.Security() entropy_client.output( "%s..." % ( blue(_("Calculating security updates")),), header=darkred(" @@ ")) inst_repo = entropy_client.installed_repository() with inst_repo.shared(): affected_deps = set() for advisory_id in sec.list(): affected_deps.update(sec.affected_id(advisory_id)) valid_matches = set() for atom in affected_deps: inst_package_id, pkg_rc = inst_repo.atomMatch(atom) if pkg_rc != 0: continue key_slot = inst_repo.retrieveKeySlotAggregated( inst_package_id) package_id, repository_id = entropy_client.atom_match(key_slot) if package_id != -1: valid_matches.add((package_id, repository_id)) if not valid_matches: entropy_client.output( "%s." % ( blue(_("All the available updates " "have been already installed")),), header=darkred(" @@ ")) return 0 exit_st, _show_cfgupd = self._install_action( entropy_client, True, True, pretend, ask, False, quiet, False, False, False, fetch, False, False, False, 1, [], package_matches=list(valid_matches)) return exit_st
def _interactive_merge(self, idx, entropy_client, root, source, dest, paths_map, scandata): """ Interactively merge config file. """ source_path = root + source dest_path = root + dest entropy_client.output( "%s: %s" % ( darkred(_("Interactive merge")), darkgreen(source_path),) ) merge_outcome_path, exit_status = self._interactive_merge_diff( source_path, dest_path) if exit_status in (2, 130): # quit return False, True try: entropy.tools.rename_keep_permissions( merge_outcome_path, source_path) except OSError as err: entropy_client.output( "%s: %s" % ( darkred(_("OSError during interactive merge")), repr(err),), level="error") return False, True except IOError as err: entropy_client.output( "%s: %s" % ( darkred(_("IOError during interactive merge")), repr(err),), level="error") return False, True merged = scandata.merge(source) del paths_map[idx] if not merged: entropy_client.output( "%s: %s" % ( darkred(_("Unable to merge file")), darkgreen(source_path),), level="error") return True, False
def _extract(self, entropy_client): """ Solo Pkg Extract command. """ files = self._nsargs.files savedir = self._nsargs.savedir if not os.path.isdir(savedir) and not os.path.exists(savedir): # this is validated by the parser # but not in case of no --savedir provided const_setup_directory(savedir) if not os.path.exists(savedir): entropy_client.output( "%s: %s" % ( brown(_("broken directory path")), savedir,), level="error", importance=1) return 1 for _file in files: entropy_client.output( "%s: %s" % ( teal(_("working on package file")), purple(_file)), header=darkred(" @@ "), back=True) file_name = os.path.basename(_file) package_path = os.path.join( savedir, file_name + ".db") ext_rc = entropy.tools.dump_entropy_metadata( _file, package_path) if not ext_rc: entropy_client.output( "%s: %s" % ( teal(_("error during metadata extraction")), purple(_file)), header=darkred(" @@ "), level="error", importance=1) return 1 entropy_client.output( "%s: %s" % ( teal(_("metadata file generated")), purple(package_path)), header=darkred(" @@ ")) return 0
def __export_key(self, entropy_server, repo_sec, is_pubkey, repo, store_path): """ Internal key export logic. """ key_msg = _("Exporting private key for repository") func_check = repo_sec.is_privkey_available if is_pubkey: func_check = repo_sec.is_pubkey_available key_msg = _("Exporting public key for repository") try: if not func_check(repo): entropy_server.output("%s: %s" % ( blue(_("No keypair available for repository")), purple(repo), ), level = "error" ) return 1 except repo_sec.KeyExpired: entropy_server.output("%s: %s" % ( darkred(_("Keypair is EXPIRED for repository")), purple(repo), ), level = "error" ) return 1 entropy_server.output("%s: %s" % (blue(key_msg), purple(repo),)) if is_pubkey: key_stream = repo_sec.get_pubkey(repo) else: key_stream = repo_sec.get_privkey(repo) # write to file try: with open(store_path, "w") as dest_w: dest_w.write(key_stream) dest_w.flush() except IOError as err: entropy_server.output("%s: %s [%s]" % ( darkgreen( _("Unable to export GPG key for repository")), bold(repo), err, ), level = "error" ) return 1 entropy_server.output("%s: %s [%s]" % ( darkgreen(_("Exported GPG key for repository")), bold(repo), brown(store_path), ), level = "info" ) return 0
def _info(self, entropy_client): """ Solo Security Info command. """ advisory_ids = self._nsargs.ids sec = entropy_client.Security() exit_st = 1 for advisory_id in advisory_ids: advisory = sec.advisory(advisory_id) if advisory is None: entropy_client.output( "%s: %s." % ( darkred(_("Advisory does not exist")), blue(advisory_id),), header=brown(" :: ")) continue self._print_advisory_information( entropy_client, advisory, key=advisory_id) exit_st = 0 return exit_st
def _show_notice_board_summary(self, entropy_client, repository): """ Show NoticeBoard information to user after repository update. """ mytxt = "%s %s: %s" % ( darkgreen(" @@ "), brown(_("Notice board")), bold(repository), ) entropy_client.output(mytxt) mydict = self._check_notice_board_availability(entropy_client, repository) if not mydict: return for key in sorted(mydict.keys()): mydata = mydict.get(key) mytxt = " [%s] [%s] %s: %s" % ( blue(str(key)), brown(mydata['pubDate']), _("Title"), darkred(mydata['title']), ) entropy_client.output(mytxt)
def _push_progress_to_output(self): mytxt = _("[F]") eta_txt = _("ETA") sec_txt = _("sec") # as in XX kb/sec current_txt = darkred(" %s: " % (mytxt,)) + \ darkgreen(str(round(float(self.__downloadedsize)/1000, 1))) + "/" \ + red(str(round(self.__remotesize, 1))) + " kB" # create progress bar barsize = 10 bartext = "[" curbarsize = 1 averagesize = (self.__average*barsize)/100 while averagesize > 0: curbarsize += 1 bartext += "=" averagesize -= 1 bartext += ">" diffbarsize = barsize - curbarsize while diffbarsize > 0: bartext += " " diffbarsize -= 1 if self.__show_speed: bartext += "] => %s" % (bytes_into_human(self.__datatransfer),) bartext += "/%s : %s: %s" % (sec_txt, eta_txt, self.__time_remaining,) else: bartext += "]" average = str(self.__average) if len(average) < 2: average = " "+average current_txt += " <-> "+average+"% "+bartext TextInterface.output(current_txt, back = True)
def __show_download_files_info(self): count = 0 pl = self._url_path_list[:] TextInterface.output( "%s: %s %s" % ( darkblue(_("Aggregated download")), darkred(str(len(pl))), darkblue(ngettext("item", "items", len(pl))), ), importance = 0, level = "info", header = purple(" ## ") ) for url, save_path in pl: count += 1 fname = os.path.basename(url) uri = spliturl(url)[1] TextInterface.output( "[%s] %s => %s" % ( darkblue(str(count)), darkgreen(uri), blue(fname), ), importance = 0, level = "info", header = brown(" # ") )
def _show_preserved_libraries(self, entropy_client): """ Inform User about preserved libraries living on the filesystem. This method is process and thread safe. """ inst_repo = entropy_client.installed_repository() with inst_repo.shared(): preserved_mgr = PreservedLibraries(inst_repo, None, frozenset(), root=etpConst['systemroot']) preserved = preserved_mgr.list() if preserved: mytxt = ngettext("There is %s preserved library on the system", "There are %s preserved libraries on the system", len(preserved)) % (len(preserved), ) entropy_client.output(darkgreen(mytxt), level="warning") for library, elfclass, path, atom in preserved: entropy_client.output("%s [%s:%s -> %s]" % ( darkred(path), purple(library), teal(const_convert_to_unicode(elfclass)), enlightenatom(atom), ))
def _show_preserved_libraries(self, entropy_client): """ Inform User about preserved libraries living on the filesystem. This method is process and thread safe. """ inst_repo = entropy_client.installed_repository() with inst_repo.shared(): preserved_mgr = PreservedLibraries( inst_repo, None, frozenset(), root=etpConst['systemroot']) preserved = preserved_mgr.list() if preserved: mytxt = ngettext( "There is %s preserved library on the system", "There are %s preserved libraries on the system", len(preserved)) % (len(preserved),) entropy_client.output( darkgreen(mytxt), level="warning") for library, elfclass, path, atom in preserved: entropy_client.output( "%s [%s:%s -> %s]" % ( darkred(path), purple(library), teal(const_convert_to_unicode(elfclass)), enlightenatom(atom), ))
def _show_notice(self, entropy_client, key, mydict): """ Show Notice Board element. """ mytxt = "[%s] [%s] %s: %s" % ( blue(str(key)), brown(mydict['pubDate']), _("Title"), darkred(mydict['title']), ) entropy_client.output(mytxt) mytxt = "%s:\n\n%s\n" % ( darkgreen(_("Content")), mydict['description'], ) entropy_client.output(mytxt) mytxt = "%s: %s" % ( darkgreen(_("Link")), blue(mydict['link']), ) entropy_client.output(mytxt) def fake_callback(s): return True input_params = [('idx', _("Press Enter to continue"), fake_callback, False)] entropy_client.input_box('', input_params, cancel_button=True)
def search(self, entropy_client, inst_repo): """ Solo Search command. """ if not self._quiet: entropy_client.output("%s..." % (darkgreen(_("Searching")), ), header=darkred(" @@ ")) matches_found = 0 for string in self._packages: results = self._search(entropy_client, inst_repo, string) matches_found += len(results) if not self._quiet: toc = [] toc.append(("%s:" % (blue(_("Keywords")), ), purple(', '.join(self._packages)))) toc.append(("%s:" % (blue(_("Found")), ), "%s %s" % ( matches_found, brown(ngettext("entry", "entries", matches_found)), ))) print_table(entropy_client, toc) if not matches_found: return 1 return 0
def __sync_repo(self, entropy_server, repository_id): EitPush.print_repository_status(entropy_server, repository_id) try: sts = entropy_server.Mirrors.sync_repository( repository_id, enable_upload = False, enable_download = True) except OnlineMirrorError as err: entropy_server.output( "%s: %s" % (darkred(_("Error")), err.value), importance=1, level="error") return 1 # try (best-effort) to generate the index of the newly # downloaded repository (indexing=True). repo = None try: if sts == 0: repo = entropy_server.open_server_repository( repository_id, read_only=False, indexing=True, lock_remote=False, do_treeupdates=False) except RepositoryError: repo = None finally: if repo is not None: repo.commit() entropy_server.close_repository(repo) EitPush.print_repository_status(entropy_server, repository_id) return sts
def sync(self): """ Start repository synchronization. @return: sync status (0 means all good; != 0 means error). @rtype: int """ self._entropy.output( "%s ..." % ( darkgreen(_("Repositories synchronization")), ), importance = 2, level = "info", header = darkred(" @@ ") ) lock = RepositoriesUpdateResourcesLock(output=self._entropy) with lock.exclusive(): self._entropy.close_repositories() rc = self._run_sync() if rc: return rc if self.not_available >= len(self.repo_ids): return 2 elif self.not_available > 0: return 1 self._set_last_successful_sync_time() return 0
def _normal_update(self, entropy_client): """ Execute update from this instance. """ repos = self._repositories[:] settings = entropy_client.Settings() if not repos: repos = list(settings['repositories']['available'].keys()) repo_conf = settings.get_setting_files_data()['repositories'] try: repo_intf = entropy_client.Repositories(repos, force=self._force) except AttributeError: entropy_client.output("%s%s %s" % ( darkred(" * "), purple(_("No repositories specified in")), repo_conf, ), level="error", importance=1) return 127 rc = repo_intf.sync() if not rc: for repository in repos: self._show_notice_board_summary(entropy_client, repository) return rc
def asker(spm_name): entropy_server.output( darkred(spm_name), header=brown(" # ")) rc = entropy_server.ask_question( _("Add this package?")) return rc == _("Yes")
def _garbage_collect_preserved_libs(self, preserved_mgr): """ Garbage collect (and remove) libraries preserved on the system no longer available or no longer needed by any installed package. """ preserved_libs = preserved_mgr.collect() inst_repo = preserved_mgr.installed_repository() for library, elfclass, path in preserved_libs: self._entropy.output( "%s: %s [%s, %s]" % ( brown(_("Removing library")), darkgreen(path), purple(library), teal(const_convert_to_unicode("%s" % (elfclass,))), ), importance = 0, level = "warning", header = darkgreen(" :: ") ) self._entropy.logger.log( "[Package]", etpConst['logging']['normal_loglevel_id'], "%s %s [%s:%s]" % ( const_convert_to_unicode("Removing library"), path, library, elfclass,) ) # This will also check if path and it's destinations (in case of # symlink) is owned by other packages. # If this is the case, removal will fail for that specific path. # This may be the case for packages like vmware-workstation, # containing symlinks pointing to system libraries. # See Sabayon bug #5182. remove_failed = preserved_mgr.remove(path) for failed_path, err in remove_failed: self._entropy.output( "%s: %s, %s" % ( purple(_("Failed to remove the library")), darkred(failed_path), err, ), importance = 1, level = "warning", header = brown(" ## ") ) self._entropy.logger.log( "[Package]", etpConst['logging']['normal_loglevel_id'], "Error during %s removal: %s" % (failed_path, err) ) preserved_mgr.unregister(library, elfclass, path) # commit changes to repository if collected if preserved_libs: inst_repo.commit()