U
    ;»{jG  ã                   @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZmZmZ d dlmZmZ d dlmZmZmZ d dlmZ d dlmZmZmZmZmZmZmZ ejj Z ejj!Z!e  "e#¡Z$e %d¡Z&e %d	¡Z'e %d
ej(¡Z)e*e+dœdd„Z,G dd„ deƒZ-e .e-¡ dS )é    N)Úreplace)ÚListÚOptionalÚTuple)Ú
BadCommandÚInstallationError)Ú
HiddenTextÚdisplay_pathÚhide_url)Úmake_command)ÚAuthInfoÚRemoteNotFoundErrorÚRemoteNotValidErrorÚ
RevOptionsÚVersionControlÚ(find_path_to_project_root_from_repo_rootÚvcsz(^git version (\d+)\.(\d+)(?:\.(\d+))?.*$z^[a-fA-F0-9]{40}$a/  ^
    # Optional user, e.g. 'git@'
    (\w+@)?
    # Server, e.g. 'github.com'.
    ([^/:]+):
    # The server-side path. e.g. 'user/project.git'. Must start with an
    # alphanumeric character so as not to be confusable with a Windows paths
    # like 'C:/foo/bar' or 'C:\foo\bar'.
    (\w[^:]*)
    $)ÚshaÚreturnc                 C   s   t t | ¡ƒS ©N)ÚboolÚ
HASH_REGEXÚmatch)r   © r   ú6/tmp/pip-install-zsn1f9xv/pip/pip/_internal/vcs/git.pyÚlooks_like_hash8   s    r   c                       s  e Zd ZdZdZdZdZdZdZe	e
ee
 dœdd	„ƒZe
e
ed
œdd„Zeedf dœdd„Zee
ee
 dœdd„ƒZee
e
eee
 ef dœdd„ƒZee
e
edœdd„ƒZee
eeedœdd„ƒZee
ee
 edœdd„ƒZe
eeedd œd!d"„Ze
eeddœd#d$„Ze
eeddœd%d&„Zee
e
dœd'd(„ƒZe	e
e
d)œd*d+„ƒZee
e
ed,œd-d.„ƒZ ed<e
ee
 e
d,œd/d0„ƒZ!ee
ee
 dœd1d2„ƒZ"ee
ee
ee
 e#f d)œ‡ fd3d4„ƒZ$ee
ddœd5d6„ƒZ%ee
ee
 dœ‡ fd7d8„ƒZ&e	e
ed9œd:d;„ƒZ'‡  Z(S )=ÚGitÚgitz.gitÚclone)zgit+httpz	git+httpszgit+sshzgit+gitzgit+file)ÚGIT_DIRÚGIT_WORK_TREEÚHEAD)Úrevr   c                 C   s   | gS r   r   ©r"   r   r   r   Úget_base_rev_argsL   s    zGit.get_base_rev_args)ÚurlÚdestr   c                 C   sJ   |   t|ƒ¡\}}|jsdS |  ||j¡s.dS t|  ||j¡d ƒ}| S )NFr   )Úget_url_rev_optionsr
   r"   Úis_commit_id_equalr   Úget_revision_sha)Úselfr%   r&   Ú_Úrev_optionsZis_tag_or_branchr   r   r   Úis_immutable_rev_checkoutP   s    zGit.is_immutable_rev_checkout.)r   c                 C   sN   | j dgdddd�}t |¡}|s2t d|¡ dS t| d¡ƒt| d	¡ƒfS )
NÚversionzgit versionFT)Úcommand_descÚshow_stdoutÚstdout_onlyzCan't parse git version: %sr   é   é   )Úrun_commandÚGIT_VERSION_REGEXr   ÚloggerÚwarningÚintÚgroup)r*   r.   r   r   r   r   Úget_git_version^   s    ü
zGit.get_git_version)Úlocationr   c                 C   sD   dddg}| j |ddd|d�}| ¡ }| d¡r@|tdƒd	… S d	S )
zl
        Return the current branch, or None if HEAD isn't at a branch
        (e.g. detached HEAD).
        zsymbolic-refú-qr!   ©r2   FT©Úextra_ok_returncodesr0   r1   Úcwdzrefs/heads/N)r4   ÚstripÚ
startswithÚlen)Úclsr;   ÚargsÚoutputÚrefr   r   r   Úget_current_branchk   s    

û
zGit.get_current_branch)r&   r"   r   c              	   C   sÂ   | j d|g|dddd�}i }| ¡  d¡D ]V}| d¡}|s>q*z|jdd	d
�\}}W n" tk
rv   td|›�ƒ‚Y nX |||< q*d|› �}d|› �}	| |¡}
|
dk	r°|
dfS | |	¡}
|
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-refFTÚignore)r@   r0   r1   Úon_returncodeÚ
úú r3   )Úmaxsplitzunexpected show-ref line: zrefs/remotes/origin/z
refs/tags/N)r4   rA   ÚsplitÚrstripÚ
ValueErrorÚget)rD   r&   r"   rF   ÚrefsÚlineZref_shaZref_nameÚ
branch_refÚtag_refr   r   r   r   r)   „   s0    û





zGit.get_revision_shac                 C   s.   |  d¡rdS t|ƒsdS |  ||¡r*dS d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)rB   r   Ú
has_commit)rD   r&   r"   r   r   r   Ú_should_fetch²   s    	
zGit._should_fetch)r&   r%   r,   r   c                 C   s¨   |j }|dk	st‚|  ||¡\}}|dk	rL| |¡}t||r@|ndd�}|S t|ƒs`t d|¡ |  ||¡sp|S | j	t
dd|| ¡ ƒ|d� | j|dd�}| |¡}|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.
        N)Úbranch_namez:Did not find branch or tag '%s', assuming revision or ref.Úfetchr<   ©r@   Ú
FETCH_HEADr#   )Úarg_revÚAssertionErrorr)   Úmake_newr   r   r6   r7   rX   r4   r   Úto_argsÚget_revision)rD   r&   r%   r,   r"   r   Ú	is_branchr   r   r   Úresolve_revisionÉ   s*    
þþ
zGit.resolve_revision)r&   Únamer   c                 C   s   |sdS |   |¡|kS )z§
        Return whether the current commit hash equals the given name.

        Args:
          dest: the repository directory.
          name: a string name.
        F)ra   )rD   r&   rd   r   r   r   r(   ÷   s    	zGit.is_commit_id_equalN)r&   r%   r,   Ú	verbosityr   c                 C   sJ  |  ¡ }t d||t|ƒ¡ |dkr*d}n|dkr8d}nd}|  ¡ dkrb|  td|||fžŽ ¡ n|  td|||fžŽ ¡ |j�r|  |||¡}t	|d
d ƒ}t 
d||¡ |d krà|  ||j¡sÞtdd| ¡ ƒ}| j||d� n6|  |¡|k�r,d|› �}	dd|d|	g}| j||d� n|  |¡}
| |
¡}t d||j¡ |  |¡ d S )NzCloning %s%s to %sr   )z--quietr2   r   )z	--verbosez
--progress)r3   é   r   ú--filter=blob:nonerY   zRev options %s, branch_name %sÚcheckoutr<   r[   zorigin/z-bz--trackzResolved %s to commit %s)r   rg   )r   )Ú
to_displayr6   Úinfor	   r:   r4   r   r"   rc   ÚgetattrÚdebugr(   r`   rH   ra   r_   Úupdate_submodules)r*   r&   r%   r,   re   Úrev_displayÚflagsrY   Úcmd_argsÚtrack_branchr   r   r   r   Ú	fetch_new  sX      þûÿ
ý
û

zGit.fetch_newc                 C   sB   | j tdd|ƒ|d� tdd| ¡ ƒ}| j ||d� |  |¡ d S )NÚconfigzremote.origin.urlr[   rh   r<   )r4   r   r`   rm   ©r*   r&   r%   r,   rp   r   r   r   ÚswitchE  s    
þz
Git.switchc                 C   sp   |   ¡ dkr"| jdddg|d� n| jddg|d� |  |||¡}tddd| ¡ ƒ}| j||d� |  |¡ d S )N)r2   é	   rZ   r<   z--tagsr[   Úresetz--hard)r:   r4   rc   r   r`   rm   rt   r   r   r   ÚupdateO  s    z
Git.updatec                 C   s€   | j dddgddd|d�}| ¡ }z|d }W n tk
rF   t‚Y nX |D ]}| d	¡rL|} qdqL| d
¡d }|  | ¡ ¡S )z¢
        Return URL of the first remote encountered.

        Raises RemoteNotFoundError if the repository does not have a remote
        url configured.
        rs   z--get-regexpzremote\..*\.urlr=   FTr>   r   zremote.origin.url rM   r2   )r4   Ú
splitlinesÚ
IndexErrorr   rB   rO   Ú_git_remote_to_pip_urlrA   )rD   r;   ÚstdoutÚremotesÚfound_remoteÚremoter%   r   r   r   Úget_remote_url]  s$    
û

zGit.get_remote_url)r%   r   c                 C   sN   t  d| ¡r| S tj | ¡r*t | ¡ ¡ S t | ¡}|rB| 	d¡S t
| ƒ‚dS )a8  
        Convert a remote url from what git uses to what pip accepts.

        There are 3 legal forms **url** may take:

            1. A fully qualified url: ssh://git@example.com/foo/bar.git
            2. A local project.git folder: /path/to/bare/repository.git
            3. SCP shorthand for form 1: git@example.com:foo/bar.git

        Form 1 is output as-is. Form 2 must be converted to URI and form 3 must
        be converted to form 1.

        See the corresponding test test_git_remote_url_to_pip() for examples of
        sample inputs/outputs.
        z\w+://zssh://\1\2/\3N)Úrer   ÚosÚpathÚexistsÚpathlibZPurePathZas_uriÚ	SCP_REGEXÚexpandr   )r%   Z	scp_matchr   r   r   r{   {  s    

zGit._git_remote_to_pip_url)r;   r"   r   c                 C   s@   z | j dddd| g|dd� W n tk
r6   Y dS X dS dS )	zU
        Check if rev is a commit that is available in the local repository.
        ú	rev-parser<   z--verifyzsha^F)r@   Úlog_failed_cmdTN)r4   r   )rD   r;   r"   r   r   r   rW   š  s    ý
zGit.has_commitc                 C   s*   |d krd}| j d|gdd|d�}| ¡ S )Nr!   rˆ   FT©r0   r1   r@   )r4   rA   )rD   r;   r"   Úcurrent_revr   r   r   ra   ª  s    üzGit.get_revisionc                 C   sT   | j ddgdd|d� ¡ }tj |¡s4tj ||¡}tj tj |d¡¡}t||ƒS )z‘
        Return the path to Python project root, relative to the repo root.
        Return None if the project root is in the repo root.
        rˆ   z	--git-dirFTrŠ   z..)r4   rA   r‚   rƒ   ÚisabsÚjoinÚabspathr   )rD   r;   Úgit_dirZ	repo_rootr   r   r   Úget_subdirectory¶  s    ü
zGit.get_subdirectoryc                    sâ   t |ƒ\}}}}}| d¡r†|dt| d¡ƒ … }|tj |¡ dd¡ d¡ }| d¡d }	|d|	… t	||	d… ||||fƒ }d|krÆd|ksšt
‚| d	d
¡}tƒ  |¡\}}
}| dd¡}ntƒ  |¡\}}
}||
|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.
        ÚfileNú/ú\ú+r2   z://zfile:zgit+z
git+ssh://zssh://Ú )ÚurlsplitÚendswithrC   ÚlstripÚurllibÚrequestÚurl2pathnamer   ÚfindÚ
urlunsplitr^   ÚsuperÚget_url_rev_and_auth)rD   r%   ÚschemeÚnetlocrƒ   ÚqueryÚfragmentÚinitial_slashesÚnewpathÚ
after_plusr"   Ú	user_pass©Ú	__class__r   r   rŸ   È  s(    

 ÿþÿzGit.get_url_rev_and_authc                 C   s6   t j t j |d¡¡sd S | jdddddg|d� d S )Nz.gitmodulesÚ	submodulerx   z--initz--recursiver<   r[   )r‚   rƒ   r„   r�   r4   )rD   r;   r   r   r   rm   ç  s    þzGit.update_submodulesc                    s|   t ƒ  |¡}|r|S z| jddg|ddddd�}W n6 tk
rT   t d|¡ Y d S  tk
rh   Y d S X tj 	| 
d¡¡S )	Nrˆ   z--show-toplevelFTÚraise)r@   r0   r1   rJ   r‰   zKcould not determine if %s is under git control because git is not availablez
)rž   Úget_repository_rootr4   r   r6   rl   r   r‚   rƒ   ÚnormpathrP   )rD   r;   ÚlocÚrr¨   r   r   r¬   ð  s*    ú
ýzGit.get_repository_root)Úrepo_urlr   c                 C   s   dS )zEIn either https or ssh form, requirements must be prefixed with git+.Tr   )r°   r   r   r   Úshould_add_vcs_url_prefix	  s    zGit.should_add_vcs_url_prefix)N))Ú__name__Ú
__module__Ú__qualname__rd   ÚdirnameÚ	repo_nameÚschemesÚunset_environÚdefault_arg_revÚstaticmethodÚstrr   r$   r   r-   r   r8   r:   Úclassmethodr   rH   r)   rX   r   r   rc   r(   rr   ru   rx   r€   r{   rW   ra   r�   r   rŸ   rm   r¬   r±   Ú__classcell__r   r   r¨   r   r   <   sd   	 -  þ-   þ?
$r   )/ÚloggingÚos.pathr‚   r…   r�   Úurllib.parser™   Úurllib.requestZdataclassesr   Útypingr   r   r   Úpip._internal.exceptionsr   r   Úpip._internal.utils.miscr   r	   r
   Zpip._internal.utils.subprocessr   Ú pip._internal.vcs.versioncontrolr   r   r   r   r   r   r   Úparser–   r�   Ú	getLoggerr²   r6   Úcompiler5   r   ÚVERBOSEr†   r»   r   r   r   Úregisterr   r   r   r   Ú<module>   s8   $

ÿ

õ   V