
(h<                 @   s  d  d l  m Z d  d l Z d  d l Z d  d l Z d  d l m Z d  d l	 m Z
 d  d l	 m Z d  d l m Z m Z d  d l m Z m Z d  d l m Z d  d l m Z d  d	 l m Z d  d
 l m Z m Z m Z m Z e r$d  d l m Z m  Z  d  d l m! Z! d  d l m" Z" m# Z# e
 j$ Z$ e
 j% Z% e j& e'  Z( e j) d  Z* d d   Z+ Gd d   d e  Z, e j- e,  d S)    )absolute_importN)parse)request)
BadCommandInstallationError)display_pathhide_url)make_command)TempDirectory)MYPY_CHECK_RUNNING)RemoteNotFoundErrorVersionControl!find_path_to_setup_from_repo_rootvcs)OptionalTuple)
HiddenText)AuthInfo
RevOptionsz^[a-fA-F0-9]{40}$c             C   s   t  t j |    S)N)bool
HASH_REGEXmatch)sha r   4/tmp/pip-build-kmztzv_d/pip/pip/_internal/vcs/git.pylooks_like_hash+   s    r   c                   su  e  Z d  Z d Z d Z d Z d3 Z d4 Z d Z e	 d d    Z
 d d   Z d d   Z e d d    Z d d   Z e d d    Z e d d    Z e d d    Z e d d    Z d d   Z d  d!   Z d" d#   Z e d$ d%    Z e d& d'    Z e d( d) d*   Z e d+ d,    Z e   f d- d.    Z e d/ d0    Z e   f d1 d2    Z   S)5Gitgitz.gitclonegit+http	git+httpsgit+sshgit+gitgit+fileGIT_DIRGIT_WORK_TREEHEADc             C   s   |  g S)Nr   )revr   r   r   get_base_rev_args;   s    zGit.get_base_rev_argsc             C   se   |  j  t |   \ } } | j s( d S|  j | | j  sA d St |  j | | j  d  } | S)NFr   )Zget_url_rev_optionsr   r'   is_commit_id_equalr   get_revision_sha)selfurldest_rev_optionsZis_tag_or_branchr   r   r   is_immutable_rev_checkout?   s    	zGit.is_immutable_rev_checkoutc             C   s   d } |  j  d g d d d d } | j |  rV | t |  d   j   d } n d } d	 j | j d	  d  d
   } t |  S)Nzgit version versionshow_stdoutFstdout_onlyTr    .   )run_command
startswithlensplitjoinparse_version)r+   ZVERSION_PFXr1   r   r   r   get_git_versionP   s    #"zGit.get_git_versionc          
   C   si   d d d g } |  j  | d d d d d d	 d
 | } | j   } | j d  re | t d  d  Sd S)zl
        Return the current branch, or None if HEAD isn't at a branch
        (e.g. detached HEAD).
        zsymbolic-refz-qr&   extra_ok_returncodes   r2   Fr3   Tcwdzrefs/heads/N)r?   )r7   stripr8   r9   )clslocationargsoutputrefr   r   r   get_current_branch_   s    
	zGit.get_current_branchc             C   sw   | j  d  s | d } t d d  H } |  j | j d | |  j d d d d | g d	 d
 d | j Wd QRXd S)z@Export the Git repository at the url to the destination location/kindexportr,   zcheckout-indexz-az-fz--prefixr2   Fr@   N)endswithr
   unpackpathr7   )r+   rC   r,   temp_dirr   r   r   rJ   x   s    
z
Git.exportc       
      C   s   |  j  d | g d | d d d d d d } i  } xd | j   j   D]P } y | j   \ } } Wn' t k
 r t d	 j |    Yn X| | | <qF Wd
 j |  } d j |  }	 | j |  } | d k	 r | d f S| j |	  } | d f S)z
        Return (sha_or_none, is_branch), where sha_or_none is a commit hash
        if the revision names a remote branch or tag, otherwise None.

        Args:
          dest: the repository directory.
          rev: the revision name.
        zshow-refr@   r2   Fr3   Ton_returncodeignorezunexpected show-ref line: {!r}zrefs/remotes/origin/{}zrefs/tags/{}N)r7   rA   
splitlinesr:   
ValueErrorformatget)
rB   r-   r'   rE   refsliner   rF   Z
branch_refZtag_refr   r   r   r*      s(    	
zGit.get_revision_shac             C   s=   | j  d  r d St |  s# d S|  j | |  r9 d Sd S)a$  
        Return true if rev is a ref or is a commit that we don't have locally.

        Branches and tags are not considered in this method because they are
        assumed to be always available locally (which is a normal outcome of
        ``git clone`` and ``git fetch --tags``).
        zrefs/TF)r8   r   
has_commit)rB   r-   r'   r   r   r   _should_fetch   s    	zGit._should_fetchc             C   s   | j  } | d k	 s t  |  j | |  \ } } | d k	 rg | j |  } | rZ | n d | _ | St |  s t j d |  |  j | |  s | S|  j	 t
 d d | | j    d | |  j | d d } | j |  } | S)z
        Resolve a revision to a new RevOptions object with the SHA1 of the
        branch, tag, or ref if found.

        Args:
          rev_options: a RevOptions object.
        Nz:Did not find branch or tag '%s', assuming revision or ref.fetchz-qr@   r'   Z
FETCH_HEAD)Zarg_revAssertionErrorr*   Zmake_newbranch_namer   loggerwarningrX   r7   r	   to_argsget_revision)rB   r-   r,   r/   r'   r   Z	is_branchr   r   r   resolve_revision   s&    
	zGit.resolve_revisionc             C   s   | s
 d S|  j  |  | k S)z
        Return whether the current commit hash equals the given name.

        Args:
          dest: the repository directory.
          name: a string name.
        F)r_   )rB   r-   namer   r   r   r)      s    	zGit.is_commit_id_equalc             C   s   | j    } t j d | | t |   |  j t d d | |   | j r|  j | | |  } t | d d   } | d  k r |  j	 | | j  st d d | j
    } |  j | d | nL |  j |  | k rd j |  } d d | d	 | g } |  j | d | |  j |  d  S)
NzCloning %s%s to %sr   z-qr[   checkoutr@   z	origin/{}z-bz--track)Z
to_displayr\   infor   r7   r	   r'   r`   getattrr)   r^   rG   rS   update_submodules)r+   r-   r,   r/   rev_displayr[   cmd_argsZtrack_branchr   r   r   	fetch_new   s     	zGit.fetch_newc             C   s[   |  j  t d d |  d | t d d | j    } |  j  | d | |  j |  d  S)Nconfigzremote.origin.urlr@   rb   z-q)r7   r	   r^   re   )r+   r-   r,   r/   rg   r   r   r   switch  s    z
Git.switchc             C   s   |  j    t d  k r7 |  j d d d g d | n |  j d d g d | |  j | | |  } t d d d | j    } |  j | d | |  j |  d  S)Nz1.9.0rY   z-qz--tagsr@   resetz--hard)r=   r<   r7   r`   r	   r^   re   )r+   r-   r,   r/   rg   r   r   r   update)  s    z
Git.updatec             C   s   |  j  d d d g d d d d d d	 d
 | } | j   } y | d } Wn t k
 rd t  Yn Xx$ | D] } | j d  rl | } Pql W| j d  d } | j   S)z
        Return URL of the first remote encountered.

        Raises RemoteNotFoundError if the repository does not have a remote
        url configured.
        ri   z--get-regexpzremote\..*\.urlr>   r?   r2   Fr3   Tr@   r   zremote.origin.url  )r?   )r7   rQ   
IndexErrorr   r8   r:   rA   )rB   rC   stdoutremotesZfound_remoteZremoter,   r   r   r   get_remote_url8  s"    
	zGit.get_remote_urlc             C   sN   y- |  j  d d d d | g d | d d Wn t k
 rE d SYn Xd Sd	 S)
zU
        Check if rev is a commit that is available in the local repository.
        z	rev-parsez-qz--verifyzsha^r@   log_failed_cmdFTN)r7   r   )rB   rC   r'   r   r   r   rW   V  s    	zGit.has_commitNc             C   sC   | d  k r d } |  j  d | g d d d d d | } | j   S)Nr&   z	rev-parser2   Fr3   Tr@   )r7   rA   )rB   rC   r'   current_revr   r   r   r_   f  s    	zGit.get_revisionc             C   s   |  j  d d g d d d d d | j   } t j j |  sT t j j | |  } t j j t j j | d   } t | |  S)	z~
        Return the path to setup.py, relative to the repo root.
        Return None if setup.py is in the repo root.
        z	rev-parsez	--git-dirr2   Fr3   Tr@   z..)r7   rA   osrM   isabsr;   abspathr   )rB   rC   git_dirZ	repo_rootr   r   r   get_subdirectoryr  s    !zGit.get_subdirectoryc                sL  t  |  \ } } } } } | j d  r | d t | j d    } | t j |  j d d  j d  } | j d  d }	 | d |	  t | |	 d  | | | | f  } d | k rd | k s t	  | j d	 d
  } t
 t |   j |  \ } }
 } | j d d  } n! t
 t |   j |  \ } }
 } | |
 | f S)a9  
        Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'.
        That's required because although they use SSH they sometimes don't
        work with a ssh:// scheme (e.g. GitHub). But we need a scheme for
        parsing. Hence we remove it again afterwards and return it as a stub.
        fileNrH   \+r?   z://zfile:zgit+z
git+ssh://zssh://r4   )urlsplitrK   r9   lstripurllib_requesturl2pathnamereplacefind
urlunsplitrZ   superr   get_url_rev_and_auth)rB   r,   schemenetlocrM   queryfragmentinitial_slashesnewpath
after_plusr'   	user_pass)	__class__r   r   r     s      #!!zGit.get_url_rev_and_authc             C   sK   t  j j t  j j | d   s% d  S|  j d d d d d g d | d  S)Nz.gitmodules	submodulerl   z--initz--recursivez-qr@   )rt   rM   existsr;   r7   )rB   rC   r   r   r   re     s
    !zGit.update_submodulesc                s   t  t |   j |  } | r" | Sy7 |  j d d g d | d d d d d d	 d
 d } Wn; t k
 r t j d |  d  SYn t k
 r d  SYn Xt j	 j
 | j d   S)Nz	rev-parsez--show-toplevelr@   r2   Fr3   TrO   raiserr   zKcould not determine if %s is under git control because git is not availablez
)r   r   get_repository_rootr7   r   r\   debugr   rt   rM   normpathrstrip)rB   rC   locr)r   r   r   r     s$    		zGit.get_repository_root)zgitr   r    r!   r"   r#   )r$   r%   )__name__
__module____qualname__ra   dirname	repo_nameschemesZunset_environZdefault_arg_revstaticmethodr(   r0   r=   classmethodrG   rJ   r*   rX   r`   r)   rh   rj   rl   rq   rW   r_   rx   r   re   r   r   r   )r   r   r   /   s4   (-"	r   ).
__future__r   loggingos.pathrt   reZpip._vendor.packaging.versionr   r<   Zpip._vendor.six.moves.urlliburllib_parser   r~   Zpip._internal.exceptionsr   r   Zpip._internal.utils.miscr   r   Zpip._internal.utils.subprocessr	   Zpip._internal.utils.temp_dirr
   Zpip._internal.utils.typingr   Z pip._internal.vcs.versioncontrolr   r   r   r   Ztypingr   r   r   r   r   r|   r   	getLoggerr   r\   compiler   r   r   registerr   r   r   r   <module>   s0   "		 