[eit] first chunk of code for the new server-side repository management toolkit (greatly inspired to git)

This commit is contained in:
Fabio Erculiani
2011-10-09 17:10:26 +02:00
parent 612e39a1e8
commit ea47fe703d
10 changed files with 846 additions and 389 deletions
-389
View File
@@ -1,389 +0,0 @@
#!/usr/bin/python2 -O
# -*- coding: utf-8 -*-
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Package Manager Server Wrapper Tool}.
"""
import os
import sys
import subprocess
sys.path.insert(0, '../libraries')
sys.path.insert(1, '../client')
sys.path.insert(2, '../server')
sys.path.insert(3, '/usr/lib/entropy/client')
sys.path.insert(4, '/usr/lib/entropy/libraries')
sys.path.insert(5, '/usr/lib/entropy/server')
from entropy.i18n import _
import entropy.tools
from text_tools import print_menu
from entropy.output import is_stdout_a_tty, nocolor, print_error, print_info, \
print_warning, purple, teal
from entropy.const import etpConst, etpUi
REAGENT_EXEC = "/usr/sbin/reagent"
ACTIVATOR_EXEC = "/usr/sbin/activator"
help_opts = [
None,
(0, " ~ eit ~ ", 1,
'The Stupid Entropy Content Tracker (wrapper) - (C) %s' % (
entropy.tools.get_year(),) ),
None,
(0, _('Options'), 0, None),
None,
(1, 'add <pkgs>', 3, _('commit to current repository only the provided packages')),
(1, 'addto <repository> <pkgs>', 1, _('commit to give repository only the provided packages')),
(1, 'bump [<repository>]', 2, _('bump repository revision, this will force upload')),
(1, 'checkout <repository>', 2, _('switch from a repository to another')),
(1, 'cleanup [<repository>]', 2, _('clean expired packages from a repository')),
(1, 'commit [<repository>]', 2, _('commit changes to repository')),
(1, 'cp <from> <to> <pkgs>', 2, _('copy packages from a repository to another')),
(1, 'deps <pkgs>', 3, _('edit package dependencies')),
(1, 'depsin <repository> <pkgs>', 1, _('edit package dependencies in given repository')),
(1, 'deptest [<repository>]', 2, _('edit package dependencies')),
(1, 'fit <package files>', 2, _('inject package files into the current repository')),
(1, 'graph <pkgs> [--complete]', 1, _('show dependency graph of packages')),
(1, 'init <repository>', 2, _('initialize repository (erasing all its content)')),
(1, 'libtest [--dump]', 2, _('look for missing libraries (scan system)')),
(1, 'linktest [<excl libs>]', 2, _('look for missing libraries (scan repository metadata)')),
(1, 'list [<repository>]', 2, _('list packages in repository')),
(1, 'log [<repository>]', 2, _('show log for repository')),
(1, 'mv <from> <to> <pkgs>', 2, _('move packages from a repository to another')),
(1, 'own <package files>', 2, _('show owners of files (in current repository)')),
(1, 'push [<repository>]', 2, _('push committed packages remotely')),
(1, 'pushas <repository> <as repo>', 1, _('push committed packages to given fake repository')),
(1, 'repack <pkgs>', 3, _('re-package list of packages in default repository')),
(1, 'repackin <repository> <pkgs>', 1, _('re-package list of packages in given repository')),
(1, 'repo', 4, _('show current repository')),
(1, 'reset [<repository>]', 2, _('reset repository to remote status')),
(1, 'revgraph <pkgs> [--complete]', 1, _('show reverse dependency graph of packages')),
(1, 'rm <pkgs>', 3, _('remove packages from current repository')),
(1, 'rmfrom <repository> <pkgs>', 1, _('remove packages from given repository')),
(1, 'search <package deps>', 2, _('search for privided package dependencies')),
(1, 'show <package deps>', 2, _('show matches for privided package dependencies')),
(1, 'status [<repository>]', 2, _('show current repositories status')),
(1, 'vacuum [<repository>]', 2, _('clean unavailable packages from a repository')),
None,
]
options = sys.argv[1:]
import re
opt_r = re.compile("^(\\-)([a-z]+)$")
for n in range(len(options)):
if opt_r.match(options[n]):
x = options[n]
del options[n]
options.extend(["-%s" % (d,) for d in x[1:]])
# preliminary options parsing
_options = []
no_color = False
force_color = False
for opt in options:
if opt in ["--nocolor", "-N"]:
nocolor()
no_color = True
elif opt in ["--color", "-C"]:
force_color = True
elif opt in ["--quiet", "-q"]:
etpUi['quiet'] = True
elif opt in ["--verbose", "-v"]:
etpUi['verbose'] = True
elif opt in ["--ask", "-a"]:
etpUi['ask'] = True
elif opt in ["--pretend", "-p"]:
etpUi['pretend'] = True
else:
_options.append(opt)
options = _options
# Check if we need to disable colors
if (not force_color) and (not is_stdout_a_tty()):
nocolor()
# print help
if not options or ("--help" in options) or ("-h" in options):
print_menu(help_opts)
if len(options) < 1:
print_error("not enough parameters")
raise SystemExit(1)
raise SystemExit(0)
def _exec_args(args):
myargs = []
if etpUi['quiet']:
myargs.append("--quiet")
if etpUi['verbose']:
myargs.append("--verbose")
if etpUi['ask']:
myargs.append("--ask")
if etpUi['pretend']:
myargs.append("--pretend")
if force_color:
myargs.append("--color")
if no_color:
myargs.append("--nocolor")
os.execvpe(args[0], args + myargs, os.environ)
def get_entropy_server(quiet = False):
oldquiet = etpUi['quiet']
try:
if quiet:
etpUi['quiet'] = True
from entropy.server.interfaces import Server
return Server(community_repo = etpConst['community']['mode'])
finally:
if quiet:
etpUi['quiet'] = oldquiet
def _get_available_repositories():
server = None
try:
server = get_entropy_server(quiet = True)
repository_ids = server.repositories()
return repository_ids
finally:
if server is not None:
server.shutdown()
main_cmd = options.pop(0)
if main_cmd == "status":
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([REAGENT_EXEC, "status"] + options)
elif main_cmd == "add" and options:
_exec_args([REAGENT_EXEC, "update", "--atoms"] + options)
elif main_cmd == "addto" and options and len(options) > 1:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([REAGENT_EXEC, "update", "--atoms"] + options)
elif main_cmd == "repack" and options:
_exec_args([REAGENT_EXEC, "update", "--atoms"] + options + \
["--repackage"] + options)
elif main_cmd == "repackin" and options and len(options) > 1:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([REAGENT_EXEC, "update", "--atoms"] + options + \
["--repackage"] + options)
elif main_cmd == "bump":
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([REAGENT_EXEC, "repo", "bump"])
elif (main_cmd == "checkout") and options and len(options) < 2:
repository_id = options.pop(0)
_exec_args([REAGENT_EXEC, "repo", "default", repository_id])
elif main_cmd == "cleanup":
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([ACTIVATOR_EXEC, "tidy"])
elif main_cmd == "vacuum":
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([ACTIVATOR_EXEC, "repo", "vacuum"])
elif main_cmd == "commit":
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([REAGENT_EXEC, "update"] + options)
else:
_exec_args([REAGENT_EXEC, "update"] + options)
elif (main_cmd == "fit") and options:
_exec_args([REAGENT_EXEC, "inject"] + options)
elif main_cmd == "list":
myopts = []
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
myopts += [options[0]]
_exec_args([REAGENT_EXEC, "query", "list"] + myopts)
elif main_cmd == "graph" and options and \
not ((len(set(options)) == 1) and ("--complete" in options)):
_exec_args([REAGENT_EXEC, "query", "graph"] + options)
elif main_cmd == "revgraph" and options and \
not ((len(set(options)) == 1) and ("--complete" in options)):
_exec_args([REAGENT_EXEC, "query", "revgraph"] + options)
elif (main_cmd == "init") and options and len(options) < 2:
repository_id = options.pop(0)
avail_repos = _get_available_repositories()
if repository_id in avail_repos:
os.environ['ETP_REPO'] = repository_id
_exec_args([REAGENT_EXEC, "repo", "init"])
elif main_cmd == "libtest":
lt_options = []
if "--dump" in options:
lt_options.append("--dump")
_exec_args([REAGENT_EXEC, "libtest"] + lt_options)
elif main_cmd == "linktest":
_exec_args([REAGENT_EXEC, "linktest"] + options)
elif main_cmd == "deptest":
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([REAGENT_EXEC, "deptest"])
elif (main_cmd == "own") and options:
_exec_args([REAGENT_EXEC, "query", "belongs"] + options)
elif main_cmd == "push":
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([ACTIVATOR_EXEC, "sync"] + options)
elif main_cmd == "pushas" and len(options) == 2:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([ACTIVATOR_EXEC, "syncas"] + options)
elif main_cmd == "show" and options:
_exec_args([REAGENT_EXEC, "query", "match"] + options)
elif main_cmd == "search" and options:
_exec_args([REAGENT_EXEC, "query", "search"] + options)
elif main_cmd == "mv" and len(options) > 2:
from_repo = options.pop(0)
to_repo = options.pop(0)
_exec_args([REAGENT_EXEC, "repo", "move", from_repo, to_repo] + options)
elif main_cmd == "cp" and len(options) > 2:
avail_repos = _get_available_repositories()
from_repo = options.pop(0)
to_repo = options.pop(0)
if (from_repo in avail_repos) and (to_repo in avail_repos):
_exec_args([REAGENT_EXEC, "repo", "copy", from_repo, to_repo] + options)
elif main_cmd == "deps" and options:
server = None
repository_id = None
try:
server = get_entropy_server(quiet = True)
# get current repository id
repository_id = server.repository()
finally:
if server is not None:
server.shutdown()
_exec_args([REAGENT_EXEC, "repo", "package-dep", repository_id] + options)
elif main_cmd == "depsin" and len(options) > 1:
avail_repos = _get_available_repositories()
repository_id = options.pop(0)
if repository_id in avail_repos:
_exec_args([REAGENT_EXEC, "repo", "package-dep", repository_id] + options)
elif main_cmd == "rm" and options:
_exec_args([REAGENT_EXEC, "repo", "remove"] + options)
elif main_cmd == "rmfrom" and options and len(options) > 1:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
_exec_args([REAGENT_EXEC, "repo", "remove"] + options)
elif main_cmd == "repo":
server = None
try:
server = get_entropy_server(quiet = True)
repository_id = server.repository()
repository_ids = server.repositories()
for repo_id in sorted(repository_ids):
if repo_id == repository_id:
print_warning(purple(repo_id) + " *")
else:
print_info(teal(repo_id))
raise SystemExit(0)
finally:
if server is not None:
server.shutdown()
elif main_cmd == "reset":
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
server = None
try:
server = get_entropy_server()
rev_path = server._get_local_repository_revision_file(
server.repository())
try:
with open(rev_path, "w") as rev_f:
rev_f.write("0\n")
except (IOError, OSError) as err:
print_error("%s: %s" % (_("reset error"), err))
raise SystemExit(1)
finally:
if server is not None:
server.shutdown()
_exec_args([ACTIVATOR_EXEC, "repo", "sync"])
elif main_cmd == "log":
if options:
avail_repos = _get_available_repositories()
if options[0] in avail_repos:
os.environ['ETP_REPO'] = options.pop(0)
server = None
try:
server = get_entropy_server()
changelog_path = server._get_local_repository_compressed_changelog_file(
server.repository())
if os.path.isfile(changelog_path) and os.access(changelog_path, os.R_OK):
proc = subprocess.Popen(
"/bin/bzcat \"%s\" | ${PAGER:-/usr/bin/less}" % (
changelog_path,), shell = True)
raise SystemExit(proc.wait())
else:
print_error("log is not available")
raise SystemExit(1)
finally:
if server is not None:
server.shutdown()
else:
print_menu(help_opts)
print_error("wrong parameters")
raise SystemExit(1)
Executable
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/python2
import sys
# Entropy imports
sys.path.insert(0, "/usr/lib/entropy/libraries")
sys.path.insert(0, "/usr/lib/entropy/client")
sys.path.insert(0, "/usr/lib/entropy/server")
sys.path.insert(0, "../libraries")
sys.path.insert(0, "../server")
sys.path.insert(0, "../client")
from eit.main import main
sys.argv[0] = "eit"
main()
+11
View File
@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Infrastructure Toolkit}.
"""
+11
View File
@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Infrastructure Toolkit}.
"""
+53
View File
@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Infrastructure Toolkit}.
"""
from entropy.const import etpConst
from entropy.server.interfaces import Server
from entropy.core.settings.base import SystemSettings
class EitCommand(object):
"""
Base class for Eit commands
"""
# Set this to the command name from where this object
# gets triggered (for eit help, "help" is the NAME
# that should be set).
NAME = None
def __init__(self, args):
self._args = args
def parse(self):
"""
Parse the actual arguments and return
the function that should be called and
its arguments. The function signature is:
int function([list of args])
The return value represents the exit status
of the "command"
"""
raise NotImplementedError()
def _entropy(self, *args, **kwargs):
"""
Return the Entropy Server object.
This method is not thread safe.
"""
if "community_repo" not in kwargs:
kwargs["community_repo"] = etpConst['community']['mode']
return Server(*args, **kwargs)
def _settings(self):
"""
Return a SystemSettings instance.
"""
return SystemSettings()
+368
View File
@@ -0,0 +1,368 @@
# -*- 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.const import etpConst
from entropy.i18n import _
from entropy.exceptions import PermissionDenied
from entropy.output import print_info, print_warning, print_error, \
darkgreen, teal, brown, darkred, bold, purple, blue, red, green
from text_tools import print_table
import entropy.tools
from eit.commands.descriptor import EitCommandDescriptor
from eit.commands.command import EitCommand
class EitCommit(EitCommand):
"""
Main Eit commit command.
"""
NAME = "commit"
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._atoms = []
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 id")
parser.add_argument("--interactive", action="store_true",
default=False,
help=_("selectively pick changes"))
parser.add_argument("--quick", action="store_true",
default=False,
help=_("no stupid questions"))
try:
nsargs = parser.parse_args(self._args)
except IOError as err:
print_error("error: %s" % (err.strerror,))
return parser.print_help, []
self._interactive = nsargs.interactive
if not self._interactive:
self._ask = not nsargs.quick
return self._commit, [nsargs.repo]
def _commit(self, repo):
"""
Commit command body.
"""
server = None
acquired = False
try:
try:
server = self._entropy(default_repository=repo)
except PermissionDenied as err:
print_error(err.value)
return 1
acquired = entropy.tools.acquire_entropy_locks(server)
if not acquired:
print_error(
darkgreen(_("Another Entropy is currently running."))
)
return 1
return self.__commit(server)
finally:
if server is not None:
if acquired:
entropy.tools.release_entropy_locks(server)
server.shutdown()
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:
print_warning(darkred(" !!! ") + \
red(_("Cannot match"))+" "+bold(item))
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:
print_info(brown(" * ") + \
red(_("No valid packages to repackage.")))
# normal scanning
print_info(brown(" * ") + \
red("%s..." % (_("Scanning database for differences"),) ))
try:
myadded, to_be_removed, to_be_injected = \
entropy_server.scan_package_changes()
except KeyboardInterrupt:
return 1
to_be_added |= myadded
if self._atoms:
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._atoms:
if myatom in tba:
tb_added_new.add(tba.get(myatom))
continue
try:
inst_myatom = entropy_server.Spm(
).match_installed_package(myatom)
except KeyError:
print_warning(darkred(" !!! ") + \
red(_("Invalid package")) + " " + bold(myatom))
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)):
print_info(brown(" * ") + \
red("%s." % (_("Zarro thinggz totoo"),)))
return 0
if to_be_injected:
print_info(brown(" @@ ") + \
blue("%s:" % (
_("These would be marked as injected"),) ))
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)
print_info(brown(" # ") + "["+blue(repoid) + "] " + \
red(atom))
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)
print_info(brown(" <> ") + \
blue("%s: " % (_("Transforming"),) )+red(atom))
entropy_server._transform_package_into_injected(
idpackage, repoid)
print_info(brown(" @@ ") + \
blue("%s." % (_("Transform complete"),) ))
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")),)
print_info(brown(" # ") + "["+blue(repoid) + \
exp_string + "] " + red(atom))
if self._interactive and to_be_removed:
print_info(brown(" @@ ") + \
blue(_("What packages do you want to remove ?")))
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:
print_info(brown(" @@ ") + blue("%s:" % (
_("These would be removed from repository"),) ))
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:
print_info(brown(" @@ ") + \
blue(_("What packages do you want to add ?")))
new_to_be_added = set()
for tb_atom, tb_counter in sorted(to_be_added,
key = lambda x: x[0]):
print_info(brown(" # ") + red(tb_atom))
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:
print_info(brown(" @@ ") + \
blue("%s:" % (
_("These would be added or updated"),) ))
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),)
print_info(brown(" # ") + item_txt)
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
print_info(brown(" @@ ") + \
blue("%s..." % (_("Compressing packages"),) ))
store_dir = entropy_server._get_local_store_directory(
repository_id)
for x in sorted(to_be_added):
print_info(brown(" # ") + teal(x[0]))
try:
pkg_list = entropy_server.Spm().generate_package(x[0],
store_dir)
generated_packages.append(pkg_list)
except OSError:
entropy.tools.print_traceback()
print_info(brown(" !!! ")+bold("%s..." % (
_("Ignoring broken Spm entry, please recompile it"),) )
)
if not generated_packages:
print_info(brown(" * ")+red(_("Nothing to do, check later.")))
# 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.close_repositories()
print_info(green(" * ") + red("%s: " % (_("Statistics"),) ) + \
blue("%s: " % (_("Entries handled"),) ) + \
bold(str(len(idpackages))))
return 0
EitCommandDescriptor.register(
EitCommandDescriptor(
EitCommit,
EitCommit.NAME,
_("commit changes to repository"))
)
+73
View File
@@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Infrastructure Toolkit}.
Eit Command descriptor class.
"""
class EitCommandDescriptor(object):
"""
EitCommand descriptor object used for
help information purposes.
"""
EIT_COMMANDS = []
EIT_COMMANDS_MAP = {}
@staticmethod
def register(descriptor):
"""
Register an EitCommandDescriptor object
"""
EitCommandDescriptor.EIT_COMMANDS.append(descriptor)
EitCommandDescriptor.EIT_COMMANDS_MAP[descriptor.get_name()] = \
descriptor
@staticmethod
def obtain():
"""
Get the list of registered EitCommandDescriptor object
"""
return EitCommandDescriptor.EIT_COMMANDS[:]
@staticmethod
def obtain_descriptor(name):
"""
Get a registered EitCommandDescritor object
through its name.
@param name: name of the EitCommandDescriptor
@type name: string
@raise KeyError: if name isn't bound to any
EitCommandDescriptor object.
"""
return EitCommandDescriptor.EIT_COMMANDS_MAP[name]
def __init__(self, klass, name, description):
self._klass = klass
self._name = name
self._description = description
def get_class(self):
"""
Get EitCommand class bound to this command
"""
return self._klass
def get_name(self):
"""
Get EitCommand name
"""
return self._name
def get_description(self):
"""
Get EitCommand description
"""
return self._description
+55
View File
@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Infrastructure Toolkit}.
"""
import argparse
from entropy.i18n import _
from eit.commands.descriptor import EitCommandDescriptor
from eit.commands.command import EitCommand
class EitHelp(EitCommand):
"""
Main Eit help command.
"""
NAME = "help"
def parse(self):
"""
Parse help command
"""
return self._show_help, []
def _show_help(self, *args):
parser = argparse.ArgumentParser(
description=_("Entropy Infrastructure Toolkit"),
epilog="http://www.sabayon.org",
formatter_class=argparse.RawDescriptionHelpFormatter)
descriptors = EitCommandDescriptor.obtain()
descriptors.sort(key = lambda x: x.get_name())
group = parser.add_argument_group("command", "available commands")
for descriptor in descriptors:
group.add_argument(descriptor.get_name(),
help=descriptor.get_description(),
action="store_true")
parser.print_help()
if not self._args:
return 1
return 0
EitCommandDescriptor.register(
EitCommandDescriptor(
EitHelp,
EitHelp.NAME,
_("this help"))
)
+179
View File
@@ -0,0 +1,179 @@
# -*- 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.const import etpConst
from entropy.i18n import _
from entropy.exceptions import PermissionDenied
from entropy.output import print_info, print_error, darkgreen, \
teal, brown, darkred, bold, purple, blue
from text_tools import print_table
import entropy.tools
from eit.commands.descriptor import EitCommandDescriptor
from eit.commands.command import EitCommand
class EitStatus(EitCommand):
"""
Main Eit status command.
"""
NAME = "status"
def parse(self):
descriptor = EitCommandDescriptor.obtain_descriptor(
EitStatus.NAME)
parser = argparse.ArgumentParser(
description=descriptor.get_description(),
formatter_class=argparse.RawDescriptionHelpFormatter,
prog="%s %s" % (sys.argv[0], EitStatus.NAME))
parser.add_argument("repo", nargs='?', default=None,
metavar="<repo>", help="repository id")
try:
nsargs = parser.parse_args(self._args)
except IOError as err:
print_error("error: %s" % (err.strerror,))
return parser.print_help, []
return self._status, [nsargs.repo]
def _status(self, repo):
"""
Status command body.
"""
server = None
acquired = False
try:
try:
server = self._entropy(default_repository=repo)
except PermissionDenied as err:
print_error(err.value)
return 1
acquired = entropy.tools.acquire_entropy_locks(server)
if not acquired:
print_error(
darkgreen(_("Another Entropy is currently running."))
)
return 1
return self.__status(server)
finally:
if server is not None:
if acquired:
entropy.tools.release_entropy_locks(server)
server.shutdown()
def __status(self, entropy_server):
plugin_id = etpConst['system_settings_plugins_ids']['server_plugin']
repos_data = self._settings()[plugin_id]['server']['repositories']
repo_id = entropy_server.repository()
repo_data = repos_data[repo_id]
repo_rev = entropy_server.local_repository_revision(repo_id)
store_dir = entropy_server._get_local_store_directory(repo_id)
upload_basedir = entropy_server._get_local_upload_directory(repo_id)
upload_files, upload_packages = \
entropy_server.Mirrors._calculate_local_upload_files(repo_id)
key_sorter = lambda x: \
entropy_server.open_repository(x[1]).retrieveAtom(x[0])
to_be_added, to_be_removed, to_be_injected = \
entropy_server.scan_package_changes()
to_be_added = [x[0] for x in to_be_added]
to_be_added.sort()
toc = []
toc.append("[%s] %s" % (purple(repo_id),
brown(repo_data['description']),))
toc.append((" %s:" % (blue(_("local revision")),),
str(repo_rev),))
store_pkgs = []
if os.path.isdir(store_dir):
store_pkgs = os.listdir(store_dir)
toc.append((" %s:" % (darkgreen(_("stored packages")),),
str(len(store_pkgs)),))
for pkg_rel in sorted(store_pkgs):
toc.append((" ", brown(pkg_rel)))
toc.append((" %s:" % (darkgreen(_("upload packages")),),
str(upload_files),))
for pkg_rel in sorted(upload_packages):
toc.append((" ", brown(pkg_rel)))
unstaged_len = len(to_be_added) + len(to_be_removed) + \
len(to_be_injected)
toc.append((" %s:" % (darkgreen(_("unstaged packages")),),
str(unstaged_len),))
print_table(toc)
del toc[:]
print_info("")
def _get_spm_slot_repo(pkg_atom):
try:
spm_slot = entropy_server.Spm(
).get_installed_package_metadata(pkg_atom, "SLOT")
spm_repo = entropy_server.Spm(
).get_installed_package_metadata(pkg_atom,
"repository")
except KeyError:
spm_repo = None
spm_slot = None
return spm_slot, spm_repo
for pkg_atom in to_be_added:
spm_slot, spm_repo = _get_spm_slot_repo(pkg_atom)
pkg_str = teal(pkg_atom)
if spm_repo is not None:
pkg_id, repo_id = entropy_server.atom_match(pkg_atom,
match_slot = spm_slot)
if pkg_id != -1:
etp_repo = entropy_server.open_repository(
repo_id).retrieveSpmRepository(pkg_id)
if etp_repo != spm_repo:
pkg_str += " [%s=>%s]" % (
etp_repo, spm_repo,)
toc.append((" %s:" % (purple(_("add")),), teal(pkg_str)))
for package_id, repo_id in sorted(to_be_removed, key = key_sorter):
pkg_atom = entropy_server.open_repository(repo_id
).retrieveAtom(package_id)
toc.append((" %s:" % (darkred(_("remove")),),
brown(pkg_atom)))
for package_id, repo_id in sorted(to_be_injected,
key = key_sorter):
pkg_atom = entropy_server.open_repository(repo_id
).retrieveAtom( package_id)
toc.append((" %s:" % (bold(_("switch injected")),),
darkgreen(pkg_atom)))
print_table(toc)
return 0
EitCommandDescriptor.register(
EitCommandDescriptor(
EitStatus,
EitStatus.NAME,
_("show repository status"))
)
+82
View File
@@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Infrastructure Toolkit}.
"""
import os
import sys
import argparse
from entropy.i18n import _
from entropy.output import print_error
import entropy.tools
from eit.commands.status import EitStatus
from eit.commands.help import EitHelp
from eit.commands.commit import EitCommit
def handle_exception(exc_class, exc_instance, exc_tb):
# restore original exception handler, to avoid loops
uninstall_exception_handler()
entropy.tools.kill_threads()
if exc_class is KeyboardInterrupt:
raise SystemExit(1)
# always slap exception data (including stack content)
entropy.tools.print_exception(tb_data = exc_tb)
raise exc_instance
def install_exception_handler():
sys.excepthook = handle_exception
def uninstall_exception_handler():
sys.excepthook = sys.__excepthook__
def main():
install_exception_handler()
args_map = {
EitHelp.NAME: EitHelp,
"-h": EitHelp,
"--help": EitHelp,
EitStatus.NAME: EitStatus,
EitCommit.NAME: EitCommit,
}
args = sys.argv[1:]
cmd = None
if args:
cmd = args[0]
args = args[1:]
cmd_class = args_map.get(cmd)
if cmd_class is None:
cmd_class = args_map.get(EitHelp.NAME)
# non-root users not allowed
allowed = True
if os.getuid() != 0 and \
cmd_class is not EitHelp:
cmd_class = EitHelp
allowed = False
cmd_obj = cmd_class(args)
func, func_args = cmd_obj.parse()
exit_st = func(*func_args)
if allowed:
raise SystemExit(exit_st)
else:
print_error(_("superuser access required"))
raise SystemExit(1)