215 lines
7.1 KiB
Python
Executable File
215 lines
7.1 KiB
Python
Executable File
#!/usr/bin/python
|
|
import sys
|
|
import os
|
|
|
|
from os import path as osp
|
|
_base = osp.dirname(osp.dirname(osp.realpath(__file__)))
|
|
if os.path.isfile(osp.join(_base, "entropy-in-vcs-checkout")):
|
|
sys.path.insert(0, osp.join(_base, "entropy_path_loader"))
|
|
import entropy_path_loader
|
|
del osp
|
|
|
|
import argparse
|
|
import functools
|
|
|
|
from entropy.locks import EntropyResourcesLock
|
|
from entropy.output import brown, print_warning, print_error, teal
|
|
from entropy.i18n import _
|
|
from entropy.client.interfaces import Client
|
|
import entropy.dep
|
|
import entropy.tools
|
|
|
|
from _entropy.solo.commands.install import SoloInstall
|
|
from _entropy.solo.utils import print_package_info
|
|
|
|
import kswitch
|
|
|
|
|
|
class SabayonSwitcher(argparse.Namespace):
|
|
|
|
def __init__(self, app_name='kernel-switcher'):
|
|
argparse.Namespace.__init__(self)
|
|
self.quiet = False
|
|
self.verbose = False
|
|
self.ask = False
|
|
self.pretend = False
|
|
self.from_running = False
|
|
self.called_method = None
|
|
self.kernel = None
|
|
self._etp_client = None
|
|
|
|
self.parser = argparse.ArgumentParser(
|
|
description=_("Sabayon Kernel Switcher"),
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
prog=app_name
|
|
)
|
|
self.subparsers = self.parser.add_subparsers(
|
|
title=app_name,
|
|
description=_("available commands"))
|
|
|
|
self._add_switch_sub_command()
|
|
self._add_list_sub_command()
|
|
self._add_help_sub_command()
|
|
|
|
def _add_switch_sub_command(self):
|
|
switch_parser = self.subparsers.add_parser(
|
|
"switch", help=_("install a new or just another kernel"))
|
|
switch_parser.set_defaults(called_method=self._switch)
|
|
switch_parser.add_argument(
|
|
"--from-running", action="store_true",
|
|
default=False,
|
|
dest='from_running',
|
|
help=_("use 'uname -r' to determine the running kernel"))
|
|
switch_parser.add_argument(
|
|
"kernel", metavar="<kernel>",
|
|
help=_("the new kernel package dependency name"))
|
|
self._add_standard_args(switch_parser, False)
|
|
|
|
def _add_list_sub_command(self):
|
|
list_parser = self.subparsers.add_parser(
|
|
"list", help=_("list kernels"))
|
|
list_parser.set_defaults(called_method=self._list)
|
|
self._add_standard_args(list_parser, True)
|
|
|
|
def _add_help_sub_command(self):
|
|
help_parser = self.subparsers.add_parser(
|
|
"help", help=_("this help"))
|
|
help_parser.set_defaults(called_method=self._print_help)
|
|
|
|
def _print_help(self):
|
|
self.parser.print_help()
|
|
|
|
@staticmethod
|
|
def _add_standard_args(_parser, restricted):
|
|
_parser.add_argument("--quiet", "-q", action="store_true",
|
|
default=False,
|
|
help=_("quiet mode"))
|
|
_parser.add_argument("--verbose", "-v", action="store_true",
|
|
default=False,
|
|
help=_("verbose mode"))
|
|
if not restricted:
|
|
_parser.add_argument("--ask", "-a", action="store_true",
|
|
default=False,
|
|
help=_("ask confirmation"))
|
|
_parser.add_argument("--pretend", "-p", action="store_true",
|
|
default=False,
|
|
help=_("just show what would be done"))
|
|
|
|
def _wrap_locked_api(method):
|
|
@functools.wraps(method)
|
|
def wrapper(self, *method_args, **method_kwargs):
|
|
lock = EntropyResourcesLock(output=Client)
|
|
try:
|
|
lock.acquire_shared()
|
|
acquired = True
|
|
self._etp_client = Client()
|
|
ans = method(self, *method_args, **method_kwargs)
|
|
finally:
|
|
if self._etp_client is not None:
|
|
self._etp_client.shutdown()
|
|
self._etp_client = None
|
|
if acquired:
|
|
lock.release()
|
|
return ans
|
|
|
|
return wrapper
|
|
|
|
@_wrap_locked_api
|
|
def _switch(self):
|
|
def _install(etp_client, matches):
|
|
install = SoloInstall([])
|
|
inst_rc, _show_cfg_upd = install._install_action(
|
|
etp_client, True, True,
|
|
self.pretend, self.ask, self.verbose,
|
|
self.quiet, False, False, False, False, False,
|
|
False, False, 1, [], package_matches=list(matches))
|
|
if _show_cfg_upd:
|
|
install._show_config_files_update(etp_client)
|
|
install._show_preserved_libraries(etp_client)
|
|
if self.pretend:
|
|
# this won't trigger any post install action
|
|
return 1
|
|
return inst_rc
|
|
|
|
switcher = kswitch.KernelSwitcher(self._etp_client)
|
|
kernel_package = self.kernel
|
|
|
|
pkg_id, pkg_repo = self._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_match = (pkg_id, pkg_repo)
|
|
kernel_matches = switcher.list()
|
|
if kernel_match not in kernel_matches:
|
|
print_error(
|
|
"%s: %s" % (brown(_("Not a kernel")),
|
|
teal(kernel_package),))
|
|
return 1
|
|
|
|
try:
|
|
return switcher.switch(
|
|
kernel_match, _install,
|
|
from_running=self.from_running)
|
|
except kswitch.CannotFindRunningKernel:
|
|
print_error(
|
|
brown(_("Cannot find your currently running kernel.")))
|
|
print_error(
|
|
brown(_("Try without --from-running.")))
|
|
return 1
|
|
|
|
@_wrap_locked_api
|
|
def _list(self):
|
|
switcher = kswitch.KernelSwitcher(self._etp_client)
|
|
kernels = switcher.list()
|
|
if not kernels:
|
|
print_warning(_("No kernel packages found"))
|
|
return 1
|
|
|
|
inst_repo = self._etp_client.installed_repository()
|
|
with inst_repo.shared():
|
|
for pkg_id, pkg_repo in kernels:
|
|
|
|
repo = self._etp_client.open_repository(pkg_repo)
|
|
print_package_info(
|
|
pkg_id, self._etp_client, repo,
|
|
show_repo_if_quiet=True,
|
|
extended=self.verbose,
|
|
quiet=self.quiet)
|
|
return 0
|
|
|
|
def main(self, argv):
|
|
|
|
try:
|
|
self.parser.parse_args(argv[1:], namespace=self)
|
|
except IOError:
|
|
self.parser.print_help()
|
|
return 1
|
|
|
|
try:
|
|
if self.called_method is None:
|
|
self.parser.print_help()
|
|
rc = 1
|
|
elif self.called_method in (self._switch, self._list) and \
|
|
not entropy.tools.is_root():
|
|
print_error(
|
|
brown(_("superuser access required")))
|
|
rc = 1
|
|
else:
|
|
rc = self.called_method()
|
|
except KeyboardInterrupt:
|
|
rc = 1
|
|
return rc
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
app = SabayonSwitcher(
|
|
app_name=os.path.basename(sys.argv[0])
|
|
)
|
|
ret = app.main(sys.argv)
|
|
raise SystemExit(ret)
|
|
|