1# alias.py 2# Alias CLI command. 3# 4# Copyright (C) 2018 Red Hat, Inc. 5# 6# This copyrighted material is made available to anyone wishing to use, 7# modify, copy, or redistribute it subject to the terms and conditions of 8# the GNU General Public License v.2, or (at your option) any later version. 9# This program is distributed in the hope that it will be useful, but WITHOUT 10# ANY WARRANTY expressed or implied, including the implied warranties of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 12# Public License for more details. You should have received a copy of the 13# GNU General Public License along with this program; if not, write to the 14# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the 16# source code or documentation are not subject to the GNU General Public 17# License and may only be used or replicated with the express permission of 18# Red Hat, Inc. 19# 20 21from __future__ import absolute_import 22from __future__ import print_function 23from __future__ import unicode_literals 24 25import logging 26import os.path 27 28import dnf.cli 29import dnf.cli.aliases 30from dnf.cli import commands 31import dnf.conf 32import dnf.exceptions 33from dnf.i18n import _ 34 35logger = logging.getLogger('dnf') 36 37 38class AliasCommand(commands.Command): 39 aliases = ('alias',) 40 summary = _('List or create command aliases') 41 42 @staticmethod 43 def set_argparser(parser): 44 enable_group = parser.add_mutually_exclusive_group() 45 enable_group.add_argument( 46 '--enable-resolving', default=False, action='store_true', 47 help=_('enable aliases resolving')) 48 enable_group.add_argument( 49 '--disable-resolving', default=False, action='store_true', 50 help=_('disable aliases resolving')) 51 parser.add_argument("subcommand", nargs='?', default='list', 52 choices=['add', 'list', 'delete'], 53 help=_("action to do with aliases")) 54 parser.add_argument("alias", nargs="*", metavar="command[=result]", 55 help=_("alias definition")) 56 57 def configure(self): 58 demands = self.cli.demands 59 if self.opts.subcommand in ('add', 'delete'): 60 demands.root_user = True 61 self.aliases_base = dnf.cli.aliases.Aliases() 62 self.aliases_base._load_aliases() 63 self.resolving_enabled = self.aliases_base.enabled 64 self._update_config_from_options() 65 66 def _update_config_from_options(self): 67 enabled = None 68 if self.opts.enable_resolving: 69 enabled = True 70 logger.info(_("Aliases are now enabled")) 71 if self.opts.disable_resolving: 72 enabled = False 73 logger.info(_("Aliases are now disabled")) 74 75 if enabled is not None: 76 if not os.path.exists(dnf.cli.aliases.ALIASES_CONF_PATH): 77 open(dnf.cli.aliases.ALIASES_CONF_PATH, 'w').close() 78 dnf.conf.BaseConfig.write_raw_configfile( 79 dnf.cli.aliases.ALIASES_CONF_PATH, 80 'main', None, {'enabled': enabled}) 81 if not self.aliases_base._disabled_by_environ(): 82 self.aliases_base.enabled = enabled 83 84 def _parse_option_alias(self): 85 new_aliases = {} 86 for alias in self.opts.alias: 87 alias = alias.split('=', 1) 88 cmd = alias[0].strip() 89 if len(cmd.split()) != 1: 90 logger.warning(_("Invalid alias key: %s"), cmd) 91 continue 92 if cmd.startswith('-'): 93 logger.warning(_("Invalid alias key: %s"), cmd) 94 continue 95 if len(alias) == 1: 96 logger.warning(_("Alias argument has no value: %s"), cmd) 97 continue 98 new_aliases[cmd] = alias[1].split() 99 return new_aliases 100 101 def _load_user_aliases(self): 102 if not os.path.exists(dnf.cli.aliases.ALIASES_USER_PATH): 103 open(dnf.cli.aliases.ALIASES_USER_PATH, 'w').close() 104 try: 105 conf = dnf.cli.aliases.AliasesConfig( 106 dnf.cli.aliases.ALIASES_USER_PATH) 107 except dnf.exceptions.ConfigError as e: 108 logger.warning(_('Config error: %s'), e) 109 return None 110 return conf 111 112 def _store_user_aliases(self, user_aliases, enabled): 113 fileobj = open(dnf.cli.aliases.ALIASES_USER_PATH, 'w') 114 output = "[main]\n" 115 output += "enabled = {}\n\n".format(enabled) 116 output += "[aliases]\n" 117 for key, value in user_aliases.items(): 118 output += "{} = {}\n".format(key, ' '.join(value)) 119 fileobj.write(output) 120 121 def add_aliases(self, aliases): 122 conf = self._load_user_aliases() 123 user_aliases = conf.aliases 124 if user_aliases is None: 125 return 126 127 user_aliases.update(aliases) 128 129 self._store_user_aliases(user_aliases, conf.enabled) 130 logger.info(_("Aliases added: %s"), ', '.join(aliases.keys())) 131 132 def remove_aliases(self, cmds): 133 conf = self._load_user_aliases() 134 user_aliases = conf.aliases 135 if user_aliases is None: 136 return 137 138 valid_cmds = [] 139 for cmd in cmds: 140 try: 141 del user_aliases[cmd] 142 valid_cmds.append(cmd) 143 except KeyError: 144 logger.info(_("Alias not found: %s"), cmd) 145 146 self._store_user_aliases(user_aliases, conf.enabled) 147 logger.info(_("Aliases deleted: %s"), ', '.join(valid_cmds)) 148 149 def list_alias(self, cmd): 150 args = [cmd] 151 try: 152 args = self.aliases_base._resolve(args) 153 except dnf.exceptions.Error as e: 154 logger.error( 155 _('%s, alias %s="%s"'), e, cmd, (' ').join(self.aliases_base.aliases[cmd])) 156 else: 157 print(_("Alias %s='%s'") % (cmd, " ".join(args))) 158 159 def run(self): 160 if not self.aliases_base.enabled: 161 logger.warning(_("Aliases resolving is disabled.")) 162 163 if self.opts.subcommand == 'add': # Add new alias 164 aliases = self._parse_option_alias() 165 if not aliases: 166 raise dnf.exceptions.Error(_("No aliases specified.")) 167 self.add_aliases(aliases) 168 return 169 170 if self.opts.subcommand == 'delete': # Remove alias 171 cmds = self.opts.alias 172 if cmds == []: 173 raise dnf.exceptions.Error(_("No alias specified.")) 174 self.remove_aliases(cmds) 175 return 176 177 if not self.opts.alias: # List all aliases 178 if not self.aliases_base.aliases: 179 logger.info(_("No aliases defined.")) 180 return 181 for cmd in self.aliases_base.aliases: 182 self.list_alias(cmd) 183 else: # List alias by key 184 for cmd in self.opts.alias: 185 if cmd not in self.aliases_base.aliases: 186 logger.info(_("No match for alias: %s") % cmd) 187 continue 188 self.list_alias(cmd) 189