# dput/configfile.py
# Part of ‘dput’, a Debian package upload toolkit.
#
# This is free software, and you are welcome to redistribute it under
# certain conditions; see the end of this file for copyright
# information, grant of license, and disclaimer of warranty.

""" Program configuration file functionality. """

import collections
import os.path
import sys

import xdg


class ConfigurationError(RuntimeError):
    """ Exception raised when failing to configure the program. """


default_config_paths = collections.OrderedDict([
        ('global', os.path.join(os.path.sep, "etc", "dput.cf")),
        ('user_xdg', os.path.join(
            xdg.xdg_config_home(), "dput", "dput.cf")),
        ('user_home', os.path.join(
            os.path.expanduser("~"), ".dput.cf")),
])


def active_config_files(config_path, debug):
    """ Yield the sequence of configuration files active for this process.

        :param config_path: Filesystem path of config file to read.
        :param debug: If true, enable debugging output.
        :return: Generator for the sequence of configuration files.
        :raise ConfigurationError: When none of the candidate configuration
            files can be opened.

        The `config_path` specifies a single candidate configuration file path
        to open. If `None`, instead use the default candidate files:

        * The global configuration file ‘/etc/dput.cf’.
        * The user configuration file:
          * $XDG_CONFIG_HOME/dput/dput.cf or, if that does not exist:
          * $HOME/.dput.cf

        Each file is open for reading when yielded in the sequence. When a
        candidate file fails to open (because it does not exist, the process
        does not have read permission to the file, etc.), that file is skipped.
        If all candidate files fail to open, raise `ConfigurationError`.
        """
    def candidate_config_paths(config_path, debug):
        if config_path:
            # Configuration file path explicitly specified to this process.
            yield config_path
        else:
            # Default configuration file paths.
            yield from default_config_paths.values()

    attempted_file_paths = []
    active_file_paths = []
    for infile_path in candidate_config_paths(config_path, debug):
        if not config_path:
            # Iterating through the default configuration paths.
            if (default_config_paths['user_xdg'] in active_file_paths):
                # We already have the standard user configuration file.
                if (infile_path == default_config_paths['user_home']):
                    # No need to try the deprecated location.
                    continue

        attempted_file_paths.append(infile_path)
        try:
            infile = open(infile_path, encoding='UTF-8')
        except OSError as exc:
            if debug:
                sys.stderr.write(
                        "{error}: skipping ‘{path}’\n".format(
                            error=str(exc), path=infile_path))
            continue
        active_file_paths.append(infile_path)
        yield infile

    if not active_file_paths:
        paths_text = ", ".join(
                "‘{0}’".format(path)
                for path in attempted_file_paths)
        raise ConfigurationError(
                "Could not open any configfile, tried {paths}".format(
                    paths=paths_text))


# Copyright © 2016–2024 Ben Finney <bignose@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty 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.


# Local variables:
# coding: utf-8
# mode: python
# End:
# vim: fileencoding=utf-8 filetype=python :
