Merge pull request #50 from Enlik/equo-mark

[solo.commands.mark] new command
This commit is contained in:
Ettore Di Giacinto
2018-08-04 23:00:31 +02:00
committed by GitHub
6 changed files with 333 additions and 6 deletions
+54
View File
@@ -0,0 +1,54 @@
equo-mark(1)
============
:man source: equo {equoversion}
:man manual: equo {equoversion}
NAME
----
equo-mark - set properties on installed packages
SYNOPSIS
--------
equo mark [-h] {auto,manual} ...
INTRODUCTION
------------
Set properties on installed packages
OPTIONS
-------
"equo mark" supports the following options which alters its behaviour.
OPTIONAL ARGUMENTS
~~~~~~~~~~~~~~~~~~
*--help*::
show this help message and exit
ACTION
~~~~~~
*auto*::
mark package as installed to satisfy a dependency
*manual*::
mark package as installed by user
AUTHORS
-------
Fabio Erculiani (lxnay@sabayon.org)
REPORTING BUGS
--------------
Report bugs to https://bugs.sabayon.org or directly to the author at
lxnay@sabayon.org.
SEE ALSO
--------
equo(1)
+9 -6
View File
@@ -68,6 +68,9 @@ COMMANDS
*lxnay*::
bow to lxnay
*mark*::
set properties on installed packages
*mask*::
mask one or more packages
@@ -117,7 +120,7 @@ COMMANDS
unmask one or more packages
*unusedpackages [unused]*::
look for unused packages (pay attention)
show unused packages (pay attention)
*update [up]*::
update repositories
@@ -145,9 +148,9 @@ lxnay@sabayon.org.
SEE ALSO
--------
equo-cache(1), equo-cleanup(1), equo-conf(1), equo-config(1), equo-deptest(1)
equo-download(1), equo-hop(1), equo-install(1), equo-libtest(1), equo-mask(1)
equo-match(1), equo-notice(1), equo-pkg(1), equo-preservedlibs(1), equo-query(1)
equo-remove(1), equo-repo(1), equo-rescue(1), equo-search(1), equo-security(1)
equo-source(1), equo-status(1), equo-ugc(1), equo-unmask(1), equo-unusedpackages(1)
equo-update(1), equo-upgrade(1)
equo-download(1), equo-hop(1), equo-install(1), equo-libtest(1), equo-mark(1)
equo-mask(1), equo-match(1), equo-notice(1), equo-pkg(1), equo-preservedlibs(1)
equo-query(1), equo-remove(1), equo-repo(1), equo-rescue(1), equo-search(1)
equo-security(1), equo-source(1), equo-status(1), equo-ugc(1), equo-unmask(1)
equo-unusedpackages(1), equo-update(1), equo-upgrade(1)
+241
View File
@@ -0,0 +1,241 @@
# -*- 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 solo.commands.descriptor import SoloCommandDescriptor
from 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"))
)
+12
View File
@@ -4772,6 +4772,18 @@ class EntropyRepositoryBase(TextInterface, EntropyRepositoryPluginStore):
"""
raise NotImplementedError()
def setInstalledPackageSource(self, package_id, source):
"""
Set package source. Please refer to I{getInstalledPackageSource()} for
more details about this field.
@param package_id: package indentifier
@type package_id: int
@param source: install source identified
@type slot: int
"""
raise NotImplementedError()
def dropInstalledPackageFromStore(self, package_id):
"""
Note: this is used by installed packages repository (also known as
+8
View File
@@ -5059,6 +5059,14 @@ class EntropySQLRepository(EntropyRepositoryBase):
return source[0]
return None
def setInstalledPackageSource(self, package_id, source):
"""
Reimplemented from EntropyRepositoryBase.
"""
self._cursor().execute("""
UPDATE installedtable SET source = ? WHERE idpackage = ?
""", (source, package_id,))
def dropInstalledPackageFromStore(self, package_id):
"""
Reimplemented from EntropyRepositoryBase.
+9
View File
@@ -2329,6 +2329,15 @@ class EntropySQLiteRepository(EntropySQLRepository):
del cached
return obj
def setInstalledPackageSource(self, package_id, source):
"""
Reimplemented from EntropySQLRepository.
We must handle live cache.
"""
super(EntropySQLiteRepository, self).setInstalledPackageSource(
package_id, source)
self._clearLiveCache("getInstalledPackageSource")
def dropInstalledPackageFromStore(self, package_id):
"""
Reimplemented from EntropySQLRepository.