7cf7e1f6b7
The module entropy_path_loader (used only for running from within the checkout; otherwise not even installed) is made to provide the _entropy namespace. (Other ideas instead of this entropy_path_loader change would be to reorganise files layout; drop support for running from the checkout as is - and perhaps require virtualenvs; require sourcing a script that sets PYTHONPATH. However, as implemented, it is not intrusive, and the good part is that it is quite isolated, not used in normal usage after installation. Basically, it only does sys.path + provides _entropy namespace.)
242 lines
7.4 KiB
Python
242 lines
7.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
|
|
@author: Slawomir Nizio <slawomir.nizio@sabayon.org>
|
|
@contact: lxnay@sabayon.org
|
|
@copyright: Slawomir Nizio
|
|
@license: GPL-2
|
|
|
|
B{Entropy Command Line Client}.
|
|
|
|
"""
|
|
import sys
|
|
import argparse
|
|
|
|
from entropy.i18n import _
|
|
from entropy.const import etpConst, const_convert_to_unicode
|
|
from entropy.output import darkred, red, blue, brown, teal, purple
|
|
|
|
from _entropy.solo.commands.descriptor import SoloCommandDescriptor
|
|
from _entropy.solo.commands.command import SoloCommand, exclusivelock
|
|
|
|
|
|
class SoloMark(SoloCommand):
|
|
"""
|
|
Main Solo Mark command.
|
|
"""
|
|
|
|
NAME = "mark"
|
|
ALIASES = []
|
|
ALLOW_UNPRIVILEGED = False
|
|
|
|
INTRODUCTION = """\
|
|
Set properties on installed packages
|
|
"""
|
|
SEE_ALSO = ""
|
|
|
|
def __init__(self, args):
|
|
SoloCommand.__init__(self, args)
|
|
self._commands = {}
|
|
|
|
def man(self):
|
|
"""
|
|
Overridden from SoloCommand.
|
|
"""
|
|
return self._man()
|
|
|
|
def _get_parser(self):
|
|
"""
|
|
Overridden from SoloCommand.
|
|
"""
|
|
_commands = {}
|
|
descriptor = SoloCommandDescriptor.obtain_descriptor(
|
|
SoloMark.NAME)
|
|
|
|
parser = argparse.ArgumentParser(
|
|
description=descriptor.get_description(),
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
prog="%s %s" % (sys.argv[0], SoloMark.NAME))
|
|
|
|
subparsers = parser.add_subparsers(
|
|
title="action",
|
|
description=_("specify property to mark on a package"),
|
|
help=_("available commands"))
|
|
|
|
def _add_standard_arguments(p, _cmd_dict):
|
|
p.add_argument(
|
|
"packages", nargs='+',
|
|
metavar="<package>", help=_("package name"))
|
|
|
|
p.add_argument(
|
|
"--pretend", "-p", action="store_true",
|
|
default=False,
|
|
help=_("show what would be done"))
|
|
_cmd_dict["--pretend"] = {}
|
|
_cmd_dict["-p"] = {}
|
|
|
|
p.add_argument(
|
|
"--ignore-missing", action="store_true",
|
|
default=False,
|
|
help=_("ignore packages that are not installed on system"))
|
|
_cmd_dict["--ignore-missing"] = {}
|
|
|
|
# It behaves differently than --multimatch from match.py,
|
|
# thus a different name.
|
|
p.add_argument(
|
|
"--multiple-versions", action="store_true",
|
|
default=False,
|
|
help=_("allow matching multiple versions of a package"))
|
|
_cmd_dict["--multiple-versions"] = {}
|
|
|
|
auto_parser = subparsers.add_parser(
|
|
"auto",
|
|
help=_("mark package as installed to satisfy a dependency"))
|
|
_cmd_dict = {}
|
|
_add_standard_arguments(auto_parser, _cmd_dict)
|
|
auto_parser.set_defaults(func=self._auto)
|
|
_commands["auto"] = _cmd_dict
|
|
|
|
manual_parser = subparsers.add_parser(
|
|
"manual",
|
|
help=_("mark package as installed by user"))
|
|
_cmd_dict = {}
|
|
_add_standard_arguments(manual_parser, _cmd_dict)
|
|
manual_parser.set_defaults(func=self._manual)
|
|
_commands["manual"] = _cmd_dict
|
|
|
|
self._commands = _commands
|
|
return parser
|
|
|
|
def parse(self):
|
|
"""
|
|
Parse command
|
|
"""
|
|
parser = self._get_parser()
|
|
try:
|
|
nsargs = parser.parse_args(self._args)
|
|
except IOError as err:
|
|
sys.stderr.write("%s\n" % (err,))
|
|
return parser.print_help, []
|
|
|
|
# Python 3.3 bug #16308
|
|
if not hasattr(nsargs, "func"):
|
|
return parser.print_help, []
|
|
|
|
self._nsargs = nsargs
|
|
return self._call_exclusive, [nsargs.func]
|
|
|
|
def bashcomp(self, last_arg):
|
|
"""
|
|
Overridden from SoloCommand.
|
|
"""
|
|
self._get_parser() # this will generate self._commands
|
|
return self._hierarchical_bashcomp(last_arg, [], self._commands)
|
|
|
|
@exclusivelock
|
|
def _auto(self, entropy_client, inst_repo):
|
|
source_key = "automatic_dependency"
|
|
return self._apply_source(
|
|
entropy_client, inst_repo, source_key, **self._get_opts())
|
|
|
|
@exclusivelock
|
|
def _manual(self, entropy_client, inst_repo):
|
|
source_key = "user"
|
|
return self._apply_source(
|
|
entropy_client, inst_repo, source_key, **self._get_opts())
|
|
|
|
def _get_opts(self):
|
|
opts = {
|
|
'packages': self._nsargs.packages,
|
|
'pretend': self._nsargs.pretend,
|
|
'ignore_missing': self._nsargs.ignore_missing,
|
|
'multiple_versions': self._nsargs.multiple_versions
|
|
}
|
|
return opts
|
|
|
|
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
|
|
|
|
SoloCommandDescriptor.register(
|
|
SoloCommandDescriptor(
|
|
SoloMark,
|
|
SoloMark.NAME,
|
|
_("set properties on installed packages"))
|
|
)
|