#
#  Copyright Bloomberg Finance LP
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#
#  This library 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
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
#  Authors:
#        Ed Baunton <ebaunton1@bloomberg.net>

"""
remote - stage files from remote urls
=====================================

**Usage:**

.. code:: yaml

   # Specify the remote source kind
   kind: remote

   # Optionally specify a relative staging filename.
   # If not specified, the basename of the url will be used.
   # filename: customfilename

   # Optionally specify whether the downloaded file should be
   # marked executable.
   # executable: true

   # Specify the url. Using an alias defined in your project
   # configuration is encouraged. 'bst track' will update the
   # sha256sum in 'ref' to the downloaded file's sha256sum.
   url: upstream:foo

   # Specify the ref. It's a sha256sum of the file you download.
   ref: 6c9f6f68a131ec6381da82f2bff978083ed7f4f7991d931bfa767b7965ebc94b

See :ref:`built-in functionality doumentation <core_source_builtins>` for
details on common configuration options for sources.

.. note::

   The ``remote`` plugin is available since :ref:`format version 10 <project_format_version>`
"""
import os
from buildstream import SourceError, utils
from ._downloadablefilesource import DownloadableFileSource


class RemoteSource(DownloadableFileSource):
    # pylint: disable=attribute-defined-outside-init

    def configure(self, node):
        super().configure(node)
        self.keyorder += ['filename']

        self.filename = self.node_get_member(node, str, 'filename', os.path.basename(self.url))
        self.executable = self.node_get_member(node, bool, 'executable', False)

        if os.sep in self.filename:
            raise SourceError('{}: filename parameter cannot contain directories'.format(self),
                              reason="filename-contains-directory")
        self.node_validate(node, DownloadableFileSource.COMMON_CONFIG_KEYS + ['filename', 'executable'])

    def get_unique_key(self):
        return super().get_unique_key() + [self.filename, self.executable]

    def stage(self, directory):
        # Same as in local plugin, don't use hardlinks to stage sources, they
        # are not write protected in the sandbox.
        dest = os.path.join(directory, self.filename)
        with self.timed_activity("Staging remote file to {}".format(dest)):

            utils.safe_copy(self._get_mirror_file(), dest)

            # To prevent user's umask introducing variability here, explicitly set
            # file modes.
            if self.executable:
                os.chmod(dest, 0o755)
            else:
                os.chmod(dest, 0o644)


def setup():
    return RemoteSource
