3 igE@sddlZddlZddlZddlZddlZddlZddlm Z m Z m Z ddl m Z mZddlmZmZmZddlmZddlmZmZmZmZmZmZmZejjZejjZej e!Z"ej#dZ$ej#dZ%ej#d ej&Z'e(e)d d d Z*Gd ddeZ+ej,e+dS)N)ListOptionalTuple) BadCommandInstallationError) HiddenText display_pathhide_url) make_command)AuthInfoRemoteNotFoundErrorRemoteNotValidError RevOptionsVersionControl(find_path_to_project_root_from_repo_rootvcsz(^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[^:]*) $)shareturncCsttj|S)N)bool HASH_REGEXmatch)rr4/tmp/pip-build-88gy_88q/pip/pip/_internal/vcs/git.pylooks_like_hash7srcseZdZdZdZdZd@ZdAZd Ze e e e d d dZ e e e dddZeedfdddZee ee dddZee e eee e fdddZee e e dddZee eeeddd Zee ee e d!d"d#Ze eed$dd%d&Ze eed$dd'd(Ze eed$dd)d*Zee e dd+d,Ze e e d-d.d/Zee e e d0d1d2Z edBe ee e d0d3d4Z!ee ee dd5d6Z"ee ee ee e#fd-fd7d8 Z$ee d$dd9d:Z%ee ee dfd;d< Z&e e e d=d>d?Z'Z(S)CGitgitz.gitclonegit+http git+httpsgit+sshgit+gitgit+fileGIT_DIR GIT_WORK_TREEHEAD)revrcCs|gS)Nr)r%rrrget_base_rev_argsKszGit.get_base_rev_args)urldestrcCsJ|jt|\}}|jsdS|j||js.dSt|j||jd}| S)NFr)Zget_url_rev_optionsr r%is_commit_id_equalrget_revision_sha)selfr'r(_ rev_optionsZis_tag_or_branchrrris_immutable_rev_checkoutOszGit.is_immutable_rev_checkout.)rcCsF|jdgddd}tj|}|s0tjd|fStdd|jDS)NversionFT) show_stdout stdout_onlyzCan't parse git version: %scss|]}t|VqdS)N)int).0crrr csz&Git.get_git_version..) run_commandGIT_VERSION_REGEXrloggerwarningtuplegroups)r+r/rrrrget_git_version]s   zGit.get_git_version)locationrcCsDdddg}|j|d dd|d}|j}|jdr@|tdd Sd S) zl Return the current branch, or None if HEAD isn't at a branch (e.g. detached HEAD). z symbolic-refz-qr$FT)extra_ok_returncodesr0r1cwdz refs/heads/N)r>)r6strip startswithlen)clsr=argsoutputrefrrrget_current_branches  zGit.get_current_branch)r(r%rc Cs|jd|g|dddd}i}xh|jjdD]V}|jd}|s@q,y|jdd d \}}Wn"tk rxtd |YnX|||<q,Wd |}d |} |j|} | dk r| dfS|j| } | dfS)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. zshow-refFTignore)r@r0r1 on_returncode   )maxsplitzunexpected show-ref line: zrefs/remotes/origin/z refs/tags/N)r6rAsplitrstrip ValueErrorget) rDr(r%rFrefslineZref_sharef_nameZ branch_refZtag_refrrrrr*~s.       zGit.get_revision_shacCs.|jdrdSt|sdS|j||r*dSdS)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``). zrefs/TF)rBr has_commit)rDr(r%rrr _should_fetchs  zGit._should_fetch)r(r'r-rcCs|j}|dk st|j||\}}|dk rF|j|}|r<|nd|_|St|sZtjd||j||sj|S|j t dd||j |d|j |dd}|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-q)r@Z FETCH_HEAD)r%) Zarg_revAssertionErrorr*make_new branch_namerr8r9rXr6r to_args get_revision)rDr(r'r-r%rZ is_branchrrrresolve_revisions&     zGit.resolve_revision)r(namercCs|sdS|j||kS)z Return whether the current commit hash equals the given name. Args: dest: the repository directory. name: a string name. F)r^)rDr(r`rrrr)s zGit.is_commit_id_equalNc Cs |j}tjd||t||jdkr@|jtddd||n|jtdd|||jr|j|||}t |dd}tj d|||dkr|j ||jstd d|j }|j||d n4|j ||krd |}d d |d |g}|j||d n|j|}|j|}tjd||j|j|dS)NzCloning %s%s to %srNrz--filter=blob:nonez-qr\zRev options %s, branch_name %scheckout)r@zorigin/z-bz--trackzResolved %s to commit %s)rNra)Z to_displayr8inforr<r6r r%r_getattrdebugr)r]rHr^r[update_submodules) r+r(r'r- rev_displayr\cmd_argsZ track_branchrrrr fetch_newsD       z Git.fetch_newcCsB|jtdd||dtdd|j}|j||d|j|dS)Nconfigzremote.origin.url)r@rbz-q)r6r r]rf)r+r(r'r-rhrrrswitch7s  z Git.switchcCsp|jd kr"|jdddg|dn|jddg|d|j|||}tddd|j}|j||d|j|dS) Nr> rYz-qz--tags)r@resetz--hard)r>rl)r<r6r_r r]rf)r+r(r'r-rhrrrupdateAs z Git.updatec Cs|jdddgd dd|d}|j}y |d}Wntk rFtYnXx|D]}|jd rN|}PqNW|jd d}|j|jS) z Return URL of the first remote encountered. Raises RemoteNotFoundError if the repository does not have a remote url configured. rjz --get-regexpzremote\..*\.urlr>FT)r?r0r1r@rzremote.origin.url rM)r>)r6 splitlines IndexErrorr rBrP_git_remote_to_pip_urlrA)rDr=stdoutremotes found_remoteremoter'rrrget_remote_urlOs"     zGit.get_remote_url)r'rcCsNtjd|r|Stjj|r*tj|jStj|}|rB|j dSt |dS)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) rerospathexistspathlibZPurePathZas_uri SCP_REGEXexpandr )r'Z scp_matchrrrrqms    zGit._git_remote_to_pip_url)r=r%rc Cs>y |jdddd|g|ddWntk r4dSXdSdS) zU Check if rev is a commit that is available in the local repository. z rev-parsez-qz--verifyzsha^F)r@log_failed_cmdTN)r6r)rDr=r%rrrrWs zGit.has_commitcCs*|dkr d}|jd|gdd|d}|jS)Nr$z rev-parseFT)r0r1r@)r6rA)rDr=r% current_revrrrr^szGit.get_revisioncCsT|jddgdd|dj}tjj|s4tjj||}tjjtjj|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. z rev-parsez --git-dirFT)r0r1r@z..)r6rArxryisabsjoinabspathr)rDr=git_dirZ repo_rootrrrget_subdirectorys  zGit.get_subdirectoryc st|\}}}}}|jdr|dt|jd }|tjj|jddjd}|jdd} |d| t || d||||f}d|krd|kst |jd d }t j |\}} } |jd d }nt j |\}} } || | fS) 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/\+r>z://zfile:zgit+z git+ssh://zssh://) urlsplitendswithrClstripurllibrequest url2pathnamereplacefind urlunsplitrZsuperget_url_rev_and_auth) rDr'schemenetlocryqueryfragmentinitial_slashesnewpath after_plusr% user_pass) __class__rrrs     zGit.get_url_rev_and_authcCs6tjjtjj|dsdS|jdddddg|ddS)Nz .gitmodules submodulernz--initz --recursivez-q)r@)rxryrzrr6)rDr=rrrrfs  zGit.update_submodulescsxtj|}|r|Sy|jddg|ddddd}Wn2tk rRtjd|dStk rddSXtjj |j dS) Nz rev-parsez--show-toplevelFTraise)r@r0r1rJr~zKcould not determine if %s is under git control because git is not availablez ) rget_repository_rootr6rr8rerrxrynormpathrQ)rDr=locr)rrrrs&  zGit.get_repository_root)repo_urlrcCsdS)zEIn either https or ssh form, requirements must be prefixed with git+.Tr)rrrrshould_add_vcs_url_prefixszGit.should_add_vcs_url_prefix)rrrr r!)r"r#)N))__name__ __module__ __qualname__r`dirname repo_nameschemesZ unset_environZdefault_arg_rev staticmethodstrrr&rr.rr2r< classmethodrrHr*rXrrr_r)rirkrnrvrqrWr^rr rrfrr __classcell__rr)rrr;s\ -+7  $r)-loggingos.pathrxr{rw urllib.parserurllib.requestZtypingrrrZpip._internal.exceptionsrrZpip._internal.utils.miscrrr Zpip._internal.utils.subprocessr Z pip._internal.vcs.versioncontrolr r r rrrrparserr getLoggerrr8compiler7rVERBOSEr|rrrrregisterrrrrs2 $    I