|
Packit Service |
21c75c |
# shell.py
|
|
Packit Service |
21c75c |
# Shell CLI command.
|
|
Packit Service |
21c75c |
#
|
|
Packit Service |
21c75c |
# Copyright (C) 2016 Red Hat, Inc.
|
|
Packit Service |
21c75c |
#
|
|
Packit Service |
21c75c |
# This copyrighted material is made available to anyone wishing to use,
|
|
Packit Service |
21c75c |
# modify, copy, or redistribute it subject to the terms and conditions of
|
|
Packit Service |
21c75c |
# the GNU General Public License v.2, or (at your option) any later version.
|
|
Packit Service |
21c75c |
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
Packit Service |
21c75c |
# ANY WARRANTY expressed or implied, including the implied warranties of
|
|
Packit Service |
21c75c |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
Packit Service |
21c75c |
# Public License for more details. You should have received a copy of the
|
|
Packit Service |
21c75c |
# GNU General Public License along with this program; if not, write to the
|
|
Packit Service |
21c75c |
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
21c75c |
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
|
|
Packit Service |
21c75c |
# source code or documentation are not subject to the GNU General Public
|
|
Packit Service |
21c75c |
# License and may only be used or replicated with the express permission of
|
|
Packit Service |
21c75c |
# Red Hat, Inc.
|
|
Packit Service |
21c75c |
#
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
from dnf.cli import commands
|
|
Packit Service |
21c75c |
from dnf.i18n import _, ucd
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
import dnf.util
|
|
Packit Service |
21c75c |
import cmd
|
|
Packit Service |
21c75c |
import copy
|
|
Packit Service |
21c75c |
import dnf
|
|
Packit Service |
21c75c |
import logging
|
|
Packit Service |
21c75c |
import shlex
|
|
Packit Service |
21c75c |
import sys
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
logger = logging.getLogger('dnf')
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
# only demands we'd like to override
|
|
Packit Service |
21c75c |
class ShellDemandSheet(object):
|
|
Packit Service |
21c75c |
available_repos = True
|
|
Packit Service |
21c75c |
resolving = True
|
|
Packit Service |
21c75c |
root_user = True
|
|
Packit Service |
21c75c |
sack_activation = True
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
class ShellCommand(commands.Command, cmd.Cmd):
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
aliases = ('shell', 'sh')
|
|
Packit Service |
21c75c |
summary = _('run an interactive {prog} shell').format(prog=dnf.util.MAIN_PROG_UPPER)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
MAPPING = {'repo': 'repo',
|
|
Packit Service |
21c75c |
'repository': 'repo',
|
|
Packit Service |
21c75c |
'exit': 'quit',
|
|
Packit Service |
21c75c |
'quit': 'quit',
|
|
Packit Service |
21c75c |
'run': 'ts_run',
|
|
Packit Service |
21c75c |
'ts': 'transaction',
|
|
Packit Service |
21c75c |
'transaction': 'transaction',
|
|
Packit Service |
21c75c |
'config': 'config',
|
|
Packit Service |
21c75c |
'resolvedep': 'resolve',
|
|
Packit Service |
21c75c |
'help': 'help'
|
|
Packit Service |
21c75c |
}
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def __init__(self, cli):
|
|
Packit Service |
21c75c |
commands.Command.__init__(self, cli)
|
|
Packit Service |
21c75c |
cmd.Cmd.__init__(self)
|
|
Packit Service |
21c75c |
self.prompt = '> '
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
@staticmethod
|
|
Packit Service |
21c75c |
def set_argparser(parser):
|
|
Packit Service |
21c75c |
parser.add_argument('script', nargs='?', metavar=_('SCRIPT'),
|
|
Packit Service |
21c75c |
help=_('Script to run in {prog} shell').format(
|
|
Packit Service |
21c75c |
prog=dnf.util.MAIN_PROG_UPPER))
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def configure(self):
|
|
Packit Service |
21c75c |
# append to ShellDemandSheet missing demands from
|
|
Packit Service |
21c75c |
# dnf.cli.demand.DemandSheet with their default values.
|
|
Packit Service |
21c75c |
default_demands = self.cli.demands
|
|
Packit Service |
21c75c |
self.cli.demands = ShellDemandSheet()
|
|
Packit Service |
21c75c |
for attr in dir(default_demands):
|
|
Packit Service |
21c75c |
if attr.startswith('__'):
|
|
Packit Service |
21c75c |
continue
|
|
Packit Service |
21c75c |
try:
|
|
Packit Service |
21c75c |
getattr(self.cli.demands, attr)
|
|
Packit Service |
21c75c |
except AttributeError:
|
|
Packit Service |
21c75c |
setattr(self.cli.demands, attr, getattr(default_demands, attr))
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def run(self):
|
|
Packit Service |
21c75c |
if self.opts.script:
|
|
Packit Service |
21c75c |
self._run_script(self.opts.script)
|
|
Packit Service |
21c75c |
else:
|
|
Packit Service |
21c75c |
self.cmdloop()
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def _clean(self):
|
|
Packit Service |
21c75c |
self.base._finalize_base()
|
|
Packit Service |
21c75c |
self.base._transaction = None
|
|
Packit Service |
21c75c |
self.base.fill_sack()
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def onecmd(self, line):
|
|
Packit Service |
21c75c |
if not line or line == '\n':
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
if line == 'EOF':
|
|
Packit Service |
21c75c |
line = 'quit'
|
|
Packit Service |
21c75c |
try:
|
|
Packit Service |
21c75c |
s_line = shlex.split(line)
|
|
Packit Service |
21c75c |
except:
|
|
Packit Service |
21c75c |
self._help()
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
# reset option parser before each command, keep usage information
|
|
Packit Service |
21c75c |
self.cli.optparser.__init__(reset_usage=False)
|
|
Packit Service |
21c75c |
opts = self.cli.optparser.parse_main_args(s_line)
|
|
Packit Service |
21c75c |
# Disable shell recursion.
|
|
Packit Service |
21c75c |
if opts.command == 'shell':
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
if opts.command in self.MAPPING:
|
|
Packit Service |
21c75c |
getattr(self, '_' + self.MAPPING[opts.command])(s_line[1::])
|
|
Packit Service |
21c75c |
else:
|
|
Packit Service |
21c75c |
cmd_cls = self.cli.cli_commands.get(opts.command)
|
|
Packit Service |
21c75c |
if cmd_cls is not None:
|
|
Packit Service |
21c75c |
cmd = cmd_cls(self.cli)
|
|
Packit Service |
21c75c |
try:
|
|
Packit Service |
21c75c |
opts = self.cli.optparser.parse_command_args(cmd, s_line)
|
|
Packit Service |
21c75c |
except SystemExit:
|
|
Packit Service |
21c75c |
# argparse.ArgumentParser prints usage information and executes
|
|
Packit Service |
21c75c |
# sys.exit() on problems with parsing command line arguments
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
try:
|
|
Packit Service |
21c75c |
cmd.cli.demands = copy.deepcopy(self.cli.demands)
|
|
Packit Service |
21c75c |
cmd.configure()
|
|
Packit Service |
21c75c |
cmd.run()
|
|
Packit Service |
21c75c |
except dnf.exceptions.Error as e:
|
|
Packit Service |
21c75c |
logger.error(_("Error:") + " " + ucd(e))
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
else:
|
|
Packit Service |
21c75c |
self._help()
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def _config(self, args=None):
|
|
Packit Service |
21c75c |
def print_or_set(key, val, conf):
|
|
Packit Service |
21c75c |
if val:
|
|
Packit Service |
21c75c |
setattr(conf, key, val)
|
|
Packit Service |
21c75c |
else:
|
|
Packit Service |
21c75c |
try:
|
|
Packit Service |
21c75c |
print('{}: {}'.format(key, getattr(conf, str(key))))
|
|
Packit Service |
21c75c |
except:
|
|
Packit Service |
21c75c |
logger.warning(_('Unsupported key value.'))
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
if not args or len(args) > 2:
|
|
Packit Service |
21c75c |
self._help('config')
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
key = args[0]
|
|
Packit Service |
21c75c |
val = args[1] if len(args) == 2 else None
|
|
Packit Service |
21c75c |
period = key.find('.')
|
|
Packit Service |
21c75c |
if period != -1:
|
|
Packit Service |
21c75c |
repo_name = key[:period]
|
|
Packit Service |
21c75c |
key = key[period+1:]
|
|
Packit Service |
21c75c |
repos = self.base.repos.get_matching(repo_name)
|
|
Packit Service |
21c75c |
for repo in repos:
|
|
Packit Service |
21c75c |
print_or_set(key, val, repo)
|
|
Packit Service |
21c75c |
if not repos:
|
|
Packit Service |
21c75c |
logger.warning(_('Could not find repository: %s'),
|
|
Packit Service |
21c75c |
repo_name)
|
|
Packit Service |
21c75c |
else:
|
|
Packit Service |
21c75c |
print_or_set(key, val, self.base.conf)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def _help(self, args=None):
|
|
Packit Service |
21c75c |
"""Output help information.
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
:param args: the command to output help information about. If
|
|
Packit Service |
21c75c |
*args* is an empty, general help will be output.
|
|
Packit Service |
21c75c |
"""
|
|
Packit Service |
21c75c |
arg = args[0] if isinstance(args, list) and len(args) > 0 else args
|
|
Packit Service |
21c75c |
msg = None
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
if arg:
|
|
Packit Service |
21c75c |
if arg == 'config':
|
|
Packit Service |
21c75c |
msg = _("""{} arg [value]
|
|
Packit Service |
21c75c |
arg: debuglevel, errorlevel, obsoletes, gpgcheck, assumeyes, exclude,
|
|
Packit Service |
21c75c |
repo_id.gpgcheck, repo_id.exclude
|
|
Packit Service |
21c75c |
If no value is given it prints the current value.
|
|
Packit Service |
21c75c |
If value is given it sets that value.""").format(arg)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
elif arg == 'help':
|
|
Packit Service |
21c75c |
msg = _("""{} [command]
|
|
Packit Service |
21c75c |
print help""").format(arg)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
elif arg in ['repo', 'repository']:
|
|
Packit Service |
21c75c |
msg = _("""{} arg [option]
|
|
Packit Service |
21c75c |
list: lists repositories and their status. option = [all | id | glob]
|
|
Packit Service |
21c75c |
enable: enable repositories. option = repository id
|
|
Packit Service |
21c75c |
disable: disable repositories. option = repository id""").format(arg)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
elif arg == 'resolvedep':
|
|
Packit Service |
21c75c |
msg = _("""{}
|
|
Packit Service |
21c75c |
resolve the transaction set""").format(arg)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
elif arg in ['transaction', 'ts']:
|
|
Packit Service |
21c75c |
msg = _("""{} arg
|
|
Packit Service |
21c75c |
list: lists the contents of the transaction
|
|
Packit Service |
21c75c |
reset: reset (zero-out) the transaction
|
|
Packit Service |
21c75c |
run: run the transaction""").format(arg)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
elif arg == 'run':
|
|
Packit Service |
21c75c |
msg = _("""{}
|
|
Packit Service |
21c75c |
run the transaction""").format(arg)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
elif arg in ['exit', 'quit']:
|
|
Packit Service |
21c75c |
msg = _("""{}
|
|
Packit Service |
21c75c |
exit the shell""").format(arg)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
if not msg:
|
|
Packit Service |
21c75c |
self.cli.optparser.print_help()
|
|
Packit Service |
21c75c |
msg = _("""Shell specific arguments:
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
config set config options
|
|
Packit Service |
21c75c |
help print help
|
|
Packit Service |
21c75c |
repository (or repo) enable, disable or list repositories
|
|
Packit Service |
21c75c |
resolvedep resolve the transaction set
|
|
Packit Service |
21c75c |
transaction (or ts) list, reset or run the transaction set
|
|
Packit Service |
21c75c |
run resolve and run the transaction set
|
|
Packit Service |
21c75c |
exit (or quit) exit the shell""")
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
print('\n' + msg)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def _repo(self, args=None):
|
|
Packit Service |
21c75c |
cmd = args[0] if args else None
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
if cmd in ['list', None]:
|
|
Packit Service |
21c75c |
self.onecmd('repolist ' + ' '.join(args[1:]))
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
elif cmd in ['enable', 'disable']:
|
|
Packit Service |
21c75c |
repos = self.cli.base.repos
|
|
Packit Service |
21c75c |
fill_sack = False
|
|
Packit Service |
21c75c |
for repo in args[1::]:
|
|
Packit Service |
21c75c |
r = repos.get_matching(repo)
|
|
Packit Service |
21c75c |
if r:
|
|
Packit Service |
21c75c |
getattr(r, cmd)()
|
|
Packit Service |
21c75c |
fill_sack = True
|
|
Packit Service |
21c75c |
else:
|
|
Packit Service |
21c75c |
logger.critical(_("Error:") + " " + _("Unknown repo: '%s'"),
|
|
Packit Service |
21c75c |
self.base.output.term.bold(repo))
|
|
Packit Service |
21c75c |
if fill_sack:
|
|
Packit Service |
21c75c |
self.base.fill_sack()
|
|
Packit Service |
21c75c |
|
|
Packit Service |
2bb387 |
# reset base._comps, as it has changed due to changing the repos
|
|
Packit Service |
2bb387 |
self.base._comps = None
|
|
Packit Service |
2bb387 |
|
|
Packit Service |
21c75c |
else:
|
|
Packit Service |
21c75c |
self._help('repo')
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def _resolve(self, args=None):
|
|
Packit Service |
21c75c |
try:
|
|
Packit Service |
21c75c |
self.cli.base.resolve(self.cli.demands.allow_erasing)
|
|
Packit Service |
21c75c |
except dnf.exceptions.DepsolveError as e:
|
|
Packit Service |
21c75c |
print(e)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def _run_script(self, file):
|
|
Packit Service |
21c75c |
try:
|
|
Packit Service |
21c75c |
with open(file, 'r') as fd:
|
|
Packit Service |
21c75c |
lines = fd.readlines()
|
|
Packit Service |
21c75c |
for line in lines:
|
|
Packit Service |
21c75c |
if not line.startswith('#'):
|
|
Packit Service |
21c75c |
self.onecmd(line)
|
|
Packit Service |
21c75c |
except IOError:
|
|
Packit Service |
21c75c |
logger.info(_('Error: Cannot open %s for reading'), self.base.output.term.bold(file))
|
|
Packit Service |
21c75c |
sys.exit(1)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def _transaction(self, args=None):
|
|
Packit Service |
21c75c |
cmd = args[0] if args else None
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
if cmd == 'reset':
|
|
Packit Service |
21c75c |
self._clean()
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
self._resolve()
|
|
Packit Service |
21c75c |
if cmd in ['list', None]:
|
|
Packit Service |
21c75c |
if self.base._transaction:
|
|
Packit Service |
21c75c |
out = self.base.output.list_transaction(self.base._transaction)
|
|
Packit Service |
21c75c |
logger.info(out)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
elif cmd == 'run':
|
|
Packit Service |
21c75c |
try:
|
|
Packit Service |
21c75c |
self.base.do_transaction()
|
|
Packit Service |
21c75c |
except dnf.exceptions.Error as e:
|
|
Packit Service |
21c75c |
logger.error(_("Error:") + " " + ucd(e))
|
|
Packit Service |
21c75c |
else:
|
|
Packit Service |
21c75c |
logger.info(_("Complete!"))
|
|
Packit Service |
21c75c |
self._clean()
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
else:
|
|
Packit Service |
21c75c |
self._help('transaction')
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def _ts_run(self, args=None):
|
|
Packit Service |
21c75c |
self._transaction(['run'])
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def _quit(self, args=None):
|
|
Packit Service |
21c75c |
logger.info(_('Leaving Shell'))
|
|
Packit Service |
21c75c |
sys.exit(0)
|