docs: 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)