def _disable_repo(self, entropy_client, repo): """ Solo Repo Disable for given repository. """ disabled = False try: disabled = entropy_client.disable_repository(repo) except ValueError: entropy_client.output( "[%s] %s" % ( purple(repo), blue(_("cannot disable repository")),), level="warning", importance=1) return 1 if disabled: entropy_client.output( "[%s] %s" % ( teal(repo), blue(_("repository disabled")),)) return 0 entropy_client.output( "[%s] %s" % ( purple(repo), blue(_("cannot disable repository")),), level="warning", importance=1) return 1
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 _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 _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 _disable(self, entropy_client): """ Solo Repo Disable command. """ exit_st = 0 settings = entropy_client.Settings() excluded_repos = settings['repositories']['excluded'] available_repos = settings['repositories']['available'] for repo in self._nsargs.repo: if repo in excluded_repos: entropy_client.output( "[%s] %s" % ( purple(repo), blue(_("repository already disabled")),), level="warning", importance=1) exit_st = 1 continue if repo not in available_repos: entropy_client.output( "[%s] %s" % ( purple(repo), blue(_("repository not available")),), level="warning", importance=1) exit_st = 1 continue _exit_st = self._disable_repo(entropy_client, repo) if _exit_st != 0: exit_st = _exit_st return exit_st
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 _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 match(self, entropy_client): """ Solo Match command. """ if not self._quiet: entropy_client.output( "%s..." % (darkgreen(_("Matching")),), header=darkred(" @@ ")) matches_found = 0 for string in self._packages: results = self._match( entropy_client, 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 _remove(self, entropy_server): """ Eit Repo Remove command. """ current_repos = entropy_server.repositories() exit_st = 0 for repository_id in self._nsargs.id: if repository_id not in current_repos: entropy_server.output( "[%s] %s" % ( purple(repository_id), blue(_("repository not available")),), level="warning", importance=1) exit_st = 1 continue parser = RepositoryConfigParser() removed = parser.remove(repository_id) if not removed: exit_st = 1 entropy_server.output( "[%s] %s" % ( purple(repository_id), blue(_("cannot remove repository")),), level="warning", importance=1) else: entropy_server.output( "[%s] %s" % ( purple(repository_id), blue(_("repository removed succesfully")),)) return exit_st
def _required(self, entropy_client, inst_repo): """ Solo Query Required command. """ quiet = self._nsargs.quiet verbose = self._nsargs.verbose libraries = self._nsargs.libraries if not quiet: entropy_client.output(darkgreen(_("Required Packages Search")), header=darkred(" @@ ")) key_sorter = lambda x: inst_repo.retrieveAtom(x) for library in libraries: results = inst_repo.searchNeeded(library, like=True) for pkg_id in sorted(results, key=key_sorter): print_package_info( pkg_id, entropy_client, inst_repo, installed_search=True, strict_output=True, extended=verbose, quiet=quiet, ) if not quiet: toc = [] entity_str = ngettext("package", "packages", len(results)) toc.append(("%s:" % (blue(_("Library")),), purple(library))) toc.append(("%s:" % (blue(_("Found")),), "%s %s" % (len(results), brown(entity_str)))) print_table(entropy_client, toc) return 0
def _search_descriptions(self, descriptions, entropy_client, entropy_repository, quiet, verbose): key_sorter = lambda x: entropy_repository.retrieveAtom(x) found = 0 for desc in descriptions: pkg_ids = entropy_repository.searchDescription(desc, just_id=True) if not pkg_ids: continue found += len(pkg_ids) for pkg_id in sorted(pkg_ids, key=key_sorter): if quiet: entropy_client.output(entropy_repository.retrieveAtom(pkg_id)) else: print_package_info( pkg_id, entropy_client, entropy_repository, extended=verbose, strict_output=False, quiet=False ) if not quiet: toc = [] toc.append(("%s:" % (blue(_("Keyword")),), purple(desc))) toc.append( ( "%s:" % (blue(_("Found")),), "%s %s" % (len(pkg_ids), brown(ngettext("entry", "entries", len(pkg_ids)))), ) ) print_table(entropy_client, toc) return found
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 __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 _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 _remove_packages(self, entropy_server, package_matches): """ Remove the given Entropy packages from their repositories. """ def show_rm(pkg_id, pkg_repo): repo = entropy_server.open_repository(pkg_repo) atom = repo.retrieveAtom(pkg_id) exp_string = '' pkg_expired = entropy_server._is_match_expired( (pkg_id, pkg_repo,)) if pkg_expired: exp_string = "|%s" % (purple(_("expired")),) entropy_server.output( "[%s%s] %s" % ( blue(pkg_repo), exp_string, darkred(atom),), header=brown(" # ")) def asker(package_match): pkg_id, pkg_repo = package_match show_rm(pkg_id, pkg_repo) rc = entropy_server.ask_question( _("Remove this package?")) return rc == _("Yes") if self._interactive: entropy_server.output( blue(_("Select packages for removal")), header=brown(" @@ ")) package_matches = list(filter(asker, package_matches)) if not package_matches: return entropy_server.output( blue(_("These would be removed from repository")), header=brown(" @@ ")) for package_id, repository_id in package_matches: show_rm(package_id, repository_id) if self._ask: rc = entropy_server.ask_question( _("Would you like to remove them now ?") ) if rc == _("No"): return remdata = {} for package_id, repository_id in package_matches: obj = remdata.setdefault(repository_id, set()) obj.add(package_id) for repository_id, packages in remdata.items(): entropy_server.remove_packages(repository_id, packages) entropy_server.commit_repositories()
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 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 action = darkgreen(_("Package download")) exit_st = self._show_packages_info( entropy_client, packages, deps, ask, pretend, verbose, quiet, action_name=action) if exit_st != 0: 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, True) if exit_st == 0: self._signal_ugc(entropy_client, down_data) return exit_st
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 _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 _connect(self): """ Connect to FTP host. """ timeout = self._timeout if timeout is None: # default timeout set to 60 seconds timeout = EntropyFtpUriHandler._DEFAULT_TIMEOUT count = 10 while True: count -= 1 try: self.__ftpconn = self.ftplib.FTP() self.__ftpconn.connect(self.__ftphost, self.__ftpport, timeout) break except (socket.gaierror,) as e: raise TransceiverConnectionError(repr(e)) except (socket.error,) as e: if not count: raise TransceiverConnectionError(repr(e)) except: if not count: raise if self._verbose: mytxt = _("connecting with user") self.output( "[ftp:%s] %s: %s" % ( darkgreen(self.__ftphost), mytxt, blue(self.__ftpuser), ), importance = 1, level = "info", header = darkgreen(" * ") ) try: self.__ftpconn.login(self.__ftpuser, self.__ftppassword) except self.ftplib.error_perm as e: raise TransceiverConnectionError(repr(e)) if self._verbose: mytxt = _("switching to") self.output( "[ftp:%s] %s: %s" % ( darkgreen(self.__ftphost), mytxt, blue(self.__ftpdir), ), importance = 1, level = "info", header = darkgreen(" * ") ) # create dirs if they don't exist self._set_cwd(self.__ftpdir, dodir = True) self.__connected = True
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 _unused(self, entropy_client): """ Command implementation. """ if not self._quiet: entropy_client.output( "%s..." % ( blue(_("Running unused packages test, " "pay attention, there can be false positives")),), header=red(" @@ ")) installed_repo = entropy_client.installed_repository() def _unused_packages_test(): return [x for x in installed_repo.retrieveUnusedPackageIds() \ if entropy_client.validate_package_removal(x)] data = [(installed_repo.retrieveOnDiskSize(x), x, \ installed_repo.retrieveAtom(x),) for x in \ _unused_packages_test()] def _user_filter(item): _size, _pkg_id, _atom = item _source = installed_repo.getInstalledPackageSource(_pkg_id) if _source == etpConst['install_sources']['user']: # remove from list, user installed stuff not going # to be listed return False return True # filter: --by-user not provided -> if package has been installed # by user, exclude from list. if not self._byuser: data = list(filter(_user_filter, data)) if self._sortbysize: data.sort(key = lambda x: x[0]) if self._quiet: entropy_client.output( '\n'.join([x[2] for x in data]), level="generic") else: for disk_size, idpackage, atom in data: disk_size = entropy.tools.bytes_into_human(disk_size) entropy_client.output( "# %s%s%s %s" % ( blue("["), brown(disk_size), blue("]"), darkgreen(atom),)) 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 _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 _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 _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 _delete(self, entropy_server): """ Actual Eit key delete code. """ repo_sec = self._get_gpg(entropy_server) if repo_sec is None: return 1 repo = entropy_server.repository() entropy_server.output("%s: %s" % ( blue(_("Deleting keys for repository")), purple(repo),)) if not repo_sec.is_keypair_available(repo): entropy_server.output("%s: %s" % ( blue(_("No keys available for given repository")), purple(repo), ), level = "warning" ) return 0 answer = entropy_server.ask_question(_("Are you really sure?")) if answer == _("No"): return 1 try: key_meta = repo_sec.get_key_metadata(repo) except KeyError: entropy_server.output("%s: %s" % ( darkgreen(_("Keys metadata not available for")), bold(repo), ), level = "error" ) return 1 # remove signatures from repository database dbconn = entropy_server.open_server_repository( repo, read_only = False) dbconn.dropGpgSignatures() repo_sec.delete_keypair(repo) entropy_server.output("%s: %s" % ( darkgreen(_("Deleted GPG key with fingerprint")), bold(key_meta['fingerprint']), ), level = "info" ) 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 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 _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_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_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 _list(self, entropy_server): """ List Available Repositories. """ repositories = entropy_server.repositories() default_repo = entropy_server.repository() for repository_id in repositories: repo_class = entropy_server.get_repository(repository_id) if repo_class == InstalledPackagesRepository: continue default_str = "" if repository_id == default_repo: default_str = " (%s)" % (purple("*"), ) meta = entropy_server.repository_metadata(repository_id) description = meta['description'] repo_mirrors = meta['repo_mirrors'] pkg_mirrors = meta['pkg_mirrors'] entropy_server.output("%s [%s]%s" % ( teal(repository_id), darkgreen(description), default_str, )) for repo_mirror in repo_mirrors: entropy_server.output(" %s: %s" % ( blue(_("repository")), brown(repo_mirror), )) for pkg_mirror in pkg_mirrors: entropy_server.output(" %s: %s" % ( blue(_("packages")), brown(pkg_mirror), )) return 0
def _disable(self, entropy_client): """ Solo Repo Disable command. """ exit_st = 0 settings = entropy_client.Settings() excluded_repos = settings['repositories']['excluded'] available_repos = settings['repositories']['available'] for repo in self._nsargs.repo: if repo in excluded_repos: entropy_client.output("[%s] %s" % ( purple(repo), blue(_("repository already disabled")), ), level="warning", importance=1) exit_st = 1 continue if repo not in available_repos: entropy_client.output("[%s] %s" % ( purple(repo), blue(_("repository not available")), ), level="warning", importance=1) exit_st = 1 continue _exit_st = self._disable_repo(entropy_client, repo) if _exit_st != 0: exit_st = _exit_st return exit_st
def show_rm(pkg_id, pkg_repo): repo = entropy_server.open_repository(pkg_repo) atom = repo.retrieveAtom(pkg_id) exp_string = '' pkg_expired = entropy_server._is_match_expired( (pkg_id, pkg_repo,)) if pkg_expired: exp_string = "|%s" % (purple(_("expired")),) entropy_server.output( "[%s%s] %s" % ( blue(pkg_repo), exp_string, darkred(atom),), header=brown(" # "))
def _remove(self, entropy_server): """ Eit Repo Remove command. """ current_repos = entropy_server.repositories() exit_st = 0 for repository_id in self._nsargs.id: if repository_id not in current_repos: entropy_server.output("[%s] %s" % ( purple(repository_id), blue(_("repository not available")), ), level="warning", importance=1) exit_st = 1 continue parser = RepositoryConfigParser() removed = parser.remove(repository_id) if not removed: exit_st = 1 entropy_server.output("[%s] %s" % ( purple(repository_id), blue(_("cannot remove repository")), ), level="warning", importance=1) else: entropy_server.output("[%s] %s" % ( purple(repository_id), blue(_("repository removed succesfully")), )) return exit_st
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 show_download_summary(down_list): 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" % ( mirrorcount, brown(basef), blue("@"), red(self._get_url_name(best_mirror)), ) self._entropy.output(txt, importance=1, level="info", header=red(" ## "))
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 _config_phase_unlocked(self, inst_repo): """ _config_phase(), assuming that the installed packages repository lock is held. """ if not inst_repo.isPackageIdAvailable(self._package_id): self._entropy.output( darkred(_("The requested package is no longer available.")), importance = 1, level = "error", header = red(" ## ") ) return 3 metadata = {} metadata['atom'] = inst_repo.retrieveAtom(self._package_id) key, slot = inst_repo.retrieveKeySlot(self._package_id) metadata['key'], metadata['slot'] = key, slot metadata['version'] = inst_repo.retrieveVersion(self._package_id) metadata['category'] = inst_repo.retrieveCategory(self._package_id) metadata['name'] = inst_repo.retrieveName(self._package_id) metadata['spm_repository'] = inst_repo.retrieveSpmRepository( self._package_id) metadata['accept_license'] = self._get_licenses( inst_repo, self._package_id) xterm_title = "%s %s: %s" % ( self._xterm_header, _("Configuring package"), metadata['atom'], ) self._entropy.set_title(xterm_title) txt = "%s: %s" % ( blue(_("Configuring package")), red(metadata['atom']), ) self._entropy.output( txt, importance = 1, level = "info", header = red(" ## ") ) return self._configure_package_unlocked(metadata)
def _test(self, entropy_client): """ Command implementation. """ entropy_client.output("%s..." % (blue(_("Running dependency test")), ), header=darkred(" @@ ")) inst_repo = entropy_client.installed_repository() with inst_repo.shared(): not_found_deps, crying_atoms, found_deps = self._test_installed( entropy_client, inst_repo) if not not_found_deps: entropy_client.output(darkgreen(_("No missing dependencies")), header=darkred(" @@ ")) return 0 entropy_client.output( "%s:" % (blue(_("These are the dependencies not found")), ), header=darkred(" @@ ")) for atom in not_found_deps: entropy_client.output(darkred(atom), header=" # ") if atom in crying_atoms: entropy_client.output("%s:" % (darkred(_("Needed by")), ), header=blue(" # ")) for x in crying_atoms[atom]: entropy_client.output(darkgreen(x), header=blue(" # ")) if self._ask: rc = entropy_client.ask_question( " %s" % (_("Would you like to install the packages ?"), )) if rc == _("No"): return 1 else: mytxt = "%s %s %s" % ( blue(_("Installing available packages in")), darkred(_("10 seconds")), blue("..."), ) entropy_client.output(mytxt, header=darkred(" @@ ")) time.sleep(10) exit_st, _show_cfgupd = self._install_action( entropy_client, True, True, self._pretend, self._ask, False, self._quiet, False, False, False, False, False, False, False, 1, sorted(found_deps)) return exit_st
def __set_cwd(self, mydir, dodir=False): if self._verbose: mytxt = _("switching to") self.output("[ftp:%s] %s: %s" % ( darkgreen(self.__ftphost), mytxt, blue(mydir), ), importance=1, level="info", header=darkgreen(" * ")) try: self.__ftpconn.cwd(mydir) except self.ftplib.error_perm as e: if e[0][:3] == '550' and dodir: self.makedirs(mydir) self.__ftpconn.cwd(mydir) else: raise self.__currentdir = self._get_cwd()
def print_repository_status(entropy_server, repository_id): remote_db_status = entropy_server.Mirrors.remote_repository_status( repository_id) entropy_server.output("%s:" % (brown(_("Entropy Repository Status")), ), importance=1, header=darkgreen(" * ")) for url, revision in remote_db_status.items(): host = EntropyTransceiver.get_uri_name(url) entropy_server.output("%s: %s" % (darkgreen(_("Host")), bold(host)), header=" ") entropy_server.output("%s: %s" % (purple(_("Remote")), blue(str(revision))), header=" ") local_revision = entropy_server.local_repository_revision( repository_id) entropy_server.output("%s: %s" % (brown(_("Local")), teal(str(local_revision))), header=" ")
def _show_package_dependencies(self, entropy_server, atom, orig_deps, orig_conflicts, 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(" # ")) for dep_str in orig_conflicts: entropy_server.output("[%s] %s" % (teal(_("conflict")), purple(dep_str)), header=brown(" #")) if not orig_conflicts: entropy_server.output(_("No conflicts"), header=brown(" # ")) if orig_deps: self._show_dependencies_legend(entropy_server, " ") if partial: entropy_server.output("")
def show_download_error(down_list, p_exit_st): for _pkg_id, repository_id, _fname, _cksum, _signs in down_list: best_mirror = get_best_mirror(repository_id) mirrorcount = repo_uris[repository_id].index(best_mirror) + 1 txt = "( mirror #%s ) %s: %s" % ( mirrorcount, blue(_("Error downloading from")), red(self._get_url_name(best_mirror)), ) if p_exit_st == -1: txt += " - %s." % ( _("data not available on this mirror"),) elif p_exit_st == -2: mirror_status.add_failing_mirror(best_mirror, 1) txt += " - %s." % (_("wrong checksum"),) elif p_exit_st == -3: txt += " - %s." % (_("not found"),) elif p_exit_st == -4: # timeout! txt += " - %s." % (_("timeout error"),) elif p_exit_st == -100: txt += " - %s." % (_("discarded download"),) else: mirror_status.add_failing_mirror(best_mirror, 5) txt += " - %s." % (_("unknown reason"),) self._entropy.output( txt, importance = 1, level = "warning", header = red(" ## ") )
def go(self): broken_uris = set() fine_uris = set() errors = False action = 'push' if self.download: action = 'pull' elif self.remove: action = 'remove' for uri in self.uris: crippled_uri = EntropyTransceiver.get_uri_name(uri) self._entropy.output("[%s|%s] %s..." % ( blue(crippled_uri), brown(action), blue(_("connecting to mirror")), ), importance=0, level="info", header=blue(" @@ ")) self._entropy.output("[%s|%s] %s %s..." % ( blue(crippled_uri), brown(action), blue(_("setting directory to")), darkgreen(self.txc_basedir), ), importance=0, level="info", header=blue(" @@ ")) fail, fine, broken = self._transceive(uri) fine_uris |= fine broken_uris |= broken if fail: errors = True return errors, fine_uris, broken_uris
def _selaction(self, entropy_client): entropy_client.output( darkred( _("Please choose an action to take for" " the selected file."))) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("-1")), darkgreen(_("Come back to the files list")), )) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("1")), brown(_("Replace original with update")), )) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("2")), darkred(_("Delete update, keeping original as is")), )) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("3")), brown(_("Edit proposed file and show diffs again")), )) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("4")), brown(_("Interactively merge original with update")), )) entropy_client.output(" (%s) %s" % ( blue(const_convert_to_unicode("5")), darkred(_("Show differences again")), )) # wait user interaction try: action = readtext( _("Your choice (type a number and press enter):") + " ") except EOFError: action = None return action
def _oscheck(self, entropy_client): """ Solo Security Oscheck command. """ mtime = self._nsargs.mtime assimilate = self._nsargs.assimilate reinstall = self._nsargs.reinstall verbose = self._nsargs.verbose quiet = self._nsargs.quiet ask = self._nsargs.ask pretend = self._nsargs.pretend fetch = self._nsargs.fetch if not quiet: entropy_client.output( "%s..." % ( blue(_("Checking system files")),), header=darkred(" @@ ")) inst_repo = entropy_client.installed_repository() with inst_repo.shared(): faulty_pkg_ids = self._oscheck_scan_unlocked( entropy_client, inst_repo, quiet, verbose, assimilate) if not faulty_pkg_ids: if not quiet: entropy_client.output( darkgreen(_("No altered files found")), header=darkred(" @@ ")) return 0 rc = 0 if faulty_pkg_ids: rc = 10 valid_matches = set() if reinstall and faulty_pkg_ids: for pkg_id in faulty_pkg_ids: key_slot = inst_repo.retrieveKeySlotAggregated(pkg_id) package_id, repository_id = entropy_client.atom_match( key_slot) if package_id != -1: valid_matches.add((package_id, repository_id)) if valid_matches: rc, _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)) if not quiet: entropy_client.output( purple(_("Altered files have been found")), header=darkred(" @@ ")) if reinstall and (rc == 0) and valid_matches: entropy_client.output( purple(_("Packages have been " "reinstalled successfully")), header=darkred(" @@ ")) return rc
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 _generate_install_queue(self, entropy_client, packages, deps, empty, deep, relaxed, onlydeps, bdeps, recursive): """ Generate a complete installation queue. """ run_queue = [] removal_queue = [] if not deps: run_queue += packages[:] return run_queue, removal_queue entropy_client.output("%s..." % (blue(_("Calculating dependencies")), ), header=darkred(" @@ ")) try: run_queue, removal_queue = \ entropy_client.get_install_queue( packages, empty, deep, relaxed=relaxed, build=bdeps, recursive=recursive, only_deps=onlydeps) except DependenciesNotFound as exc: run_deps = exc.value entropy_client.output("%s:" % (blue(_("Dependencies not found")), ), header=darkred(" @@ "), level="error") for package in run_deps: self._show_masked_package_info(entropy_client, package, from_user=False) return None, None except DependenciesCollision as exc: col_deps, pkg_revdeps = exc.value entropy_client.output( "%s:" % (blue(_("Conflicting packages were pulled in")), ), header=darkred(" @@ "), level="error") # run_queue is a list of sets entropy_client.output("", level="warning") for pkg_matches in col_deps: for pkg_match in pkg_matches: pkg_id, pkg_repo = pkg_match repo = entropy_client.open_repository(pkg_repo) entropy_client.output("%s%s%s" % ( teal(repo.retrieveAtom(pkg_id)), darkred(etpConst['entropyrepoprefix']), purple(pkg_repo), ), header=brown(" # "), level="warning") if not pkg_revdeps[pkg_match]: entropy_client.output( "(%s: %s)" % ( green(_("required by")), # Conflicting dependencies could have been # specified by user, in which case they were # not pulled in by anything. teal(_("(no reverse dependencies)")), ), header=blue(" "), level="info") continue for pkg_revdep in pkg_revdeps[pkg_match]: pkg_revdep_id, pkg_revdep_repo = pkg_revdep revdep_repo = \ entropy_client.open_repository(pkg_revdep_repo) entropy_client.output("(%s: %s%s%s)" % ( green(_("required by")), teal(revdep_repo.retrieveAtom(pkg_revdep_id)), darkred(etpConst['entropyrepoprefix']), purple(pkg_revdep_repo), ), header=blue(" "), level="info") entropy_client.output("", level="warning") entropy_client.output("%s: %s" % ( purple(_("Please mask conflicts using")), bold("equo mask <package>"), ), header=darkred(" @@ "), level="error") return None, None return run_queue, removal_queue
def _generate_install_queue(self, entropy_client, packages, deps, empty, deep, relaxed, onlydeps, bdeps, recursive): """ Generate a complete installation queue. """ run_queue = [] removal_queue = [] if not deps: run_queue += packages[:] return run_queue, removal_queue entropy_client.output("%s..." % (blue(_("Calculating dependencies")), ), header=darkred(" @@ ")) try: run_queue, removal_queue = \ entropy_client.get_install_queue( packages, empty, deep, relaxed=relaxed, build=bdeps, recursive=recursive, only_deps=onlydeps) except DependenciesNotFound as exc: run_deps = exc.value entropy_client.output("%s:" % (blue(_("Dependencies not found")), ), header=darkred(" @@ "), level="error") for package in run_deps: self._show_masked_package_info(entropy_client, package, from_user=False) return None, None except DependenciesCollision as exc: col_deps = exc.value entropy_client.output( "%s:" % (blue(_("Conflicting packages were pulled in")), ), header=darkred(" @@ "), level="error") # run_queue is a list of sets entropy_client.output("", level="warning") for pkg_matches in col_deps: for pkg_id, pkg_repo in pkg_matches: repo = entropy_client.open_repository(pkg_repo) entropy_client.output(teal(repo.retrieveAtom(pkg_id)), header=brown(" # "), level="warning") entropy_client.output("", level="warning") entropy_client.output("%s: %s" % ( purple(_("Please mask conflicts using")), bold("equo mask <package>"), ), header=darkred(" @@ "), level="error") return None, None return run_queue, removal_queue
def _accept_license(entropy_client, inst_repo, package_matches): """ Prompt user licenses to accept. """ 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 _get_license_text(license_name, repository_id): repo = entropy_client.open_repository(repository_id) text = repo.retrieveLicenseText(license_name) tmp_fd, tmp_path = const_mkstemp(prefix="LICENSES.") # text is binary string, do not use codecs.open() with os.fdopen(tmp_fd, "wb") as tmp_f: tmp_f.write(text) return tmp_path # before even starting the fetch, make sure # that the user accepts their licenses licenses = entropy_client.get_licenses_to_accept(package_matches) # ACCEPT_LICENSE env var support accept_license = os.getenv("ACCEPT_LICENSE", "").split() if "*" in accept_license: licenses.clear() else: for mylic in accept_license: licenses.pop(mylic, None) if licenses: entropy_client.output( "%s:" % (blue(_("You need to accept the licenses below")), ), header=darkred(" @@ ")) for key in sorted(licenses.keys()): entropy_client.output( "%s: %s, %s:" % (darkred(_("License")), bold(key), darkred(_("needed by"))), header=" :: ") for package_id, repository_id in licenses[key]: repo = entropy_client.open_repository(repository_id) atom = repo.retrieveAtom(package_id) entropy_client.output("[%s:%s] %s" % ( brown(_("from")), darkred(repository_id), bold(atom), ), header=blue(" # ")) while True: action = _read_lic_selection() if action is None: # interpret EOF as "reject" return 1 try: choice = int(action) except (ValueError, TypeError): continue if choice not in (0, 1, 2, 3): continue if choice == 0: return 1 elif choice == 1: # read # pick one repository and read license text # from there. lic_repository_id = None for package_id, repository_id in licenses[key]: repo = entropy_client.open_repository(repository_id) if repo.isLicenseDataKeyAvailable(key): lic_repository_id = repository_id break if lic_repository_id is None: entropy_client.output( "%s!" % (brown(_("No license data available")), )) continue filename = _get_license_text(key, lic_repository_id) viewer = os.getenv("PAGER", "") viewer_args = shlex.split(viewer) if not viewer_args: entropy_client.output( "%s ! %s %s" % (brown(_("No file viewer")), darkgreen(_("License saved into")), filename)) continue subprocess.call(viewer_args + [filename]) try: os.remove(filename) except OSError as err: if err.errno != errno.ENOENT: raise continue elif choice == 2: break elif choice == 3: inst_repo.acceptLicense(key) break return 0
def _document_rm(self, entropy_client): """ Solo Ugc Document Rm command. """ pkgkey = self._nsargs.pkgkey repository = self._nsargs.repo document_ids = self._nsargs.ids try: webserv = _get_service( entropy_client, repository, tx_cb = True) except WebService.UnsupportedService: entropy_client.output( "[%s] %s" % ( darkgreen(repository), blue(_("Repository does not " "support Entropy Services.")), ), level="warning", importance=1 ) return 1 entropy_client.output( "[%s] %s" % ( darkgreen(repository), blue(_("Documents removal")), ), header=bold(" @@ ") ) entropy_client.output( "[%s] %s:" % ( darkgreen(repository), blue(_("Please review your submission")), ), header=bold(" @@ ") ) entropy_client.output( " %s: %s" % ( darkred(_("Document identifiers")), blue(', '.join(document_ids)), ) ) rc = entropy_client.ask_question( _("Would you like to review them?")) if rc == _("Yes"): try: docs_map = webserv.get_documents_by_id(document_ids, cache = False) except WebService.WebServiceException as err: entropy_client.output( "%s: %s" % ( blue(_("UGC error")), err, ), level="error", importance=1 ) return 1 for pkgkey, doc in docs_map.items(): if doc is None: # doesn't exist continue self._show_document(entropy_client, doc, repository, pkgkey) rc = entropy_client.ask_question( _("Would you like to continue with the removal?")) if rc != _("Yes"): return 1 try: docs_map = webserv.get_documents_by_id(document_ids, cache = False) except WebService.WebServiceException as err: entropy_client.output( "%s: %s" % ( blue(_("UGC error")), err, ), level="error", importance=1 ) return 1 for identifier in document_ids: doc = docs_map[identifier] if doc is None: entropy_client.output( "%s: %s" % ( blue(_("UGC error")), _("cannot get the requested Document"), ), level="error", importance=1 ) continue try: docs_map = webserv.remove_document(identifier) except WebService.WebServiceException as err: entropy_client.output( "%s: %s" % ( blue(_("UGC error")), err, ), level="error", importance=1 ) continue entropy_client.output( "%s: %s" % ( blue(_("UGC status")), _("removed successfully"), ), level="error", importance=1 ) return 0
def _vote_add(self, entropy_client): """ Solo Ugc Vote Add command. """ pkgkey = self._nsargs.pkgkey repository = self._nsargs.repo try: webserv = _get_service( entropy_client, repository, tx_cb = True) except WebService.UnsupportedService: entropy_client.output( "[%s] %s" % ( darkgreen(repository), blue(_("Repository does not " "support Entropy Services.")), ), level="warning", importance=1 ) return 1 username = webserv.get_credentials() if username is None: entropy_client.output( "[%s] %s" % ( darkgreen(repository), blue(_("Not logged in, please login first.")), ), level="warning", importance=1 ) return 1 entropy_client.output( "[%s] %s" % ( purple(pkgkey), blue(_("add vote")), ), header=bold(" @@ ") ) def mycb(s): return s input_data = [ ('vote', darkred(_("Insert your vote (from 1 to 5)")), mycb, False)] data = entropy_client.input_box( blue(_("Entropy UGC vote submission")), input_data, cancel_button = True) if not data: return 1 elif not isinstance(data, dict): return 1 elif 'vote' not in data: return 1 elif not data['vote']: return 1 try: vote = int(data['vote']) if vote not in ClientWebService.VALID_VOTES: raise ValueError() except ValueError: entropy_client.output( "[%s] %s: %s: %s" % ( darkred(pkgkey), blue(_("UGC error")), _("invalid vote, must be in range"), " ".join([str(x) for x in \ ClientWebService.VALID_VOTES]), ), level="error", importance=1 ) return 1 entropy_client.output( "[%s] %s:" % ( purple(pkgkey), blue(_("Please review your submission")), ), header=bold(" @@ ") ) entropy_client.output( "%s: %s" % ( darkred(_("Vote")), blue(const_convert_to_unicode(vote)), ), header=" " ) rc = entropy_client.ask_question( _("Do you want to submit?")) if rc != _("Yes"): return 1 try: voted = webserv.add_vote(pkgkey, vote, clear_available_cache = True) except WebService.WebServiceException as err: entropy_client.output( "[%s] %s: %s" % ( darkred(pkgkey), blue(_("UGC error")), err, ), level="error", importance=1 ) return 1 if not voted: entropy_client.output( "[%s] %s: %s" % ( darkred(pkgkey), blue(_("UGC error")), _("already voted"), ), level="error", importance=1 ) return 1 else: entropy_client.output("[%s] %s" % ( purple(pkgkey), blue(_("vote added, thank you!")), ) ) self._vote_get(entropy_client) return 0
def _document_get(self, entropy_client): """ Solo Ugc Document Get command. """ pkgkey = self._nsargs.pkgkey repository = self._nsargs.repo try: webserv = _get_service( entropy_client, repository, tx_cb = True) except WebService.UnsupportedService: entropy_client.output( "[%s] %s" % ( darkgreen(repository), blue(_("Repository does not " "support Entropy Services.")), ), level="warning", importance=1 ) return 1 docs = [] docs_offset = 0 while True: try: docs_list = webserv.get_documents([pkgkey], cache = False, offset = docs_offset)[pkgkey] except WebService.WebServiceException as err: entropy_client.output( "[%s] %s: %s" % ( darkred(pkgkey), blue(_("UGC error")), err, ), level="error", importance=1 ) return 1 if docs_list is None: entropy_client.output( "[%s] %s: NULL list" % ( darkred(pkgkey), blue(_("UGC error")), ), level="error", importance=1 ) return 1 docs.extend(docs_list) if not docs_list.has_more(): break docs_offset += len(docs_list) try: downloads = webserv.get_downloads( [pkgkey], cache = False)[pkgkey] except WebService.WebServiceException as err: entropy_client.output( "[%s] %s: %s" % ( darkred(pkgkey), blue(_("UGC error")), err, ), level="error", importance=1 ) return 1 for doc in docs: self._show_document(entropy_client, doc, repository, pkgkey) if docs: entropy_client.output( "%s: %s" % ( blue(_("Number of downloads")), downloads, ), header=darkred(" @@ ") ) else: entropy_client.output( blue(_("No User Generated Content available.")), header=darkred(" @@ ") ) return 0
def _show_masked_package_info(self, entropy_client, package, from_user=True): """ Show information about a masked package. """ def _find_belonging_dependency(package_atoms): crying_atoms = set() for atom in package_atoms: for repository_id in entropy_client.repositories(): repo = entropy_client.open_repository(repository_id) riddep = repo.searchDependency(atom) if riddep == -1: continue rpackage_ids = repo.searchPackageIdFromDependencyId(riddep) for i in rpackage_ids: i, r = repo.maskFilter(i) if i == -1: continue iatom = repo.retrieveAtom(i) crying_atoms.add((iatom, repository_id)) return crying_atoms def _get_masked_package_reason(match): package_id, repository_id = match repo = entropy_client.open_repository(repository_id) package_id, reason_id = repo.maskFilter(package_id) masked = False if package_id == -1: masked = True settings = entropy_client.Settings() return masked, reason_id, settings['pkg_masking_reasons'].get( reason_id) masked_matches = entropy_client.atom_match(package, mask_filter=False, multi_match=True) if masked_matches[1] == 0: mytxt = "%s %s %s." % ( # every package matching app-foo is masked darkred(_("Every package matching")), bold(package), darkred(_("is masked")), ) entropy_client.output(mytxt, header=bold(" !!! "), level="warning") m_reasons = {} for match in masked_matches[0]: masked, reason_id, reason = _get_masked_package_reason(match) if not masked: continue reason_obj = ( reason_id, reason, ) obj = m_reasons.setdefault(reason_obj, []) obj.append(match) for reason_id, reason in sorted(m_reasons.keys()): entropy_client.output( "%s: %s" % (blue(_("Masking reason")), darkgreen(reason)), header=bold(" # "), level="warning") for m_package_id, m_repo in m_reasons[(reason_id, reason)]: repo = entropy_client.open_repository(m_repo) try: m_atom = repo.retrieveAtom(m_package_id) except TypeError: m_atom = "package_id: %s %s %s %s" % ( m_package_id, _("matching"), package, _("is broken"), ) entropy_client.output("%s: %s %s %s" % (darkred(_("atom")), brown(m_atom), brown(_("in")), purple(m_repo)), header=blue(" <> "), level="warning") elif from_user: mytxt = "%s %s %s." % ( darkred(_("No match for")), bold(package), darkred(_("in repositories")), ) entropy_client.output(mytxt, header=bold(" !!! "), level="warning") if len(package) > 3: self._show_did_you_mean(entropy_client, package, False) else: entropy_client.output("%s: %s" % (blue(_("Not found")), brown(package)), header=darkred(" # "), level="error") crying_atoms = _find_belonging_dependency([package]) if crying_atoms: entropy_client.output("%s:" % (blue(_("package needed by"))), header=darkred(" # "), level="error") for c_atom, c_repo in crying_atoms: entropy_client.output( "[%s: %s] %s" % (blue(_("from")), brown(c_repo), darkred(c_atom)), header=darkred(" # "), level="error")
def _update(self, entropy_client, cmd=None): """ Solo Conf Enable command. """ docmd = False if cmd != None: docmd = True updates = entropy_client.ConfigurationUpdates() paths_map = {} first_pass = True while True: entropy_client.output("%s..." % (darkgreen(_("Scanning filesystem")), ), header=brown(" @@ ")) scandata = updates.get() if not scandata: entropy_client.output(teal(_("All fine baby. Nothing to do!"))) break root = scandata.root() if first_pass: paths_map.update(dict(enumerate(sorted(scandata.keys()), 1))) first_pass = False for idx in sorted(paths_map.keys()): x = paths_map[idx] try: obj = scandata[x] except KeyError: # duplicated entry? del paths_map[idx] continue file_path = root + obj['destination'] entropy_client.output("(%s) %s: %s" % (blue("%d" % (idx, )), darkgreen(_("file")), x)) if not paths_map: entropy_client.output(teal(_("All fine baby. Nothing to do!"))) break if not docmd: cmd = self._selfile(entropy_client) else: docmd = False try: cmd = int(cmd) except (ValueError, TypeError): entropy_client.output(_("Type a number"), level="error", importance=1) continue # actions if cmd == -1: # exit return -1 elif cmd in (-3, -5): # automerge files asking one by one self._automerge(cmd, entropy_client, root, paths_map, scandata) break elif cmd in (-7, -9): self._autodiscard(cmd, entropy_client, root, paths_map, scandata) break elif cmd > 0: if self._handle_command(cmd, entropy_client, root, paths_map, scandata): continue break
def _oscheck_scan_unlocked(self, entropy_client, inst_repo, quiet, verbose, assimilate): """ Execute the filesystem scan. """ pkg_ids = inst_repo.listAllPackageIds() total = len(pkg_ids) faulty_pkg_ids = [] for count, pkg_id in enumerate(pkg_ids, 1): pkg_atom = inst_repo.retrieveAtom(pkg_id) sts_txt = "%s%s/%s%s %s" % ( blue("["), darkgreen(str(count)), purple(str(total)), blue("]"), brown(pkg_atom)) if not quiet: entropy_client.output( sts_txt, header=blue(" @@ "), back=True) cont_s = inst_repo.retrieveContentSafety(pkg_id) if not cont_s: if not quiet and verbose: entropy_client.output( "%s: %s" % ( brown(pkg_atom), _("no checksum information"),), header=darkred(" @@ ")) # if pkg provides content! continue paths_tainted = [] paths_unavailable = [] for path, safety_data in cont_s.items(): tainted = False mtime = None sha256 = None if not os.path.lexists(path): # file does not exist # NOTE: current behaviour is to ignore # file not available # this might change in future. paths_unavailable.append(path) continue elif not mtime: # verify sha256 sha256 = entropy.tools.sha256(path) tainted = sha256 != safety_data['sha256'] if tainted: cont_s[path]['sha256'] = sha256 else: # verify mtime mtime = os.path.getmtime(path) tainted = mtime != safety_data['mtime'] if tainted: cont_s[path]['mtime'] = mtime if assimilate: if mtime is None: cont_s[path]['mtime'] = os.path.getmtime(path) elif sha256 is None: cont_s[path]['sha256'] = entropy.tools.sha256(path) if tainted: paths_tainted.append(path) if paths_tainted: faulty_pkg_ids.append(pkg_id) paths_tainted.sort() if not quiet: entropy_client.output( "%s: %s" % ( teal(pkg_atom), _("found altered files"),), header=darkred(" @@ ")) for path in paths_tainted: if quiet: entropy_client.output( path, level="generic") else: txt = " %s" % (purple(path),) entropy_client.output( purple(path), header=" ") if assimilate: if not quiet: entropy_client.output( "%s, %s" % ( sts_txt, teal(_("assimilated new " "hashes and mtime"))), header=blue(" @@ ")) inst_repo.setContentSafety(pkg_id, cont_s) if paths_unavailable: paths_unavailable.sort() if not quiet and verbose: for path in paths_unavailable: txt = " %s [%s]" % ( teal(path), purple(_("unavailable")) ) entropy_client.output(txt) return faulty_pkg_ids
def _print_advisory_information(self, entropy_client, advisory_data, key): """ Print Security Advisory. """ toc = [] # print advisory code toc.append( blue(" @@ ") + \ red("%s " % (_("Advisory Identifier"),)) + bold(key) + \ red(" | ")+blue(advisory_data['url'])) # title toc.append((darkgreen(" %s:" % (_("Title"),)), darkred(advisory_data['title']))) # description description = advisory_data['description'].split("\n") desc_text = darkgreen(" %s:" % (_("Description"),) ) for x in description: toc.append((desc_text, x.strip())) desc_text = " " for item in advisory_data['description_items']: desc_text = " %s " % (darkred("(*)"),) count = 8 mystr = [] for word in item.split(): count -= 1 mystr.append(word) if count < 1: toc.append((" ", desc_text+' '.join(mystr))) desc_text = " " mystr = [] count = 8 if count < 8: toc.append((" ", desc_text+' '.join(mystr))) # background if advisory_data['background']: background = advisory_data['background'].split("\n") bg_text = darkgreen(" %s:" % (_("Background"),)) for x in background: toc.append((bg_text, purple(x.strip()))) bg_text = " " # access if advisory_data['access']: toc.append((darkgreen(" %s:" % (_("Exploitable"),)), bold(advisory_data['access']))) # impact if advisory_data['impact']: impact = advisory_data['impact'].split("\n") imp_text = darkgreen(" %s:" % (_("Impact"),)) for x in impact: toc.append((imp_text, brown(x.strip()))) imp_text = " " # impact type if advisory_data['impacttype']: toc.append((darkgreen(" %s:" % (_("Impact type"),)), bold(advisory_data['impacttype']))) # revised if advisory_data['revised']: toc.append((darkgreen(" %s:" % (_("Revised"),)), brown(advisory_data['revised']))) # announced if advisory_data['announced']: toc.append((darkgreen(" %s:" % (_("Announced"),)), brown(advisory_data['announced']))) # synopsis synopsis = advisory_data['synopsis'].split("\n") syn_text = darkgreen(" %s:" % (_("Synopsis"),)) for x in synopsis: toc.append((syn_text, x.strip())) syn_text = " " # references if advisory_data['references']: toc.append(darkgreen(" %s:" % (_("References"),))) for reference in advisory_data['references']: toc.append((" ", darkblue(reference))) # gentoo bugs if advisory_data['bugs']: toc.append(darkgreen(" %s:" % (_("Upstream bugs"),))) for bug in advisory_data['bugs']: toc.append((" ", darkblue(bug))) # affected if advisory_data['affected']: toc.append(darkgreen(" %s:" % (_("Affected"),))) for key in advisory_data['affected']: toc.append((" ", darkred(key))) affected_data = advisory_data['affected'][key][0] vul_vers = affected_data['vul_vers'] unaff_vers = affected_data['unaff_vers'] if vul_vers: toc.append((" ", brown("%s: " % ( _("vulnerable versions"),))+", ".join(vul_vers))) if unaff_vers: toc.append((" ", brown("%s: " % ( _("unaffected versions"),))+", ".join(unaff_vers))) # workaround workaround = advisory_data['workaround'].split("\n") if advisory_data['workaround']: work_text = darkgreen(" %s:" % (_("Workaround"),)) for x in workaround: toc.append((work_text, darkred(x.strip()))) work_text = " " # resolution if advisory_data['resolution']: res_text = darkgreen(" %s:" % (_("Resolution"),)) resolutions = advisory_data['resolution'] for resolution in resolutions: for x in resolution.split("\n"): toc.append((res_text, x.strip())) res_text = " " print_table(entropy_client, toc, cell_spacing=3)
def _document_add(self, entropy_client): """ Solo Ugc Document Add command. """ pkgkey = self._nsargs.pkgkey repository = self._nsargs.repo try: webserv = _get_service( entropy_client, repository, tx_cb = True) except WebService.UnsupportedService: entropy_client.output( "[%s] %s" % ( darkgreen(repository), blue(_("Repository does not " "support Entropy Services.")), ), level="warning", importance=1 ) return 1 username = webserv.get_credentials() if username is None: entropy_client.output( "[%s] %s" % ( darkgreen(repository), blue(_("Not logged in, please login first.")), ), level="error", importance=1 ) return 1 entropy_client.output( "[%s|%s] %s" % ( darkgreen(str(repository)), purple(str(pkgkey)), blue(_("Add document")), ), header=bold(" @@ ") ) valid_types = { ('c', _('text comment')): Document.COMMENT_TYPE_ID, ('o', _('icon')): Document.ICON_TYPE_ID, ('f', _('simple file')): Document.FILE_TYPE_ID, ('i', _('simple image')): Document.IMAGE_TYPE_ID, ('y', _('video')): Document.VIDEO_TYPE_ID, } upload_needed_types = [ Document.FILE_TYPE_ID, Document.IMAGE_TYPE_ID, Document.ICON_TYPE_ID, Document.VIDEO_TYPE_ID ] my_quick_types = [x[0] for x in valid_types] def mycb(s): return s def path_cb(s): return const_file_readable(s) def types_cb(s): return s in my_quick_types input_data = [ ('title', darkred(_("Insert document title")), mycb, False), ('description', darkred(_("Insert document description/comment")), mycb, False), ('keywords', darkred(_("Insert document's keywords (space separated)")), mycb, False), ('type', "%s [%s]" % (darkred(_("Choose document type")), ', '.join(["(%s) %s" % (brown(x[0]), darkgreen(x[1]),) \ for x in valid_types])), types_cb, False), ] data = entropy_client.input_box( blue(_("Entropy UGC document submission")), input_data, cancel_button = True) if not data: return 1 elif not isinstance(data, dict): return 1 doc_type = None for myshort, mylong in valid_types: if data['type'] == myshort: doc_type = (myshort, mylong) data['type'] = valid_types.get((myshort, mylong,)) break data['path'] = None if data['type'] in upload_needed_types: input_data = [('path', darkred(_("Insert document path")), path_cb, False)] u_data = entropy_client.input_box( blue(_("Entropy UGC document submission")), input_data, cancel_button = True) if not u_data: return 1 elif not isinstance(data, dict): return 1 data['path'] = u_data['path'] keywords = ', '.join(data['keywords'].split()) # verify entropy_client.output( "[%s] %s:" % ( purple(pkgkey), blue(_("Please review your submission")), ), header=bold(" @@ ") ) entropy_client.output( "%s: %s" % ( darkred(_("Title")), blue(data['title']), ), header=" " ) entropy_client.output( "%s: %s" % ( darkred(_("Description")), blue(data['description']), ), header=" " ) entropy_client.output( "%s: %s" % ( darkred(_("Keywords")), blue(keywords), ), header=" " ) if data['path'] != None: entropy_client.output( "%s: %s" % ( darkred(_("Document path")), blue(data['path']), ), header=" " ) entropy_client.output( "%s: (%s) %s" % ( darkred(_("Document type")), darkred(doc_type[0]), blue(doc_type[1]), ), header=" " ) rc = entropy_client.ask_question(_("Do you want to submit?")) if rc != _("Yes"): return 1 doc_factory = DocumentFactory(repository) doc = None doc_f = None doc_type = data['type'] try: if doc_type == Document.COMMENT_TYPE_ID: doc = doc_factory.comment(username, data['description'], data['title'], data['keywords']) elif doc_type == Document.ICON_TYPE_ID: doc_f = open(data['path'], "rb") doc = doc_factory.icon(username, doc_f, data['title'], data['description'], data['keywords']) elif doc_type == Document.FILE_TYPE_ID: doc_f = open(data['path'], "rb") doc = doc_factory.file(username, doc_f, data['title'], data['description'], data['keywords']) elif doc_type == Document.IMAGE_TYPE_ID: doc_f = open(data['path'], "rb") doc = doc_factory.image(username, doc_f, data['title'], data['description'], data['keywords']) elif doc_type == Document.VIDEO_TYPE_ID: doc_f = open(data['path'], "rb") doc = doc_factory.video(username, doc_f, data['title'], data['description'], data['keywords']) except AssertionError as err: entropy_client.output( "[%s] %s: %s" % ( darkred(pkgkey), blue(_("Invalid document")), err, ), level="error", importance=1 ) if doc_f is not None: doc_f.close() return 1 try: new_doc = webserv.add_document(pkgkey, doc) except WebService.WebServiceException as err: entropy_client.output( "[%s] %s: %s" % ( darkred(pkgkey), blue(_("UGC error")), err, ), level="error", importance=1 ) return 1 finally: if doc_f is not None: doc_f.close() entropy_client.output( "[%s|id:%s] %s" % ( purple(pkgkey), new_doc.document_id(), blue(_("Document added, thank you!")), ), header=bold(" @@ ") ) return 0
def _apply_source(self, entropy_client, inst_repo, source_key, packages, pretend, ignore_missing, multiple_versions): source = etpConst['install_sources'][source_key] reverse_install_sources = { 0: _("unknown"), 1: _("manual"), 2: _("dependency") } other_source = _("other") source_txt = reverse_install_sources.get(source, other_source) packages = entropy_client.packages_expand(packages) package_ids = {} allfound = True for package in packages: if package in package_ids: continue pkg_ids, _rc = inst_repo.atomMatch(package, multiMatch=multiple_versions) if not multiple_versions: pkg_ids = set([pkg_ids]) if _rc == 0: package_ids[package] = pkg_ids else: allfound = False entropy_client.output("!!! %s: %s %s." % ( purple(_("Warning")), teal(const_convert_to_unicode(package)), purple(_("is not installed")), )) if not allfound: entropy_client.output(darkred(_("Some packages were not found")), level="info" if ignore_missing else "error", importance=1) if not ignore_missing: return 1 for package in packages: if package not in package_ids: # Package was not found. continue for pkg_id in package_ids[package]: pkg_atom = inst_repo.retrieveAtom(pkg_id) current_source = inst_repo.getInstalledPackageSource(pkg_id) current_source_txt = reverse_install_sources.get( current_source, other_source) if current_source == source: txt = "%s: %s" % (brown(pkg_atom), _("no change")) entropy_client.output(txt, header=blue(" @@ ")) else: txt = "%s: %s => %s" % (brown(pkg_atom), current_source_txt, source_txt) entropy_client.output(txt, header=red(" !! ")) if not pretend: inst_repo.setInstalledPackageSource(pkg_id, source) return 0