File Explorer

/proc/self/root/proc/thread-self/root/proc/self/root/lib/python3.9/site-packages/dnf/cli

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

aliases.py7.0 KB · 211 lines
# aliases.py# Resolving aliases in CLI arguments.## Copyright (C) 2018 Red Hat, Inc.## This copyrighted material is made available to anyone wishing to use,# modify, copy, or redistribute it subject to the terms and conditions of# the GNU General Public License v.2, or (at your option) any later version.# This program is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY expressed or implied, including the implied warranties of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General# Public License for more details.  You should have received a copy of the# GNU General Public License along with this program; if not, write to the# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the# source code or documentation are not subject to the GNU General Public# License and may only be used or replicated with the express permission of# Red Hat, Inc.# from __future__ import absolute_importfrom __future__ import unicode_literalsfrom dnf.i18n import _ import collectionsimport dnf.clifrom dnf.conf.config import PRIO_DEFAULTimport dnf.exceptionsimport libdnf.confimport loggingimport osimport os.path logger = logging.getLogger('dnf') ALIASES_DROPIN_DIR = '/etc/dnf/aliases.d/'ALIASES_CONF_PATH = os.path.join(ALIASES_DROPIN_DIR, 'ALIASES.conf')ALIASES_USER_PATH = os.path.join(ALIASES_DROPIN_DIR, 'USER.conf')  class AliasesConfig(object):    def __init__(self, path):        self._path = path        self._parser = libdnf.conf.ConfigParser()        self._parser.read(self._path)     @property    def enabled(self):        option = libdnf.conf.OptionBool(True)        try:            option.set(PRIO_DEFAULT, self._parser.getData()["main"]["enabled"])        except IndexError:            pass        return option.getValue()     @property    def aliases(self):        result = collections.OrderedDict()        section = "aliases"        if not self._parser.hasSection(section):            return result        for key in self._parser.options(section):            value = self._parser.getValue(section, key)            if not value:                continue            result[key] = value.split()        return result  class Aliases(object):    def __init__(self):        self.aliases = collections.OrderedDict()        self.conf = None        self.enabled = True         if self._disabled_by_environ():            self.enabled = False            return         self._load_main()         if not self.enabled:            return         self._load_aliases()     def _disabled_by_environ(self):        option = libdnf.conf.OptionBool(True)        try:            option.set(PRIO_DEFAULT, os.environ['DNF_DISABLE_ALIASES'])            return option.getValue()        except KeyError:            return False        except RuntimeError:            logger.warning(                _('Unexpected value of environment variable: '                  'DNF_DISABLE_ALIASES=%s'), os.environ['DNF_DISABLE_ALIASES'])            return True     def _load_conf(self, path):        try:            return AliasesConfig(path)        except RuntimeError as e:            raise dnf.exceptions.ConfigError(                _('Parsing file "%s" failed: %s') % (path, e))        except IOError as e:            raise dnf.exceptions.ConfigError(                _('Cannot read file "%s": %s') % (path, e))     def _load_main(self):        try:            self.conf = self._load_conf(ALIASES_CONF_PATH)            self.enabled = self.conf.enabled        except dnf.exceptions.ConfigError as e:            logger.debug(_('Config error: %s'), e)     def _load_aliases(self, filenames=None):        if filenames is None:            try:                filenames = self._dropin_dir_filenames()            except dnf.exceptions.ConfigError:                return        for filename in filenames:            try:                conf = self._load_conf(filename)                if conf.enabled:                    self.aliases.update(conf.aliases)            except dnf.exceptions.ConfigError as e:                logger.warning(_('Config error: %s'), e)     def _dropin_dir_filenames(self):        # Get default aliases config filenames:        #   all files from ALIASES_DROPIN_DIR,        #   and ALIASES_USER_PATH as the last one (-> override all others)        ignored_filenames = [os.path.basename(ALIASES_CONF_PATH),                             os.path.basename(ALIASES_USER_PATH)]         def _ignore_filename(filename):            return filename in ignored_filenames or\                filename.startswith('.') or\                not filename.endswith(('.conf', '.CONF'))         filenames = []        try:            if not os.path.exists(ALIASES_DROPIN_DIR):                os.mkdir(ALIASES_DROPIN_DIR)            for fn in sorted(os.listdir(ALIASES_DROPIN_DIR)):                if _ignore_filename(fn):                    continue                filenames.append(os.path.join(ALIASES_DROPIN_DIR, fn))        except (IOError, OSError) as e:            raise dnf.exceptions.ConfigError(e)        if os.path.exists(ALIASES_USER_PATH):            filenames.append(ALIASES_USER_PATH)        return filenames     def _resolve(self, args):        stack = []        self.prefix_options = []         def store_prefix(args):            num = 0            for arg in args:                if arg and arg[0] != '-':                    break                num += 1             self.prefix_options += args[:num]             return args[num:]         def subresolve(args):            suffix = store_prefix(args)             if (not suffix or  # Current alias on stack is resolved                    suffix[0] not in self.aliases or  # End resolving                    suffix[0].startswith('\\')):  # End resolving                try:                    stack.pop()                     # strip the '\' if it exists                    if suffix[0].startswith('\\'):                        suffix[0] = suffix[0][1:]                except IndexError:                    pass                 return suffix             if suffix[0] in stack:  # Infinite recursion detected                raise dnf.exceptions.Error(                    _('Aliases contain infinite recursion'))             # Next word must be an alias            stack.append(suffix[0])            current_alias_result = subresolve(self.aliases[suffix[0]])            if current_alias_result:  # We reached non-alias or '\'                return current_alias_result + suffix[1:]            else:  # Need to resolve aliases in the rest                return subresolve(suffix[1:])         suffix = subresolve(args)        return self.prefix_options + suffix     def resolve(self, args):        if self.enabled:            try:                args = self._resolve(args)            except dnf.exceptions.Error as e:                logger.error(_('%s, using original arguments.'), e)        return args