Files
entropy/server/eit/commands/commit.py

366 lines
14 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 os
import argparse
from entropy.i18n import _
from entropy.output import darkgreen, teal, brown, \
darkred, bold, purple, blue, red
import entropy.tools
from eit.commands.descriptor import EitCommandDescriptor
from eit.commands.command import EitCommand
class EitCommit(EitCommand):
"""
Main Eit commit command.
"""
NAME = "commit"
ALIASES = ["ci"]
def __init__(self, args):
EitCommand.__init__(self, args)
# ask user before any critical operation
self._ask = True
# interactively ask for packages to be staged, etc
self._interactive = False
# list of package dependencies to re-package, if any
self._repackage = []
# execute actions only for given atoms, if any
self._packages = []
def parse(self):
descriptor = EitCommandDescriptor.obtain_descriptor(
EitCommit.NAME)
parser = argparse.ArgumentParser(
description=descriptor.get_description(),
formatter_class=argparse.RawDescriptionHelpFormatter,
prog="%s %s" % (sys.argv[0], EitCommit.NAME))
parser.add_argument("repo", nargs='?', default=None,
metavar="<repo>", help=_("repository"))
parser.add_argument("--interactive", action="store_true",
default=False,
help=_("selectively pick changes"))
parser.add_argument("--quick", action="store_true",
default=not self._ask,
help=_("no stupid questions"))
try:
nsargs = parser.parse_args(self._args)
except IOError as err:
return parser.print_help, []
self._interactive = nsargs.interactive
if not self._interactive:
self._ask = not nsargs.quick
return self._call_locked, [self._commit, nsargs.repo]
def _commit(self, entropy_server):
to_be_added = set()
to_be_removed = set()
to_be_injected = set()
key_sorter = lambda x: \
entropy_server.open_repository(x[1]).retrieveAtom(x[0])
repository_id = entropy_server.repository()
generated_packages = []
if self._repackage:
packages = []
dbconn = entropy_server.open_server_repository(
repository_id, read_only = True,
no_upload = True)
spm = entropy_server.Spm()
for item in self._repackage:
match = dbconn.atomMatch(item)
if match[0] == -1:
entropy_server.output(
red(_("Cannot match"))+" "+bold(item),
header=darkred(" !!! "),
importance=1,
level="warning")
else:
cat = dbconn.retrieveCategory(match[0])
name = dbconn.retrieveName(match[0])
version = dbconn.retrieveVersion(match[0])
spm_pkg = os.path.join(cat, name + "-" + version)
spm_build = \
spm.get_installed_package_build_script_path(
spm_pkg)
spm_pkg_dir = os.path.dirname(spm_build)
if os.path.isdir(spm_pkg_dir):
packages.append((spm_pkg, 0))
if packages:
to_be_added |= set(packages)
else:
entropy_server.output(
red(_("No valid packages to repackage.")),
header=brown(" * "),
importance=1)
# normal scanning
entropy_server.output(
red("%s..." % (_("Scanning database for differences"),) ),
header=brown(" * "),
importance=1)
try:
myadded, to_be_removed, to_be_injected = \
entropy_server.scan_package_changes()
except KeyboardInterrupt:
return 1
to_be_added |= myadded
if self._packages:
to_be_removed.clear()
to_be_injected.clear()
tba = dict(((x[0], x,) for x in to_be_added))
tb_added_new = set()
for myatom in self._packages:
if myatom in tba:
tb_added_new.add(tba.get(myatom))
continue
try:
inst_myatom = entropy_server.Spm(
).match_installed_package(myatom)
except KeyError:
entropy_server.output(
red(_("Invalid package"))+" "+bold(myatom),
header=darkred(" !!! "),
importance=1,
level="warning")
continue
if inst_myatom in tba:
tb_added_new.add(tba.get(inst_myatom))
to_be_added = tb_added_new
if not (len(to_be_removed)+len(to_be_added)+len(to_be_injected)):
entropy_server.output(
red(_("Zarro thinggz to do")),
header=brown(" * "),
importance=1)
return 0
if to_be_injected:
entropy_server.output(
blue(_("These would be marked as injected")),
header=brown(" @@ "))
for idpackage, repoid in sorted(to_be_injected,
key = key_sorter):
dbconn = entropy_server.open_server_repository(repoid,
read_only = True, no_upload = True)
atom = dbconn.retrieveAtom(idpackage)
entropy_server.output("["+blue(repoid) + "] " + red(atom),
header=brown(" # "))
if self._ask:
rc = entropy_server.ask_question(
">> %s" % (_("Do it now ?"),))
else:
rc = _("Yes")
if rc == _("Yes"):
for idpackage, repoid in sorted(to_be_injected,
key = key_sorter):
dbconn = entropy_server.open_server_repository(repoid,
read_only = True, no_upload = True)
atom = dbconn.retrieveAtom(idpackage)
entropy_server.output(
"%s: %s" % (blue(_("Transforming")),
red(atom)),
header=brown(" <> "))
entropy_server._transform_package_into_injected(
idpackage, repoid)
entropy_server.output(blue(_("Action completed")),
header=brown(" @@ "))
def show_rm(idpackage, repoid):
dbconn = entropy_server.open_server_repository(repoid,
read_only = True, no_upload = True)
atom = dbconn.retrieveAtom(idpackage)
exp_string = ''
pkg_expired = entropy_server._is_match_expired(
(idpackage, repoid,))
if pkg_expired:
exp_string = "|%s" % (purple(_("expired")),)
entropy_server.output(
"["+blue(repoid) + exp_string + "] " + red(atom),
header=brown(" # "))
if self._interactive and to_be_removed:
entropy_server.output(
blue(_("Select packages for removal")),
header=brown(" @@ "))
new_to_be_removed = set()
for idpackage, repoid in sorted(to_be_removed,
key = key_sorter):
show_rm(idpackage, repoid)
rc = entropy_server.ask_question(
">> %s" % (_("Remove this package?"),))
if rc == _("Yes"):
new_to_be_removed.add((idpackage, repoid,))
to_be_removed = new_to_be_removed
if to_be_removed:
entropy_server.output(
blue(_("These would be removed from repository")),
header=brown(" @@ "))
for idpackage, repoid in sorted(to_be_removed,
key = key_sorter):
show_rm(idpackage, repoid)
if self._ask:
rc = entropy_server.ask_question(
">> %s" % (
_("Would you like to remove them now ?"),) )
else:
rc = _("Yes")
if rc == _("Yes"):
remdata = {}
for idpackage, repoid in to_be_removed:
if repoid not in remdata:
remdata[repoid] = set()
remdata[repoid].add(idpackage)
for repoid in remdata:
entropy_server.remove_packages(repoid,
remdata[repoid])
if self._interactive and to_be_added:
entropy_server.output(
blue(_("Select packages to add")),
header=brown(" @@ "))
new_to_be_added = set()
for tb_atom, tb_counter in sorted(to_be_added,
key = lambda x: x[0]):
entropy_server.output(red(tb_atom),
header=brown(" # "))
rc = entropy_server.ask_question(
">> %s" % (_("Add this package?"),))
if rc == _("Yes"):
new_to_be_added.add((tb_atom, tb_counter,))
to_be_added = new_to_be_added
if to_be_added:
entropy_server.output(
blue(_("These would be added or updated")),
header=brown(" @@ "))
items = sorted([x[0] for x in to_be_added])
for item in items:
item_txt = purple(item)
# this is a spm atom
spm_key = entropy.dep.dep_getkey(item)
try:
spm_slot = entropy_server.Spm(
).get_installed_package_metadata(item, "SLOT")
spm_repo = entropy_server.Spm(
).get_installed_package_metadata(
item, "repository")
except KeyError:
spm_slot = None
spm_repo = None
#
# inform user about SPM repository sources moves !!
#
etp_repo = None
if spm_repo is not None:
pkg_id, repo_id = entropy_server.atom_match(spm_key,
match_slot = spm_slot)
if repo_id != 1:
repo_db = entropy_server.open_server_repository(
repo_id, just_reading = True)
etp_repo = repo_db.retrieveSpmRepository(pkg_id)
if (etp_repo is not None) and \
(etp_repo != spm_repo):
item_txt += ' [%s {%s=>%s}]' % (
bold(_("warning")),
darkgreen(etp_repo), blue(spm_repo),)
entropy_server.output(item_txt, header=brown(" # "))
if self._ask:
rc = entropy_server.ask_question(">> %s (%s %s)" % (
_("Would you like to package them now ?"),
_("inside"),
repository_id,
)
)
if rc == _("No"):
return 0
problems = entropy_server._check_config_file_updates()
if problems:
return 1
# package them
entropy_server.output(
blue(_("Compressing packages")),
header=brown(" @@ "))
store_dir = entropy_server._get_local_store_directory(
repository_id)
for x in sorted(to_be_added):
entropy_server.output(teal(x[0]),
header=brown(" # "))
try:
pkg_list = entropy_server.Spm().generate_package(x[0],
store_dir)
generated_packages.append(pkg_list)
except OSError:
entropy.tools.print_traceback()
entropy_server.output(
bold(_("Ignoring broken Spm entry, please recompile it")),
header=brown(" !!! "),
importance=1,
level="warning")
if not generated_packages:
entropy_server.output(
red(_("Nothing to do, check later.")),
header=brown(" * "))
# then exit gracefully
return 0
etp_pkg_files = [(pkg_list, False) for pkg_list in \
generated_packages]
idpackages = entropy_server.add_packages_to_repository(
repository_id, etp_pkg_files)
if idpackages:
# checking dependencies and print issues
entropy_server.extended_dependencies_test([repository_id])
entropy_server.commit_repositories()
entropy_server.output(red("%s: " % (_("Statistics"),) ) + \
blue("%s: " % (_("Entries handled"),) ) + \
bold(str(len(idpackages))),
header=darkgreen(" * "))
return 0
EitCommandDescriptor.register(
EitCommandDescriptor(
EitCommit,
EitCommit.NAME,
_("commit changes to repository"))
)