def __init__(self, opts, remote, per_remote_defaults,
                 override_params, cache_root, role='gitfs'):
        self.opts = opts
        self.role = role
        self.env_blacklist = self.opts.get(
            '{0}_env_blacklist'.format(self.role), [])
        self.env_whitelist = self.opts.get(
            '{0}_env_whitelist'.format(self.role), [])
        repo_conf = copy.deepcopy(per_remote_defaults)

        per_remote_collisions = [x for x in override_params
                                 if x in PER_REMOTE_ONLY]
        if per_remote_collisions:
            log.critical(
                'The following parameter names are restricted to per-remote '
                'use only: {0}. This is a bug, please report it.'.format(
                    ', '.join(per_remote_collisions)
                )
            )

        try:
            valid_per_remote_params = override_params + PER_REMOTE_ONLY
        except __HOLE__:
            valid_per_remote_params = \
                list(override_params) + list(PER_REMOTE_ONLY)

        if isinstance(remote, dict):
            self.id = next(iter(remote))
            self.get_url()
            per_remote_conf = dict(
                [(key, six.text_type(val)) for key, val in
                 six.iteritems(salt.utils.repack_dictlist(remote[self.id]))]
            )
            if not per_remote_conf:
                log.critical(
                    'Invalid per-remote configuration for {0} remote \'{1}\'. '
                    'If no per-remote parameters are being specified, there '
                    'may be a trailing colon after the URL, which should be '
                    'removed. Check the master configuration file.'
                    .format(self.role, self.id)
                )
                failhard(self.role)

            # Separate the per-remote-only (non-global) parameters
            per_remote_only = {}
            for param in PER_REMOTE_ONLY:
                if param in per_remote_conf:
                    per_remote_only[param] = per_remote_conf.pop(param)

            per_remote_errors = False
            for param in (x for x in per_remote_conf
                          if x not in valid_per_remote_params):
                if param in AUTH_PARAMS \
                        and self.provider not in AUTH_PROVIDERS:
                    msg = (
                        '{0} authentication parameter \'{1}\' (from remote '
                        '\'{2}\') is only supported by the following '
                        'provider(s): {3}. Current {0}_provider is \'{4}\'.'
                        .format(
                            self.role,
                            param,
                            self.id,
                            ', '.join(AUTH_PROVIDERS),
                            self.provider
                        )
                    )
                    if self.role == 'gitfs':
                        msg += (
                            'See the GitFS Walkthrough in the Salt '
                            'documentation for further information.'
                        )
                    log.critical(msg)
                else:
                    msg = (
                        'Invalid {0} configuration parameter \'{1}\' in '
                        'remote {2}. Valid parameters are: {3}.'.format(
                            self.role,
                            param,
                            self.url,
                            ', '.join(valid_per_remote_params)
                        )
                    )
                    if self.role == 'gitfs':
                        msg += (
                            ' See the GitFS Walkthrough in the Salt '
                            'documentation for further information.'
                        )
                    log.critical(msg)

                per_remote_errors = True
            if per_remote_errors:
                failhard(self.role)

            repo_conf.update(per_remote_conf)
            repo_conf.update(per_remote_only)
        else:
            self.id = remote
            self.get_url()

        # Winrepo doesn't support the 'root' option, but it still must be part
        # of the GitProvider object because other code depends on it. Add it as
        # an empty string.
        if 'root' not in repo_conf:
            repo_conf['root'] = ''

        if self.role == 'winrepo' and 'name' not in repo_conf:
            # Ensure that winrepo has the 'name' parameter set if it wasn't
            # provided. Default to the last part of the URL, minus the .git if
            # it is present.
            repo_conf['name'] = self.url.rsplit('/', 1)[-1]
            # Remove trailing .git from name
            if repo_conf['name'].lower().endswith('.git'):
                repo_conf['name'] = repo_conf['name'][:-4]

        # Set all repo config params as attributes
        for key, val in six.iteritems(repo_conf):
            setattr(self, key, val)

        if hasattr(self, 'mountpoint'):
            self.mountpoint = salt.utils.url.strip_proto(self.mountpoint)
        else:
            # For providers which do not use a mountpoint, assume the
            # filesystem is mounted at the root of the fileserver.
            self.mountpoint = ''

        if not isinstance(self.url, six.string_types):
            log.critical(
                'Invalid {0} remote \'{1}\'. Remotes must be strings, you '
                'may need to enclose the URL in quotes'.format(
                    self.role,
                    self.id
                )
            )
            failhard(self.role)

        hash_type = getattr(hashlib, self.opts.get('hash_type', 'md5'))
        self.hash = hash_type(self.id).hexdigest()
        self.cachedir_basename = getattr(self, 'name', self.hash)
        self.cachedir = os.path.join(cache_root, self.cachedir_basename)
        if not os.path.isdir(self.cachedir):
            os.makedirs(self.cachedir)

        try:
            self.new = self.init_remote()
        except Exception as exc:
            msg = ('Exception caught while initializing {0} remote \'{1}\': '
                   '{2}'.format(self.role, self.id, exc))
            if isinstance(self, GitPython):
                msg += ' Perhaps git is not available.'
            log.critical(msg, exc_info_on_loglevel=logging.DEBUG)
            failhard(self.role)
dataset/ETHPy150Open saltstack/salt/salt/utils/gitfs.py/GitProvider.__init__