# Copyright 2005-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# Author(s): Brian Harring (ferringb@gentoo.org)

import os

from portage.cache import template


class FsBased(template.database):
    """template wrapping fs needed options, and providing _ensure_access as a way to
    attempt to ensure files have the specified owners/perms"""

    def __init__(self, *args, **config):
        for x, y in (("gid", -1), ("perms", 0o644)):
            if x in config:
                # Since Python 3.4, chown requires int type (no proxies).
                setattr(self, "_" + x, int(config[x]))
                del config[x]
            else:
                setattr(self, "_" + x, y)
        super().__init__(*args, **config)

        if self.label.startswith(os.path.sep):
            # normpath.
            self.label = os.path.sep + os.path.normpath(self.label).lstrip(os.path.sep)

    def _ensure_access(self, path, mtime=-1):
        """returns true or false if it's able to ensure that path is properly chmod'd and chowned.
        if mtime is specified, attempts to ensure that's correct also"""
        from portage.exception import PortageException
        from portage.util import apply_permissions

        try:
            apply_permissions(path, gid=self._gid, mode=self._perms)
            if mtime != -1:
                mtime = int(mtime)
                os.utime(path, (mtime, mtime))
        except (PortageException, OSError):
            return False
        return True

    def _ensure_dirs(self, path=None):
        """with path!=None, ensure beyond self.location.  otherwise, ensure self.location"""
        from portage.util import apply_permissions, ensure_dirs

        if path:
            path = os.path.dirname(path)
            base = self.location
        else:
            path = self.location
            base = "/"

        for d in path.lstrip(os.path.sep).rstrip(os.path.sep).split(os.path.sep):
            base = os.path.join(base, d)
            if ensure_dirs(base):
                # We only call apply_permissions if ensure_dirs created
                # a new directory, so as not to interfere with
                # permissions of existing directories.
                mode = self._perms
                if mode == -1:
                    mode = 0
                mode |= 0o755
                apply_permissions(base, mode=mode, gid=self._gid)

    def _prune_empty_dirs(self):
        all_dirs = []
        for parent, dirs, files in os.walk(self.location):
            for x in dirs:
                all_dirs.append(os.path.join(parent, x))
        while all_dirs:
            try:
                os.rmdir(all_dirs.pop())
            except OSError:
                pass


def gen_label(base, label):
    """if supplied label is a path, generate a unique label based upon label, and supplied base path"""
    if label.find(os.path.sep) == -1:
        return label
    label = label.strip('"').strip("'")
    label = os.path.join(*(label.rstrip(os.path.sep).split(os.path.sep)))
    tail = os.path.split(label)[1]
    return f"{tail}-{abs(label.__hash__()):X}"
