The old "dependencies" metadata is deprecated. It was found that the generated metadata might get corrupted by colliding atom strings. The new implementation avoids collisions completely and is more efficient.
252 lines
8.1 KiB
Python
252 lines
8.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
|
|
@author: Fabio Erculiani <lxnay@sabayon.org>
|
|
@contact: lxnay@sabayon.org
|
|
@copyright: Fabio Erculiani
|
|
@license: GPL-2
|
|
|
|
B{Entropy Infrastructure Toolkit}.
|
|
|
|
"""
|
|
import sys
|
|
import argparse
|
|
|
|
from entropy.i18n import _
|
|
from entropy.const import etpConst
|
|
from entropy.output import purple, darkgreen, brown, teal, blue
|
|
|
|
from eit.commands.descriptor import EitCommandDescriptor
|
|
from eit.commands.command import EitCommand
|
|
|
|
|
|
class EitDeps(EitCommand):
|
|
"""
|
|
Main Eit deps command.
|
|
"""
|
|
|
|
NAME = "deps"
|
|
ALIASES = []
|
|
|
|
def __init__(self, args):
|
|
EitCommand.__init__(self, args)
|
|
self._packages = []
|
|
|
|
def _get_parser(self):
|
|
descriptor = EitCommandDescriptor.obtain_descriptor(
|
|
EitDeps.NAME)
|
|
parser = argparse.ArgumentParser(
|
|
description=descriptor.get_description(),
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
prog="%s %s" % (sys.argv[0], EitDeps.NAME))
|
|
|
|
parser.add_argument("packages", nargs='+', metavar="<package>",
|
|
help=_("package name"))
|
|
parser.add_argument("--in", metavar="<repository>",
|
|
help=_("inject into given repository"),
|
|
dest="inrepo", default=None)
|
|
|
|
return parser
|
|
|
|
INTRODUCTION = """\
|
|
Through this tool it's possible to add, remove and edit dependencies of
|
|
any package.
|
|
This might be helpful for small tweaks or trivial changes in order to
|
|
avoid a complete repackage.
|
|
Please do not abuse it, package file metadata are not updated accordingly,
|
|
and the same is for Source Package Manager metadata.
|
|
Consider this a last resort for updating package dependencies in a
|
|
non-permanent way.
|
|
"""
|
|
|
|
def man(self):
|
|
"""
|
|
Overridden from EitCommand.
|
|
"""
|
|
return self._man()
|
|
|
|
def parse(self):
|
|
parser = self._get_parser()
|
|
try:
|
|
nsargs = parser.parse_args(self._args)
|
|
except IOError:
|
|
return parser.print_help, []
|
|
|
|
self._packages += nsargs.packages
|
|
return self._call_locked, [self._deps, nsargs.inrepo]
|
|
|
|
def _show_dependencies_legend(self, entropy_server, indent = None):
|
|
"""
|
|
Print dependency types legend.
|
|
"""
|
|
if indent is None:
|
|
indent = ""
|
|
dep_types = etpConst['dependency_type_ids']
|
|
dep_descs = etpConst['dependency_type_ids_desc']
|
|
|
|
for dep_id, dep_val in sorted(dep_types.items(),
|
|
key = lambda x: x[0], reverse = True):
|
|
dep_desc = dep_descs.get(dep_id, _("N/A"))
|
|
txt = '%s%s%s%s %s' % (
|
|
indent, teal("{"), dep_val+1, teal("}"), dep_desc,)
|
|
entropy_server.output(txt)
|
|
|
|
def _show_package_dependencies(self, entropy_server, atom,
|
|
orig_deps, 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(" # "))
|
|
else:
|
|
self._show_dependencies_legend(entropy_server, " ")
|
|
|
|
if partial:
|
|
entropy_server.output("")
|
|
|
|
def _deps(self, entropy_server):
|
|
"""
|
|
Actual Eit deps code.
|
|
"""
|
|
repository_id = entropy_server.repository()
|
|
|
|
# match
|
|
package_ids = []
|
|
for package in self._packages:
|
|
match = entropy_server.atom_match(
|
|
package, match_repo = [repository_id])
|
|
if match[1] == repository_id:
|
|
package_ids.append(match[0])
|
|
else:
|
|
entropy_server.output(
|
|
"[%s] %s %s" % (
|
|
purple(repository_id),
|
|
darkgreen(package),
|
|
teal(_("not found"))),
|
|
importance=1, level="warning")
|
|
if not package_ids:
|
|
entropy_server.output(
|
|
purple(_("No packages found")),
|
|
importance=1, level="error")
|
|
return 1
|
|
|
|
avail_dep_type_desc = []
|
|
d_type_ids = etpConst['dependency_type_ids']
|
|
d_type_desc = etpConst['dependency_type_ids_desc']
|
|
for dep_val, dep_id in sorted(d_type_ids.items(),
|
|
key = lambda x: x[1]):
|
|
avail_dep_type_desc.append(d_type_desc[dep_val])
|
|
|
|
def pkg_dep_types_cb(s):
|
|
try:
|
|
avail_dep_type_desc.index(s[1])
|
|
except IndexError:
|
|
return False
|
|
return True
|
|
|
|
repo = entropy_server.open_repository(repository_id)
|
|
for package_id in package_ids:
|
|
atom = repo.retrieveAtom(package_id)
|
|
orig_deps = repo.retrieveDependencies(
|
|
package_id, extended = True,
|
|
resolve_conditional_deps = False)
|
|
dep_type_map = dict(orig_deps)
|
|
|
|
def dep_check_cb(s):
|
|
input_params = [
|
|
('dep_type', ('combo', (_("Dependency type"),
|
|
avail_dep_type_desc),),
|
|
pkg_dep_types_cb, False)
|
|
]
|
|
|
|
data = entropy_server.input_box(
|
|
("%s: %s" % (_('Select a dependency type for'), s,)),
|
|
input_params
|
|
)
|
|
if data is None:
|
|
return False
|
|
|
|
rc_dep_type = avail_dep_type_desc.index(
|
|
data['dep_type'][1])
|
|
dep_type_map[s] = rc_dep_type
|
|
changes_made_type_map = {s: rc_dep_type}
|
|
|
|
self._show_package_dependencies(entropy_server,
|
|
atom, changes_made_type_map.items(), partial = True)
|
|
return True
|
|
|
|
self._show_package_dependencies(
|
|
entropy_server, atom, orig_deps)
|
|
|
|
entropy_server.output("")
|
|
current_deps = [x[0] for x in orig_deps]
|
|
input_params = [
|
|
('new_deps', ('list', (_('Dependencies'), current_deps),),
|
|
dep_check_cb, True)
|
|
]
|
|
data = entropy_server.input_box(
|
|
_("Dependencies editor"), input_params)
|
|
if data is None:
|
|
continue
|
|
|
|
new_deps = data.get('new_deps', [])
|
|
orig_deps = [(x, dep_type_map[x],) for x in new_deps]
|
|
|
|
self._show_package_dependencies(
|
|
entropy_server, atom, orig_deps)
|
|
rc_ask = entropy_server.ask_question(_("Confirm ?"))
|
|
if rc_ask == _("No"):
|
|
continue
|
|
|
|
w_repo = entropy_server.open_server_repository(
|
|
repository_id, read_only = False)
|
|
|
|
# save new dependencies
|
|
while True:
|
|
try:
|
|
w_repo.removeDependencies(package_id)
|
|
w_repo.insertDependencies(package_id, orig_deps)
|
|
w_repo.commit()
|
|
except (KeyboardInterrupt, SystemExit,):
|
|
continue
|
|
break
|
|
|
|
# now bump, this makes EAPI=3 differential db sync happy
|
|
old_pkg_data = w_repo.getPackageData(package_id)
|
|
w_repo.handlePackage(old_pkg_data)
|
|
|
|
entropy_server.output(
|
|
"%s: %s" % (
|
|
blue(atom),
|
|
darkgreen(_("dependencies updated successfully"))),
|
|
header=brown(" @@ "))
|
|
|
|
entropy_server.commit_repositories()
|
|
return 0
|
|
|
|
|
|
EitCommandDescriptor.register(
|
|
EitCommandDescriptor(
|
|
EitDeps,
|
|
EitDeps.NAME,
|
|
_('edit dependencies for packages in repository'))
|
|
)
|