[eit.commands.pkgmove] new command "eit pkgmove"
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
# -*- 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 errno
|
||||
import argparse
|
||||
import tempfile
|
||||
import codecs
|
||||
import time
|
||||
|
||||
from entropy.i18n import _
|
||||
from entropy.output import purple, teal
|
||||
|
||||
from eit.commands.descriptor import EitCommandDescriptor
|
||||
from eit.commands.command import EitCommand
|
||||
|
||||
|
||||
class EitPkgmove(EitCommand):
|
||||
"""
|
||||
Main Eit pkgmove command.
|
||||
"""
|
||||
|
||||
NAME = "pkgmove"
|
||||
ALIASES = []
|
||||
|
||||
def __init__(self, args):
|
||||
EitCommand.__init__(self, args)
|
||||
self._repository_id = None
|
||||
|
||||
def _get_parser(self):
|
||||
""" Overridden from EitCommand """
|
||||
descriptor = EitCommandDescriptor.obtain_descriptor(
|
||||
EitPkgmove.NAME)
|
||||
parser = argparse.ArgumentParser(
|
||||
description=descriptor.get_description(),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
prog="%s %s" % (sys.argv[0], EitPkgmove.NAME))
|
||||
|
||||
parser.add_argument("repo", default=None,
|
||||
metavar="<repo>", help=_("repository"))
|
||||
|
||||
return parser
|
||||
|
||||
def parse(self):
|
||||
parser = self._get_parser()
|
||||
try:
|
||||
nsargs = parser.parse_args(self._args)
|
||||
except IOError:
|
||||
return parser.print_help, []
|
||||
|
||||
self._repository_id = nsargs.repo
|
||||
return self._call_locked, [self._pkgmove, self._repository_id]
|
||||
|
||||
def _pkgmove(self, entropy_server):
|
||||
"""
|
||||
Open $EDITOR and let user add/remove package moves.
|
||||
"""
|
||||
notice_text = """\
|
||||
# This is the package move metadata for repository %s, read this:
|
||||
# - the statements must start with either "move" or "slotmove".
|
||||
# - move statement syntax:
|
||||
# move <from package key> <to package key>
|
||||
# - slotmove statement syntax:
|
||||
# slotmove <package dependency> <from slot> <to slot>
|
||||
# - the order of the statements is taken into consideration (KEPT!).
|
||||
# - lines not starting with "move" or "slotmove" will be ignored.
|
||||
# - any line starting with "#" will be ignored as well.
|
||||
#
|
||||
# Example:
|
||||
# move app-foo/bar app-bar/foo
|
||||
# slotmove >=x11-libs/foo-2.0 0 2.0
|
||||
|
||||
""" % (self._repository_id,)
|
||||
tmp_path = None
|
||||
repo = entropy_server.open_server_repository(
|
||||
self._repository_id, read_only=False)
|
||||
actions = repo.retrieveTreeUpdatesActions(self._repository_id)
|
||||
new_actions = []
|
||||
while True:
|
||||
|
||||
if tmp_path is None:
|
||||
tmp_fd, tmp_path = tempfile.mkstemp(
|
||||
prefix = 'entropy.server.pkgmove',
|
||||
suffix = ".conf")
|
||||
with os.fdopen(tmp_fd, "w") as tmp_f:
|
||||
tmp_f.write(notice_text)
|
||||
for action in actions:
|
||||
tmp_f.write(action + "\n")
|
||||
tmp_f.flush()
|
||||
|
||||
success = entropy_server.edit_file(tmp_path)
|
||||
if not success:
|
||||
# retry ?
|
||||
os.remove(tmp_path)
|
||||
return 1
|
||||
|
||||
del new_actions[:]
|
||||
invalid_lines = []
|
||||
with codecs.open(tmp_path, "r", encoding="utf-8") as tmp_f:
|
||||
for line in tmp_f.readlines():
|
||||
if line.startswith("#"):
|
||||
# skip
|
||||
continue
|
||||
strip_line = line.strip()
|
||||
if not strip_line:
|
||||
# ignore
|
||||
continue
|
||||
if strip_line.startswith("move"):
|
||||
split_line = strip_line.split()
|
||||
if len(split_line) != 3:
|
||||
entropy_server.output(
|
||||
"%s: %s !!!" % (_("invalid line"), strip_line),
|
||||
importance=1, level="warning")
|
||||
invalid_lines.append(strip_line)
|
||||
else:
|
||||
new_actions.append(strip_line)
|
||||
elif strip_line.startswith("slotmove"):
|
||||
split_line = strip_line.split()
|
||||
if len(split_line) != 4:
|
||||
entropy_server.output(
|
||||
"%s: %s !!!" % (
|
||||
purple(_("invalid line")), strip_line),
|
||||
importance=1, level="warning")
|
||||
invalid_lines.append(strip_line)
|
||||
else:
|
||||
new_actions.append(strip_line)
|
||||
else:
|
||||
entropy_server.output(
|
||||
"%s: %s !!!" % (
|
||||
purple(_("invalid line")), strip_line),
|
||||
importance=1, level="warning")
|
||||
invalid_lines.append(strip_line)
|
||||
|
||||
if invalid_lines:
|
||||
resp = entropy_server.ask_question(
|
||||
_("Invalid syntax, what to do ?"),
|
||||
responses=(_("Repeat"), _("Abort")))
|
||||
if resp == _("Abort"):
|
||||
os.remove(tmp_path)
|
||||
return 1
|
||||
else:
|
||||
# repeat, edit same file
|
||||
continue
|
||||
|
||||
# show submitted info
|
||||
for action in new_actions:
|
||||
entropy_server.output(action, level="generic")
|
||||
entropy_server.output("", level="generic")
|
||||
|
||||
# ask confirmation
|
||||
while True:
|
||||
try:
|
||||
rc_question = entropy_server.ask_question(
|
||||
"[%s] %s" % (
|
||||
purple(self._repository_id),
|
||||
teal(_("Do you agree?"))
|
||||
),
|
||||
responses = (_("Yes"), _("Repeat"), _("No"),)
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
# do not allow, we're in a critical region
|
||||
continue
|
||||
break
|
||||
if rc_question == _("Yes"):
|
||||
break
|
||||
elif rc_question == _("No"):
|
||||
return 1
|
||||
# otherwise repeat everything again
|
||||
# keep tmp_path
|
||||
|
||||
if tmp_path is not None:
|
||||
try:
|
||||
os.remove(tmp_path)
|
||||
except (OSError) as err:
|
||||
if err.errno != errno.ENOENT:
|
||||
raise
|
||||
|
||||
# write new actions
|
||||
branch = self._settings()['repositories']['branch']
|
||||
actions_meta = []
|
||||
cur_t = time.time()
|
||||
# time is completely fake, no particular precision required
|
||||
for action in new_actions:
|
||||
cur_t += 1
|
||||
actions_meta.append((action, branch, str(cur_t)))
|
||||
|
||||
repo.removeTreeUpdatesActions(self._repository_id)
|
||||
try:
|
||||
repo.insertTreeUpdatesActions(actions_meta, self._repository_id)
|
||||
except Exception as err:
|
||||
repo.rollback()
|
||||
raise
|
||||
repo.commit()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
EitCommandDescriptor.register(
|
||||
EitCommandDescriptor(
|
||||
EitPkgmove,
|
||||
EitPkgmove.NAME,
|
||||
_('edit automatic package moves for repository'))
|
||||
)
|
||||
Reference in New Issue
Block a user