265 lines
8.8 KiB
Python
Executable File
265 lines
8.8 KiB
Python
Executable File
#!/usr/bin/python2
|
|
import sys
|
|
sys.path.insert(0, '/usr/lib/entropy/libraries')
|
|
sys.path.insert(0, '/usr/lib/entropy/server')
|
|
sys.path.insert(0, '/usr/lib/entropy/client')
|
|
sys.path.insert(0, '../libraries')
|
|
sys.path.insert(0, '../server')
|
|
sys.path.insert(0, '../client')
|
|
|
|
import os
|
|
import subprocess
|
|
|
|
from entropy.const import etpUi, etpConst
|
|
from entropy.output import teal, purple, darkgreen, blue, brown, print_info, \
|
|
red, nocolor, print_warning, print_error
|
|
from entropy.exceptions import DependenciesNotRemovable
|
|
from entropy.i18n import _
|
|
from entropy.client.interfaces import Client
|
|
import entropy.dep
|
|
import entropy.tools
|
|
|
|
# equo modules
|
|
from text_query import print_package_info
|
|
from text_ui import install_packages
|
|
|
|
APP_NAME = os.path.basename(sys.argv[0])
|
|
KERNEL_BINARY_VIRTUAL = "virtual/linux-binary"
|
|
|
|
def _get_kernels(etp_client):
|
|
matches, x_rc = etp_client.atom_match(KERNEL_BINARY_VIRTUAL,
|
|
multi_match = True, multi_repo = True)
|
|
return matches, x_rc
|
|
|
|
def _remove_tag_from_slot(slot):
|
|
if not hasattr(entropy.dep, "remove_tag_from_slot"):
|
|
# backward compatibility
|
|
return slot[::-1].split(",", 1)[-1][::-1]
|
|
return entropy.dep.remove_tag_from_slot(slot)
|
|
|
|
def _get_target_tag(etp_client, kernel_match):
|
|
try:
|
|
matches = etp_client.get_reverse_queue([kernel_match],
|
|
recursive = False)
|
|
except DependenciesNotRemovable:
|
|
# wtf should not happen
|
|
raise
|
|
tags = set()
|
|
for pkg_id, pkg_repo in matches:
|
|
tag = etp_client.open_repository(pkg_repo).retrieveTag(pkg_id)
|
|
if tag:
|
|
tags.add(tag)
|
|
|
|
if tags:
|
|
tags = sorted(tags, reverse = True)
|
|
return tags.pop(0)
|
|
|
|
def _setup_kernel_symlink(target_tag):
|
|
eselect_exec = "/usr/bin/eselect"
|
|
if os.access(eselect_exec, os.X_OK):
|
|
subprocess.call((eselect_exec, "kernel", "set", target_tag))
|
|
|
|
def _guess_kernel_name(kernel_atom):
|
|
"""
|
|
This method takes advantage of Entropy kernel package info files available
|
|
at /etc/kernels/<pkg-name>-<pkg-ver>/ directory.
|
|
This function tries to read uname -r from the RELEASE_LEVEL file.
|
|
"""
|
|
namever = entropy.dep.remove_cat(kernel_atom)
|
|
kernel_meta_file = os.path.join("/etc/kernels", namever, "RELEASE_LEVEL")
|
|
if os.path.isfile(kernel_meta_file):
|
|
try:
|
|
with open(kernel_meta_file, "r") as km_f:
|
|
kernel_name = km_f.readline().strip()
|
|
if kernel_name:
|
|
return kernel_name
|
|
except (OSError, IOError):
|
|
return None
|
|
|
|
# removing and installing proprietary drivers might reset the selected
|
|
# OpenGL implementation
|
|
|
|
def _get_opengl_impl():
|
|
eselect_exec = "/usr/bin/eselect"
|
|
sts = 1
|
|
out = "xorg-x11"
|
|
if os.access(eselect_exec, os.X_OK) and not etpUi['pretend']:
|
|
sts, xout = entropy.tools.getstatusoutput("%s opengl show" % (
|
|
eselect_exec,))
|
|
if sts == 0:
|
|
out = xout
|
|
return out
|
|
|
|
def _set_opengl_impl(opengl):
|
|
eselect_exec = "/usr/bin/eselect"
|
|
if os.access(eselect_exec, os.X_OK):
|
|
args = (eselect_exec, "opengl", "set", opengl)
|
|
subprocess.call(args)
|
|
|
|
def _show_kernel_warnings(kernel_atom):
|
|
print_info("%s %s" % (purple(kernel_atom), teal(_("has been installed."))))
|
|
print_warning("%s: %s" % (red(_("Attention")),
|
|
brown(_("some external drivers cannot work across multiple kernels."))))
|
|
print_warning(darkgreen(_("Please reboot your computer now !")))
|
|
|
|
def _switch_kernel(args):
|
|
if not args:
|
|
print_error(brown(_("No kernel packages given")))
|
|
return 1
|
|
if len(args) > 1:
|
|
print_error(brown(_("More than one kernel package given")))
|
|
return 1
|
|
kernel_package = args.pop(0)
|
|
|
|
etp_client = None
|
|
acquired = False
|
|
try:
|
|
etp_client = Client()
|
|
acquired = entropy.tools.acquire_entropy_locks(etp_client)
|
|
if not acquired:
|
|
print_error(brown(_("Another Entropy is currently running.")))
|
|
return 1
|
|
|
|
pkg_id, pkg_repo = etp_client.atom_match(kernel_package)
|
|
if pkg_id == -1:
|
|
print_error("%s: %s" % (brown(_("Package does not exist")),
|
|
teal(kernel_package),))
|
|
return 1
|
|
kernel_matches, rc = _get_kernels(etp_client)
|
|
|
|
kernel_match = (pkg_id, pkg_repo)
|
|
if kernel_match not in kernel_matches:
|
|
print_error("%s: %s" % (brown(_("Not a kernel")),
|
|
teal(kernel_package),))
|
|
return 1
|
|
|
|
kernel_atom = etp_client.open_repository(pkg_repo).retrieveAtom(pkg_id)
|
|
# this can be None !
|
|
target_tag = _get_target_tag(etp_client, kernel_match)
|
|
|
|
inst_repo = etp_client.installed_repository()
|
|
latest_kernel, k_rc = inst_repo.atomMatch(KERNEL_BINARY_VIRTUAL)
|
|
installed_revdeps = []
|
|
if (latest_kernel != -1) and target_tag:
|
|
installed_revdeps = etp_client.get_removal_queue([latest_kernel],
|
|
recursive = False)
|
|
|
|
# only pull in packages that are installed at this time.
|
|
def _installed_pkgs_translator(inst_pkg_id):
|
|
if inst_pkg_id == latest_kernel:
|
|
# will be added later
|
|
return None
|
|
key, slot = inst_repo.retrieveKeySlot(inst_pkg_id)
|
|
target_slot = _remove_tag_from_slot(slot) + "," + target_tag
|
|
|
|
pkg_id, pkg_repo = etp_client.atom_match(key,
|
|
match_slot = target_slot)
|
|
if pkg_id == -1:
|
|
return None
|
|
return pkg_id, pkg_repo
|
|
|
|
matches = map(_installed_pkgs_translator, installed_revdeps)
|
|
matches = [x for x in matches if x is not None]
|
|
matches.append(kernel_match)
|
|
|
|
opengl = _get_opengl_impl()
|
|
rc, other = install_packages(
|
|
etp_client,
|
|
atomsdata = matches,
|
|
check_critical_updates = False
|
|
)
|
|
if (rc == 0) and (not etpUi['pretend']):
|
|
_set_opengl_impl(opengl)
|
|
if target_tag:
|
|
# if target_tag is None, we are unable to set the symlink
|
|
_setup_kernel_symlink(target_tag)
|
|
else:
|
|
# try to guess, sigh, for now
|
|
guessed_kernel_name = _guess_kernel_name(kernel_atom)
|
|
if guessed_kernel_name:
|
|
_setup_kernel_symlink(guessed_kernel_name)
|
|
_show_kernel_warnings(kernel_atom)
|
|
return rc
|
|
|
|
finally:
|
|
if acquired and (etp_client is not None):
|
|
entropy.tools.release_entropy_locks(etp_client)
|
|
if etp_client is not None:
|
|
etp_client.shutdown()
|
|
|
|
def _list_kernels(args):
|
|
etp_client = None
|
|
acquired = False
|
|
try:
|
|
etp_client = Client()
|
|
acquired = entropy.tools.acquire_entropy_locks(etp_client)
|
|
if not acquired:
|
|
print_error(brown(_("Another Entropy is currently running.")))
|
|
return 1
|
|
matches, rc = _get_kernels(etp_client)
|
|
if (rc != 0) or (not matches):
|
|
print_warning(_("No kernel packages found"))
|
|
return 1
|
|
|
|
key_sorter = lambda x: \
|
|
etp_client.open_repository(x[1]).retrieveAtom(x[0])
|
|
for pkg_id, pkg_repo in sorted(matches, key = key_sorter):
|
|
repo = etp_client.open_repository(pkg_repo)
|
|
print_package_info(pkg_id, etp_client, repo,
|
|
show_repo_if_quiet = True, extended = etpUi['verbose'],
|
|
quiet = etpUi['quiet'])
|
|
|
|
return 0
|
|
finally:
|
|
if acquired and (etp_client is not None):
|
|
entropy.tools.release_entropy_locks(etp_client)
|
|
if etp_client is not None:
|
|
etp_client.shutdown()
|
|
|
|
def _print_help(args):
|
|
print_info("%s - %s" % (blue(APP_NAME),
|
|
teal(_("Sabayon Linux Kernel Switcher BETA")),))
|
|
print_info(" %s:\t%s %s" % (purple(_("switch kernel")),
|
|
brown(APP_NAME), darkgreen("switch <kernel package>")))
|
|
print_info(" %s:\t%s %s" % (purple(_("list kernels")), brown(APP_NAME),
|
|
darkgreen("list"),))
|
|
print_info(" %s:\t\t%s %s" % (purple(_("this help")), brown(APP_NAME),
|
|
darkgreen("help")))
|
|
if not args:
|
|
return 1
|
|
return 0
|
|
|
|
args_map = {
|
|
'switch': _switch_kernel,
|
|
'list': _list_kernels,
|
|
'help': _print_help,
|
|
'__fallback__': _print_help,
|
|
}
|
|
|
|
argv = sys.argv[1:]
|
|
argv = []
|
|
for arg in sys.argv[1:]:
|
|
if arg == "--nocolor":
|
|
nocolor()
|
|
elif arg in ("--quiet", "-q"):
|
|
etpUi['quiet'] = True
|
|
elif arg in ("--verbose", "-v"):
|
|
etpUi['verbose'] = True
|
|
elif arg in ("--pretend", "-p"):
|
|
etpUi['pretend'] = True
|
|
elif arg in ("--ask", "-a"):
|
|
etpUi['ask'] = True
|
|
else:
|
|
argv.append(arg)
|
|
|
|
if not argv:
|
|
argv.append("help")
|
|
|
|
cmd, args = argv[0], argv[1:]
|
|
func = args_map.get(cmd, args_map.get("__fallback__"))
|
|
try:
|
|
rc = func(args)
|
|
except KeyboardInterrupt:
|
|
raise SystemExit(1)
|
|
raise SystemExit(rc)
|