Return repo details for the specified saltenv as a namedtuple

def _get_repo_details(saltenv):
    '''
    Return repo details for the specified saltenv as a namedtuple
    '''
    contextkey = 'winrepo._get_repo_details.{0}'.format(saltenv)

    if contextkey in __context__:
        (winrepo_source_dir, local_dest, winrepo_file) = __context__[contextkey]
    else:
        winrepo_source_dir = __opts__['winrepo_source_dir']
        dirs = [__opts__['cachedir'], 'files', saltenv]
        url_parts = _urlparse(winrepo_source_dir)
        dirs.append(url_parts.netloc)
        dirs.extend(url_parts.path.strip('/').split('/'))
        local_dest = os.sep.join(dirs)

        winrepo_file = os.path.join(local_dest, 'winrepo.p')  # Default
        # Check for a valid windows file name
        if not re.search(r'[\/:*?"<>|]',
                         __opts__['winrepo_cachefile'],
                         flags=re.IGNORECASE):
            winrepo_file = os.path.join(
                local_dest,
                __opts__['winrepo_cachefile']
                )
        else:
            log.error(
                'minion configuration option \'winrepo_cachefile\' has been '
                'ignored as its value (%s) is invalid. Please ensure this '
                'option is set to a valid filename.',
                __opts__['winrepo_cachefile']
            )

        # Do some safety checks on the repo_path as its contents can be removed,
        # this includes check for bad coding
        system_root = os.environ.get('SystemRoot', r'C:\Windows')
        if not salt.utils.path.safe_path(
                path=local_dest,
                allow_path='\\'.join([system_root, 'TEMP'])):

            raise CommandExecutionError(
                'Attempting to delete files from a possibly unsafe location: '
                '{0}'.format(local_dest)
            )

        __context__[contextkey] = (winrepo_source_dir, local_dest, winrepo_file)

    try:
        os.makedirs(local_dest)
    except OSError as exc:
        if exc.errno != errno.EEXIST:
            raise CommandExecutionError(
                'Failed to create {0}: {1}'.format(local_dest, exc)
            )

    winrepo_age = -1
    try:
        stat_result = os.stat(winrepo_file)
        mtime = stat_result.st_mtime
        winrepo_age = time.time() - mtime
    except OSError as exc:
        if exc.errno != errno.ENOENT:
            raise CommandExecutionError(
                'Failed to get age of {0}: {1}'.format(winrepo_file, exc)
            )
    except AttributeError:
        # Shouldn't happen but log if it does
        log.warning('st_mtime missing from stat result %s', stat_result)
    except TypeError:
        # Shouldn't happen but log if it does
        log.warning('mtime of %s (%s) is an invalid type', winrepo_file, mtime)

    repo_details = collections.namedtuple(
        'RepoDetails',
        ('winrepo_source_dir', 'local_dest', 'winrepo_file', 'winrepo_age')
    )
    return repo_details(winrepo_source_dir, local_dest, winrepo_file, winrepo_age)