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 _wait_resource(self, shared): """ Try to acquire the resource, on failure, print a warning and block until acquired. """ if shared: acquired = self.try_acquire_shared() else: acquired = self.try_acquire_exclusive() if acquired: return True if shared: msg = "%s %s ..." % ( blue(_("Acquiring shared lock on")), darkgreen(self.path()),) else: msg = "%s %s ..." % ( blue(_("Acquiring exclusive lock on")), darkgreen(self.path()),) self._out.output( msg, importance=0, back=True, level="warning" ) if shared: self.acquire_shared() else: self.acquire_exclusive() return True
def _show_config_files_update(self, entropy_client): """ Inform User about configuration file updates, if any. """ entropy_client.output( blue(_("Scanning configuration files to update")), header=darkgreen(" @@ "), back=True) updates = entropy_client.ConfigurationUpdates() scandata = updates.get() if not scandata: entropy_client.output( blue(_("No configuration files to update.")), header=darkgreen(" @@ ")) return mytxt = ngettext( "There is %s configuration file needing update", "There are %s configuration files needing update", len(scandata)) % (len(scandata),) entropy_client.output( darkgreen(mytxt), level="warning") mytxt = "%s: %s" % ( purple(_("Please run")), bold("equo conf update")) entropy_client.output( darkgreen(mytxt), level="warning")
def _get_parser(self): self._real_command = sys.argv[0] descriptor = EitCommandDescriptor.obtain_descriptor( EitPull.NAME) parser = argparse.ArgumentParser( description=descriptor.get_description(), formatter_class=argparse.RawDescriptionHelpFormatter, prog="%s %s" % (sys.argv[0], EitPull.NAME)) parser.add_argument("repo", nargs='?', default=None, metavar="<repo>", help=_("repository")) parser.add_argument("--conservative", action="store_true", help=_("do not execute implicit package name " "and slot updates"), default=self._conservative) parser.add_argument("--quick", action="store_true", default=False, help=_("no stupid questions")) parser.add_argument("--pretend", action="store_true", default=False, help=_("show what would be done")) group = parser.add_mutually_exclusive_group() group.add_argument("--all", action="store_true", default=False, help=_("pull all the repositories")) return parser
def graph_packages(packages, entropy_client, complete = False, repository_ids = None, quiet = False): found = False for package in packages: match = entropy_client.atom_match(package, match_repo = repository_ids) if match[0] == -1: continue if not quiet: entropy_client.output( darkgreen("%s %s..." % ( _("Graphing"), purple(package),) ), header=brown(" @@ ")) found = True pkg_id, repo_id = match repodb = entropy_client.open_repository(repo_id) g_pkg = repodb.retrieveAtom(pkg_id) _graph_package(match, g_pkg, entropy_client, show_complete = complete, quiet = quiet) if not found: entropy_client.output( purple(_("No packages found")), level="warning", importance=1) return 1 return 0
def _get_parser(self): """ Overridden from EitCp """ descriptor = EitCommandDescriptor.obtain_descriptor( EitCp.NAME) parser = argparse.ArgumentParser( description=descriptor.get_description(), formatter_class=argparse.RawDescriptionHelpFormatter, prog="%s %s" % (sys.argv[0], EitCp.NAME)) parser.add_argument("source", nargs=1, metavar="<source>", help=_("source repository")) parser.add_argument("dest", nargs=1, metavar="<dest>", help=_("destination repository")) parser.add_argument("--conservative", action="store_true", help=_("do not execute implicit package name " "and slot updates"), default=self._conservative) parser.add_argument("--deps", action="store_true", default=False, help=_("include dependencies")) parser.add_argument("package", nargs='+', metavar="<package>", help=_("package dependency")) return parser
def _get_parser(self): """ Overridden from SoloCommand. """ _commands = [] descriptor = SoloCommandDescriptor.obtain_descriptor( SoloConf.NAME) parser = argparse.ArgumentParser( description=descriptor.get_description(), formatter_class=argparse.RawDescriptionHelpFormatter, prog="%s %s" % (sys.argv[0], SoloConf.NAME)) subparsers = parser.add_subparsers( title="action", description=_("manage configuration file updates"), help=_("available commands")) update_parser = subparsers.add_parser( "update", help=_("update configuration files")) update_parser.set_defaults(func=self._update) _commands.append("update") self._commands = _commands return parser
def _files(self, entropy_server): """ Actual Eit files code. """ exit_st = 0 for package in self._packages: pkg_id, pkg_repo = entropy_server.atom_match(package) if pkg_id == -1: exit_st = 1 if not self._quiet: entropy_server.output( "%s: %s" % ( purple(_("Not matched")), teal(package)), level="warning", importance=1) continue entropy_repository = entropy_server.open_repository(pkg_repo) files = entropy_repository.retrieveContent( pkg_id, order_by="file") atom = entropy_repository.retrieveAtom(pkg_id) if self._quiet: for path in files: entropy_server.output(path, level="generic") else: for path in files: entropy_server.output(path) entropy_server.output( "[%s] %s: %s %s" % ( purple(pkg_repo), darkgreen(atom), bold(str(len(files))), teal(_("files found")))) return exit_st
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 _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 _notify_comment_submit(self, app, username, text): """ Notify User about Comment submission with current credentials. """ box = NotificationBox( _("You are about to add a <b>comment</b> as <b>%s</b>.") % (escape_markup(username),), message_type=Gtk.MessageType.INFO, context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID, ) def _comment_submit(widget): self._comment_submit(app, username, text) box.add_button(_("_Ok, cool!"), _comment_submit) def _send_comment(): self._on_send_comment(None, app=app) def _logout_webservice(widget): self._logout_webservice(app, _send_comment) box.add_button(_("_No, logout!"), _logout_webservice) box.add_destroy_button(_("_Later")) self._nc.append(box)
def print_date(mydate): if not mydate: return _("N/A") try: return convert_unix_time_to_human_time(int(mydate)) except (ValueError, TypeError,): return _("N/A")
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 _vacuum(self, entropy_client, inst_repo): """ Solo Smart Vacuum command. """ entropy_client.output( "%s..." % ( brown(_("Compacting the Installed Packages repository")), ), importance=1, level="info", header=darkgreen(" @@ "), back=True ) inst_repo.dropAllIndexes() inst_repo.vacuum() inst_repo.commit() entropy_client.output( "%s." % ( brown(_("Compaction complete")), ), importance=1, level="info", header=darkgreen(" @@ ") ) return 0
def _get_parser(self): """ Overridden from SoloCommand. """ _commands = {} descriptor = SoloCommandDescriptor.obtain_descriptor( SoloPreservedLibs.NAME) parser = argparse.ArgumentParser( description=descriptor.get_description(), formatter_class=argparse.RawDescriptionHelpFormatter, prog="%s %s" % (sys.argv[0], SoloPreservedLibs.NAME)) subparsers = parser.add_subparsers( title="action", description=_("manage preserved libraries"), help=_("available commands")) list_parser = subparsers.add_parser( "list", help=_("list the currently preserved libraries")) list_parser.set_defaults(func=self._list) self._setup_verbose_quiet_parser(list_parser) _commands["list"] = {} gc_parser = subparsers.add_parser( "gc", help=_("show libraries that could be garbage collected")) gc_parser.set_defaults(func=self._gc) _commands["gc"] = {} self._commands = _commands return parser
def _show_help(self, *args): # equo help <foo> <bar> if len(self._args) > 1: # syntax error return -10 parser = argparse.ArgumentParser( description=_("Entropy Command Line Client, Equo"), epilog="http://www.sabayon.org", formatter_class=ColorfulFormatter) # filtered out in solo.main. Will never get here parser.add_argument( "--color", action="store_true", default=None, help=_("force colored output")) descriptors = SoloCommandDescriptor.obtain() descriptors.sort(key = lambda x: x.get_name()) group = parser.add_argument_group("command", "available commands") for descriptor in descriptors: if descriptor.get_class().HIDDEN: continue aliases = descriptor.get_class().ALIASES aliases_str = ", ".join([teal(x) for x in aliases]) if aliases_str: aliases_str = " [%s]" % (aliases_str,) name = "%s%s" % (purple(descriptor.get_name()), aliases_str) desc = descriptor.get_description() group.add_argument(name, help=darkgreen(desc), action="store_true") parser.print_help() if not self._args: return 1 return 0
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_package_dependencies(self, entropy_server, atom, orig_deps, partial = False): """ Print package dependencies for atom. """ if not partial: entropy_server.output( "%s, %s" % ( blue(atom), darkgreen(_("package dependencies"))), header=brown(" @@ ")) else: entropy_server.output("") for dep_str, dep_id in orig_deps: entropy_server.output( "[%s: %s] %s" % ( brown(_("type")), darkgreen(str(dep_id+1)), purple(dep_str)), header=brown(" #")) if not orig_deps: entropy_server.output( _("No dependencies"), header=brown(" # ")) else: self._show_dependencies_legend(entropy_server, " ") if partial: entropy_server.output("")
def _show_notice(self, entropy_server, key, mydict): """ Print notice board entry content """ mytxt = "[%s] [%s]" % ( blue(str(key)), brown(mydict['pubDate']), ) entropy_server.output(mytxt) entropy_server.output("", level="generic") entropy_server.output( "%s: %s" % (darkgreen(_("Title")), purple(mydict['title'])), level="generic") entropy_server.output("", level="generic") entropy_server.output(mydict['description'], level="generic") entropy_server.output("", level="generic") mytxt = "%s: %s" % ( darkgreen(_("URL")), blue(mydict['link']), ) entropy_server.output(mytxt) def fake_callback(dummy_s): return True input_params = [ ('idx', _('Press Enter to continue'), fake_callback, False) ] data = entropy_server.input_box( '', input_params, cancel_button = True)
def revgraph_packages(packages, entropy_client, complete = False, repository_ids = None, quiet = False): if repository_ids is None: repository_ids = [entropy_client.installed_repository( ).repository_id()] found = False for repository_id in repository_ids: entropy_repository = entropy_client.open_repository(repository_id) for package in packages: pkg_id, pkg_rc = entropy_repository.atomMatch(package) if pkg_rc == 1: continue if not quiet: entropy_client.output( darkgreen("%s %s..." % ( _("Reverse graphing installed package"), purple(package),) ), header=brown(" @@ ")) found = True g_pkg = entropy_repository.retrieveAtom(pkg_id) _revgraph_package(entropy_client, pkg_id, g_pkg, entropy_repository, show_complete = complete, quiet = quiet) if not found: entropy_client.output( purple(_("No packages found")), level="warning", importance=1) return 1 return 0
def _submit_fail(): box = NotificationBox( _("Comment submit error: <i>%s</i>") % (err_msg,), message_type=Gtk.MessageType.ERROR, context_id=self.COMMENT_NOTIFICATION_CONTEXT_ID) box.add_destroy_button(_("Ok, thanks")) self._nc.append(box)
def setup(self): pref = Preference( 50, _("Clean Entropy Web Service Session"), _("Discard any registered login credential " "used to send votes and comments."), "edit-clear", self._logout) self._prefc.append(pref) self.connect( "application-activated", self._on_application_activated) self._app_store.connect( "redraw-request", self._on_redraw_request) self._app_comment_send_button.connect( "clicked", self._on_send_comment) self._app_comment_send_button.set_sensitive(False) self._app_comment_text_buffer.connect( "changed", self._on_comment_buffer_changed) self._stars.connect("changed", self._on_stars_clicked) self._app_info_lbl.connect( "activate-link", self._on_info_lbl_activate_link) self._service.connect( "application-processed", self._on_reload_state) self._service.connect( "application-processing", self._on_reload_state) self._service.connect( "application-abort", self._on_reload_state)
def _trigger_call_ext_generic(self): try: return self._do_trigger_call_ext_generic() except Exception as err: mykey = self._pkgdata['category']+"/"+self._pkgdata['name'] tback = entropy.tools.get_traceback() self._entropy.output(tback, importance = 0, level = "error") self._entropy.logger.write(tback) self._entropy.logger.log( "[Trigger]", etpConst['logging']['normal_loglevel_id'], "[POST] ATTENTION Cannot run External trigger for " + \ mykey + "!! " + str(Exception) + ": " + repr(err) ) mytxt = "%s: %s %s. %s." % ( bold(_("QA")), brown(_("Cannot run External trigger for")), bold(mykey), brown(_("Please report it")), ) self._entropy.output( mytxt, importance = 0, header = red(" ## ") ) return 0
def mirror_fail_check(repository_id, best_mirror): # check if uri is sane if not mirror_status.get_failing_mirror_status(best_mirror) >= 30: return False # set to 30 for convenience mirror_status.set_failing_mirror_status(best_mirror, 30) mirrorcount = repo_uris[repository_id].index(best_mirror) + 1 txt = "( mirror #%s ) %s %s - %s" % ( mirrorcount, blue(_("Mirror")), red(self._get_url_name(best_mirror)), _("maximum failure threshold reached"), ) self._entropy.output( txt, importance = 1, level = "warning", header = red(" ## ") ) if mirror_status.get_failing_mirror_status(best_mirror) == 30: mirror_status.add_failing_mirror(best_mirror, 45) elif mirror_status.get_failing_mirror_status(best_mirror) > 31: mirror_status.add_failing_mirror(best_mirror, -4) else: mirror_status.set_failing_mirror_status(best_mirror, 0) try: remaining[repository_id].remove(best_mirror) except ValueError: # ignore pass return True
def update_queue_information(self, queue_len): """ Update Action Queue related info. """ daemon_action = self._last_daemon_action msg = None if daemon_action == DaemonAppActions.INSTALL: msg = _("Installing") elif daemon_action == DaemonAppActions.REMOVE: msg = _("Removing") if msg is not None: more_msg = "" queue_len -= 1 queue_len = max(0, queue_len) if queue_len: more_msg = ngettext( ", and <b>%d</b> <i>more in queue</i>", ", and <b>%d</b> <i>more in queue</i>", queue_len) more_msg = prepare_markup(more_msg % (queue_len,)) self._action_label.set_markup( "<big><b>%s</b>%s</big>" % ( escape_markup(msg), more_msg,))
def _rename(self, button): """ Try to login to Entropy Web Services. """ repository_id = self._repo_entry.get_text() valid = entropy.tools.validate_repository_id(repository_id) if not valid: self._repo_message.show() self._repo_message.set_markup( prepare_markup( _("<b>Invalid</b> Repository name!"))) return from_repository_id = self._repo.repository() renamed = self._service.rename_repository( from_repository_id, repository_id) if not renamed: self._repo_message.show() self._repo_message.set_markup( prepare_markup( _("Repository rename <b>not allowed</b>!"))) return self.destroy() self.emit("renamed")
def _scan_packages(self, entropy_client, inst_repo, packages): """ Scan the list of package names filtering out unmatched entries. """ found_pkgs = [] for package in packages: package_id, _pkg_rc = inst_repo.atomMatch(package) if package_id == -1: mytxt = "!!! %s: %s %s." % ( purple(_("Warning")), teal(const_convert_to_unicode(package)), purple(_("is not available")), ) entropy_client.output( "!!!", level="warning", importance=1) entropy_client.output( mytxt, level="warning", importance=1) entropy_client.output( "!!!", level="warning", importance=1) continue found_pkgs.append(package_id) return found_pkgs
def cleanup(entropy_client, directories): """ Temporary files cleaner. @param directories: list of directory paths @type directories: list @return: exit status @rtype: int """ counter = 0 for xdir in directories: if not os.path.isdir(xdir): continue entropy_client.output( "%s %s %s..." % ( _("Cleaning"), darkgreen(xdir), _("directory"),), back = True) for data in os.listdir(xdir): subprocess.call(["rm", "-rf", os.path.join(xdir, data)]) counter += 1 entropy_client.output( "%s: %s %s" % ( _("Cleaned"), counter, _("files and directories"),) ) return 0
def _notify_vote_submit(self, app, username, vote): """ Notify User about Comment submission with current credentials. """ msg = ngettext( "Rate <b>%s</b> as <b>%s</b>, with <b>%d</b> star?", "Rate <b>%s</b> as <b>%s</b>, with <b>%d</b> stars?", vote, ) msg = msg % (app.name, escape_markup(username), vote) box = NotificationBox(msg, message_type=Gtk.MessageType.INFO, context_id=self.VOTE_NOTIFICATION_CONTEXT_ID) def _vote_submit(widget): self._vote_submit(app, username, vote) box.add_button(_("_Ok, cool!"), _vote_submit) def _send_vote(): self._on_stars_clicked(self._stars, app=app) def _logout_webservice(widget): self._logout_webservice(app, _send_vote) box.add_button(_("_No, logout!"), _logout_webservice) box.add_destroy_button(_("_Later")) self._nc.append(box)
def _setup_not_found_box(self, search_text): """ Setup "not found" message label and layout """ nf_box = self._not_found_box with self._entropy.rwsem().reader(): # now self._not_found_label is available meant_packages = self._entropy.get_meant_packages( search_text) text = escape_markup(search_text) msg = "%s <b>%s</b>" % ( escape_markup(_("Nothing found for")), text,) if meant_packages: first_entry = meant_packages[0] app = Application( self._entropy, self._entropy_ws, self._service, first_entry) name = app.name msg += ", %s" % ( prepare_markup(_("did you mean <a href=\"%s\">%s</a>?")) % ( escape_markup(name), escape_markup(name),),) self._not_found_label.set_markup(msg)
def get_markup(self): """ Return Repository markup text. """ msg = "<b>%s</b>\n<small><i>%s</i>\n<b>%s</b></small>" if self.enabled(): enabled_msg = _("Enabled") else: enabled_msg = _("Disabled") msg = msg % (escape_markup( self.repository()), escape_markup( self.description()), escape_markup(enabled_msg)) return prepare_markup(msg)
def acquired_msg_cb(obj, exclusive): if exclusive: msg = _("Acquired exclusive lock on") else: msg = _("Acquired shared lock on") self._entropy.output( "%s %s" % ( darkred(msg), darkgreen(obj.get_path()), ), level="warning", # use stderr, avoid breaking --quiet back=True, importance=0)
def _submit_fail(err_msg): if err_msg is None: box = NotificationBox( _("You already voted this <b>Application</b>"), message_type=Gtk.MessageType.ERROR, context_id=self.VOTE_NOTIFICATION_CONTEXT_ID) else: box = NotificationBox( _("Vote error: <i>%s</i>") % (err_msg, ), message_type=Gtk.MessageType.ERROR, context_id=self.VOTE_NOTIFICATION_CONTEXT_ID) box.add_destroy_button(_("Ok, thanks")) self._nc.append(box)
def _quickpkg(self, entropy_client, inst_repo): """ Solo Pkg Quickpkg command. """ packages = self._nsargs.packages 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 package_ids = self._scan_packages(entropy_client, inst_repo, packages) if not package_ids: return 1 for package_id in package_ids: atom = inst_repo.retrieveAtom(package_id) entropy_client.output( "%s: %s" % ( teal(_("generating package")), purple(atom),), header=brown(" @@ "), back=True) pkg_data = inst_repo.getPackageData(package_id) file_path = entropy_client.generate_package( pkg_data, save_directory=savedir) if file_path is None: entropy_client.output( "%s: %s" % ( darkred(_("package file creation error")), blue(atom),), level="error", importance=1) return 3 entropy_client.output( "[%s] %s: %s" % ( darkgreen(atom), teal(_("package generated")), purple(file_path),), header=brown(" ## ")) 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 _download(self, entropy_client): """ Solo Download command. """ ask = self._nsargs.ask pretend = self._nsargs.pretend verbose = self._nsargs.verbose quiet = self._nsargs.quiet deep = self._nsargs.deep deps = not self._nsargs.nodeps recursive = not self._nsargs.norecursive relaxed = self._nsargs.relaxed onlydeps = self._nsargs.onlydeps bdeps = self._nsargs.bdeps multifetch = self._nsargs.multifetch inst_repo = entropy_client.installed_repository() with inst_repo.shared(): packages = self._scan_packages(entropy_client, self._nsargs.packages) if not packages: entropy_client.output("%s." % (darkred(_("No packages found")), ), level="error", importance=1) return 1 run_queue, removal_queue = self._generate_install_queue( entropy_client, packages, deps, False, deep, relaxed, onlydeps, bdeps, recursive) if (run_queue is None) or (removal_queue is None): return 1 elif not (run_queue or removal_queue): entropy_client.output("%s." % (blue(_("Nothing to do")), ), level="warning", header=darkgreen(" @@ ")) return 0 if pretend: entropy_client.output("%s." % (blue(_("All done")), )) return 0 down_data = {} exit_st = self._download_packages(entropy_client, run_queue, down_data, multifetch) if exit_st == 0: self._signal_ugc(entropy_client, down_data) return exit_st
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 _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 show_notice_window(self): if self.notice_window_shown: const_debug_write("show_notice_window", "Notice window already shown.") return if not self.package_updates: const_debug_write("show_notice_window", "No computed updates.") return entropy_ver = None packages = [] for atom in self.package_updates: key = entropy.dep.dep_getkey(atom) avail_rev = entropy.dep.dep_get_entropy_revision(atom) avail_tag = entropy.dep.dep_gettag(atom) my_pkg = entropy.dep.remove_entropy_revision(atom) my_pkg = entropy.dep.remove_tag(my_pkg) pkgcat, pkgname, pkgver, pkgrev = entropy.dep.catpkgsplit(my_pkg) ver = pkgver if pkgrev != "r0": ver += "-%s" % (pkgrev, ) if avail_tag: ver += "#%s" % (avail_tag, ) if avail_rev: ver += "~%s" % (avail_tag, ) if key == "sys-apps/entropy": entropy_ver = ver packages.append("%s (%s)" % ( key, ver, )) critical_msg = "" if entropy_ver is not None: critical_msg = "%s <b>sys-apps/entropy</b> %s, %s <b>%s</b>. %s." % ( _("Your system currently has an outdated version of"), _("installed"), _("the latest available version is"), entropy_ver, _("It is recommended that you upgrade to " "the latest before updating any other packages")) self._notice_window.populate(packages, critical_msg) self._notice_window.show() self.notice_window_shown = True
def _on_applications_managed(self, widget, success, local_activity): """ Emitted by RigoServiceController telling us that enqueue application actions have been completed. """ msg = "N/A" if not success: if local_activity == LocalActivityStates.MANAGING_APPLICATIONS: msg = "<b>%s</b>: %s" % ( _("Application Management Error"), _("please check the management log"), ) elif local_activity == LocalActivityStates.UPGRADING_SYSTEM: msg = "<b>%s</b>: %s" % ( _("System Upgrade Error"), _("please check the upgrade log"), ) message_type = Gtk.MessageType.ERROR else: if local_activity == LocalActivityStates.MANAGING_APPLICATIONS: msg = _("Applications managed <b>successfully</b>!") elif local_activity == LocalActivityStates.UPGRADING_SYSTEM: msg = _("System Upgraded <b>successfully</b>!") message_type = Gtk.MessageType.INFO box = NotificationBox( msg, message_type=message_type, context_id=RigoServiceController.NOTIFICATION_CONTEXT_ID) box.add_destroy_button(_("Ok, thanks")) box.add_button(_("Show me"), self._on_show_work_view) self._nc.append(box) self._work_view_c.deactivate_app_box()
def _show_removal_error(self, err): """ During Comment removal, the WebService raised an auth error """ msg = "<b>%s</b>: %s" % (escape_markup( _("Cannot remove comment")), err) box = NotificationBox( msg, message_type=Gtk.MessageType.ERROR, context_id=self.COMMENT_REMOVE_NOTIFICATION_CONTEXT) box.add_destroy_button(_("_Ok, thanks")) self._nc.append(box) self.show()
def warn_version_mismatch(): equo_ver = read_client_release() entropy_ver = etpConst['entropyversion'] if equo_ver != entropy_ver: print_warning("") print_warning("%s: %s" % ( bold(_("Entropy/Equo version mismatch")), purple(_("it could make your system explode!")), )) print_warning("(%s [equo] & %s [entropy])" % ( blue(equo_ver), blue(entropy_ver), )) print_warning("")
def _get_parser(self): """ Overridden from SoloCommand. """ descriptor = SoloCommandDescriptor.obtain_descriptor(SoloLibtest.NAME) parser = argparse.ArgumentParser( description=descriptor.get_description(), formatter_class=argparse.RawDescriptionHelpFormatter, prog="%s %s" % (sys.argv[0], SoloLibtest.NAME)) _commands = [] parser.add_argument("--ask", "-a", action="store_true", default=False, help=_("ask before making any changes")) _commands.append("--ask") _commands.append("-a") parser.add_argument("--quiet", "-q", action="store_true", default=False, help=_("show less details " "(useful for scripting)")) _commands.append("--quiet") _commands.append("-q") parser.add_argument("--pretend", "-p", action="store_true", default=False, help=_("just show what would be done")) _commands.append("--pretend") _commands.append("-p") parser.add_argument("--listfiles", action="store_true", default=False, help=_("print broken files to stdout")) _commands.append("--listfiles") parser.add_argument("--dump", action="store_true", default=False, help=_("dump results to files")) _commands.append("--dump") self._commands = _commands return parser
def _inject(self, entropy_server): """ Actual Eit inject code. """ extensions = entropy_server.Spm_class( ).binary_packages_extensions() etp_pkg_files = [] for pkg_path in self._packages: pkg_path = os.path.realpath(pkg_path) if not const_file_readable(pkg_path): entropy_server.output( "%s: %s" % (purple(pkg_path), teal(_("no such file or directory"))), importance=1, level="error") return 1 found = False for ext in extensions: if pkg_path.endswith("."+ext): etp_pkg_files.append(pkg_path) found = True break if not found: entropy_server.output( "%s: %s" % (purple(pkg_path), teal(_("unsupported extension"))), importance=1, level="error") return 1 if not etp_pkg_files: entropy_server.output( teal(_("no valid package paths")), importance=1, level="error") return 1 # in this case, no split package files are provided repository_id = entropy_server.repository() etp_pkg_files = [([x], True,) for x in etp_pkg_files] package_ids = entropy_server.add_packages_to_repository( repository_id, etp_pkg_files, ask=self._ask) if package_ids: # checking dependencies and print issues entropy_server.extended_dependencies_test([repository_id]) entropy_server.commit_repositories() if package_ids: return 0 return 1
def _setup_verbose_quiet_parser(self, parser): """ Add --verbose and --quiet switches to parser. """ parser.add_argument("--verbose", "-v", action="store_true", default=False, help=_("verbose output")) parser.add_argument("--quiet", "-q", action="store_true", default=False, help=_("quiet output"))
def _clean(self, entropy_client, _inst_repo): """ Solo Cache Clean command. """ entropy_client.output(blue( _("Cleaning Entropy cache, please wait ...")), level="info", header=brown(" @@ "), back=True) entropy_client.clear_cache() entropy_client.output(darkgreen(_("Entropy cache cleaned.")), level="info", header=brown(" @@ ")) 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 upload(self, load_path, remote_path): self.__connect_if_not() path = os.path.join(self.__ftpdir, remote_path) tmp_path = path + EntropyUriHandler.TMP_TXC_FILE_EXT tries = 0 def updater(buf): self._commit_buffer_update(len(buf)) self._update_speed() self._update_progress() self._speed_limit_loop() while tries < 10: tries += 1 self._init_vars() try: file_size = get_file_size(load_path) self.__filesize = round(float(file_size) / 1000, 1) self.__filekbcount = 0 with open(load_path, "r") as f: rc = self.__ftpconn.storbinary("STOR " + tmp_path, f, 8192, updater) self._update_progress(force=True) # now we can rename the file with its original name self.rename(tmp_path, path) done = rc.find("226") != -1 return done except Exception as e: # connection reset by peer print_traceback() mytxt = red("%s: %s, %s... #%s") % ( _("Upload issue"), repr(e), _("retrying"), tries + 1, ) self.output(mytxt, importance=1, level="warning", header=" ") self._reconnect() # reconnect self.delete(tmp_path) self.delete(path)
def _remove(self, entropy_server): """ Actual Eit remove code. """ repository_id = entropy_server.repository() repo = entropy_server.open_repository(repository_id) pkg_matches = [] for package in self._packages: pkg = repo.atomMatch(package, multiMatch = True) for pkg_id in pkg[0]: pkg_match = (pkg_id, repository_id) if pkg_match not in pkg_matches: pkg_matches.append(pkg_match) if not pkg_matches: entropy_server.output( purple(_("No packages found")), importance=1, level="error") return 1 if not self._nodeps: pkg_matches = entropy_server.get_reverse_queue(pkg_matches, system_packages = False) entropy_server.output( darkgreen( _("These are the packages that would be removed") + ":"), importance=1, header=brown(" @@ ")) repo_map = {} for pkg_id, repo_id in pkg_matches: repo = entropy_server.open_repository(repo_id) pkgatom = repo.retrieveAtom(pkg_id) entropy_server.output( "[%s] %s" % (teal(repo_id), purple(pkgatom)), header=brown(" # ")) obj = repo_map.setdefault(repo_id, []) obj.append(pkg_id) if self._ask: resp = entropy_server.ask_question( _("Would you like to continue ?")) if resp == _("No"): return 0 for repo_id, pkg_ids in repo_map.items(): entropy_server.remove_packages(repo_id, pkg_ids) return 0
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 _mirrorsort(self, entropy_client): """ Solo Repo Mirrorsort command. """ exit_st = 0 settings = entropy_client.Settings() excluded_repos = settings['repositories']['excluded'] available_repos = settings['repositories']['available'] simulate = self._nsargs.simulate for repo in self._nsargs.repo: try: repo_data = entropy_client.reorder_mirrors(repo, dry_run=simulate) except KeyError: entropy_client.output("[%s] %s" % ( purple(repo), blue(_("repository not available")), ), level="warning", importance=1) exit_st = 1 continue # show new order, this doesn't take into account # fallback mirrors which are put at the end of # the list by SystemSettings logic. mirrors = copy.copy(repo_data['plain_packages']) if mirrors and not simulate: mirrors.reverse() entropy_client.output("[%s] %s" % ( teal(repo), darkgreen(_("mirror order:")), )) count = 0 for mirror in mirrors: count += 1 entropy_client.output(" %d. %s" % ( count, brown(mirror), )) entropy_client.output("[%s] %s" % ( teal(repo), blue(_("mirrors sorted successfully")), )) return exit_st
def _setup_application_info(self, app, metadata): """ Setup the actual UI widgets content and emit 'application-show' """ self._setup_application_markup(metadata['markup']) self._app_info_lbl.set_markup(metadata['info']) # install/remove/update buttons self._setup_buttons(app, metadata['is_installed'], metadata['is_updatable']) # only comments supported, point to the remote # www service for the rest if app.is_installed_app(): self._app_comment_more_label.hide() else: self._app_comment_more_label.set_markup( "<b>%s</b>: <a href=\"%s\">%s</a>" % ( escape_markup(_("Want to add images, etc?")), escape_markup(build_application_store_url(app, "ugc")), escape_markup(_("click here!")), )) self._app_comment_more_label.show() stats = metadata['stats'] icon = metadata['icon'] self._setup_application_stats(stats, icon) # load application comments asynchronously # so at the beginning, just place a spinner spinner = Gtk.Spinner() spinner.set_size_request(-1, 48) spinner.set_tooltip_text(escape_markup(_("Loading comments..."))) spinner.set_name("comment-box-spinner") for child in self._app_comments_box.get_children(): child.destroy() self._app_comments_box.pack_start(spinner, False, False, 0) spinner.show() spinner.start() downloader = ApplicationViewController.MetadataDownloader( app, self, self._append_comments_safe, app.download_comments) downloader.start() downloader = ApplicationViewController.MetadataDownloader( app, self, self._append_images_safe, app.download_images) downloader.start() self.emit("application-show", app)
def _remove_phase(self): """ Run the remove phase. """ inst_repo = self._entropy.open_repository(self._repository_id) with inst_repo.exclusive(): if not inst_repo.isPackageIdAvailable(self._package_id): self._entropy.output(darkred( _("The requested package is no longer available")), importance=1, level="warning", header=brown(" @@ ")) # install.py assumes that a zero exit status is returned # in this case. return 0 atom = inst_repo.retrieveAtom(self._package_id) xterm_title = "%s %s: %s" % ( self._xterm_header, _("Removing"), atom, ) self._entropy.set_title(xterm_title) self._entropy.output("%s: %s" % ( blue(_("Removing")), red(atom), ), importance=1, level="info", header=red(" ## ")) self._entropy.logger.log("[Package]", etpConst['logging']['normal_loglevel_id'], "Removing package: %s" % (atom, )) txt = "%s: %s" % ( blue(_("Removing from Entropy")), red(atom), ) self._entropy.output(txt, importance=1, level="info", header=red(" ## ")) return self._remove_phase_unlocked(inst_repo)
def _get_parser(self): """ Overridden from EitCommand """ descriptor = EitCommandDescriptor.obtain_descriptor( EitBump.NAME) parser = argparse.ArgumentParser( description=descriptor.get_description(), formatter_class=argparse.RawDescriptionHelpFormatter, prog="%s %s" % (sys.argv[0], EitBump.NAME)) parser.add_argument("repo", nargs='?', default=None, metavar="<repo>", help=_("repository")) parser.add_argument("--sync", action="store_true", default=self._sync, help=_("sync with remote repository")) return parser
def _on_work_interrupt(self, widget): """ We've been explicitly asked to interrupt the currently ongoing work """ rc = self._show_yesno_dialog( self._window, escape_markup(_("Activity Interruption")), escape_markup( _("Are you sure you want to interrupt" " the ongoing Activity? The interruption will" " occur as soon as possible, potentially not" " immediately."))) if rc == Gtk.ResponseType.NO: return self._service.interrupt_activity()
def _spmuids(self, entropy_client, inst_repo): """ Solo Smart Spmuids command. """ entropy_client.output("%s..." % (purple(_("Re-generating packages mapping")), ), header=brown(" @@ "), back=True) inst_repo.regenerateSpmUidMapping() entropy_client.output("%s..." % (purple(_("Packages mapping re-generated")), ), header=brown(" @@ ")) return 0
def _compress_packages(self, entropy_server, repository_id, packages): """ Compress (and generate package tarball) the list of given spm package names inside the given Entropy repository. """ entropy_server.output( blue(_("Compressing packages")), header=brown(" @@ ")) generated_packages = collections.deque() store_dir = entropy_server._get_local_store_directory(repository_id) if not os.path.isdir(store_dir): try: os.makedirs(store_dir) except (IOError, OSError) as err: entropy_server.output( "%s: %s" % (_("Cannot create store directory"), err), header=brown(" !!! "), importance=1, level="error") return generated_packages, 1 for count, spm_name in enumerate(packages, 1): entropy_server.output( teal(spm_name), header=brown(" # "), count=(count, len(packages))) try: pkg_list = entropy_server.Spm().generate_package(spm_name, store_dir) generated_packages.append(pkg_list) except OSError: entropy.tools.print_traceback() entropy_server.output( bold(_("Ignoring broken Spm entry, please recompile it")), header=brown(" !!! "), importance=1, level="warning") if not generated_packages: entropy_server.output( red(_("Nothing to do, check later.")), header=brown(" * ")) return generated_packages, 0 return generated_packages, None
def _handle_preserved_lib(self, path, atom, preserved_mgr): """ Preserve libraries that would be removed but are still needed by installed packages. This is a safety measure for accidental removals. Proper library dependency ordering should be done during dependencies calculation. """ solved = preserved_mgr.resolve(path) if solved is None: return None paths = preserved_mgr.determine(path) if paths: self._entropy.output( "%s: %s, %s" % ( darkgreen(_("Protecting")), teal(path), darkgreen(_("library needed by:")), ), importance = 1, level = "warning", header = red(" ## ") ) library, elfclass, s_path = solved preserved_mgr.register(library, elfclass, s_path, atom) installed_package_ids = preserved_mgr.needed(path) installed_repository = preserved_mgr.installed_repository() for installed_package_id in installed_package_ids: atom = installed_repository.retrieveAtom(installed_package_id) self._entropy.output( brown(atom), importance = 0, level = "warning", header = darkgreen(" :: ") ) self._entropy.logger.log( "[Package]", etpConst['logging']['normal_loglevel_id'], "Protecting library %s, due to package: %s" % ( path, atom,) ) return paths
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 _remove(self, entropy_server): """ Actual Eit notice remove code. """ if self._repository_id is None: self._repository_id = entropy_server.repository() data = entropy_server.Mirrors.read_notice_board(self._repository_id) if data is None: entropy_server.output(purple(_("Notice board not available")), importance=1, level="error") return 1 items, counter = data changed = False while True: try: sel = self._show_notice_selector( entropy_server, darkgreen(_("Choose the one you want to remove")), items) except KeyboardInterrupt: break if (sel >= 0) and (sel <= counter): self._show_notice(entropy_server, sel, items.get(sel)) q_rc = entropy_server.ask_question( _("Are you sure you want to remove this?")) if q_rc == _("Yes"): changed = True entropy_server.Mirrors.remove_from_notice_board( self._repository_id, sel) data = entropy_server.Mirrors.read_notice_board( self._repository_id, do_download=False) items, counter = data elif sel == -1: break if changed or (counter == 0): if counter == 0: status = entropy_server.Mirrors.remove_notice_board( self._repository_id) else: status = entropy_server.Mirrors.upload_notice_board( self._repository_id) if not status: return 1 return 0