Re\@sddlmZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl m Z mZddlmZmZmZddlmZddlmZmZmZmZmZmZmZmZmZdd lm Z m!Z!dd l"m#Z#e#rvdd l$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-dd l.m/Z/ej0e1Z2d dZ3ddZ4e4ddZ5ddZ6ddZ7ddZ8Gddde9Z:Gddde9Z;Gddde9Z<dS))absolute_importN) pkg_resources)UninstallationError)bin_pybin_user)WINDOWScache_from_source uses_pycache) indent_log) FakeFileaskdist_in_usersite dist_is_local egg_link_pathis_localnormalize_pathrenamesrmtree)AdjacentTempDirectory TempDirectory)MYPY_CHECK_RUNNING) AnyCallableDictIterableIteratorListOptionalSetTuple) DistributioncCst|rt}nt}tjj||}|g}tr|j|d|j|d|r{|j|dn|j|d|S)zCreate the fully qualified name of the files created by {console,gui}_scripts for the given ``dist``. Returns the list of file names z.exez .exe.manifestz -script.pywz -script.py)r rrospathjoinrappend)dist script_nameis_guibin_direxe_namepaths_to_remover+/builddir/build/BUILDROOT/alt-python35-pip-20.2.4-5.el8.x86_64/opt/alt/python35/lib/python3.5/site-packages/pip/_internal/req/req_uninstall.py _script_names's   r-cs%tjfdd}|S)Nc?sEt}x5||D]$}||kr|j||VqWdS)N)setadd)argskwseenitem)fnr+r,unique?s    z_unique..unique) functoolswraps)r4r5r+)r4r,_unique=s!r8ccstjt|jd}x|D]}tjj|j|d}|V|jdr%tjj |\}}|dd}tjj||d}|Vtjj||d}|Vq%WdS) a Yield all the uninstallation paths for dist based on RECORD-without-.py[co] Yield paths to all the files in RECORD. For each .py file in RECORD, add the .pyc and .pyo in the same directory. UninstallPathSet.add() takes care of the __pycache__ .py[co]. RECORDrz.pyNz.pycz.pyo) csvreaderr get_metadata_linesr!r"r#locationendswithsplit)r%rrowr"dnr4baser+r+r,uninstallation_pathsJs  rFcsktjjt}xOt|dtD];tfdd|D}|s(|jq(W|S)zCompact a path set to contain the minimal number of paths necessary to contain all paths in the set. If /a/path/ and /a/path/to/a/file.txt are both in the set, leave only the shorter path.keyc3sO|]E}j|jdoFt|jdjkVqdS)*N) startswithrstriplen).0 shortpath)r"sepr+r, mszcompact..)r!r"rNr.sortedrKanyr/)paths short_paths should_skipr+)r"rNr,compactbs   rUc s^tdd|D}t|}ttdd|jDdt}t}ddx|D]tfdd|Drqlt}t}xltjD][\}}|jfdd|D|jfd d|DqW||sl|j ||j tj qlWtt |j ||BS) zReturns a set containing the paths that need to be renamed. This set may include directories when the original sequence of paths included every file on disk. css'|]}tjj||fVqdS)N)r!r"normcase)rLpr+r+r,rO}sz&compress_for_rename..css%|]}tjj|dVqdS)rN)r!r"rA)rLrWr+r+r,rOsrGcWstjjtjj|S)N)r!r"rVr#)ar+r+r, norm_joinsz&compress_for_rename..norm_joinc3s*|] }tjjj|VqdS)N)r!r"rVrI)rLw)rootr+r,rOsc3s!|]}|VqdS)Nr+)rLd)dirnamerYr[r+r,rOsc3s!|]}|VqdS)Nr+)rLf)r]rYr[r+r,rOs)dictr.rPvaluesrKrQr!walkupdatedifference_updater/rNmap __getitem__) rRcase_map remaining unchecked wildcards all_files all_subdirssubdirsfilesr+)r]rYr[r,compress_for_renamevs*          rnc Csvt|}t}t}t}xa|D]Y}|jdrFq.|jdsad|krz|jtjj||j|q.Wtttjj|}t|}x|D]}xtj |D]~\}} } xl| D]d} | jdrqtjj || } tjj | rtjj| |kr|j| qWqWqW|dd|DB}||fS)asReturns a tuple of 2 sets of which paths to display to user The first set contains paths that would be deleted. Files of a package are not added and the top-level directory of the package has a '*' added at the end - to signify that all it's contents are removed. The second set contains files that would have been skipped in the above folders. z.pycz __init__.pyz .dist-infocSs%h|]}tjj|dqS)rH)r!r"r#)rLfolderr+r+r, s z.compress_for_output_listing..) r.r@r/r!r"r]rdrVrUrar#isfile) rR will_remove will_skipfoldersrmr"_normcased_filesrodirpath_dirfilesfnamefile_r+r+r,compress_for_output_listings0          r{c@speZdZdZddZddZddZdd Zd d Zd d Z e ddZ dS)StashedUninstallPathSetzWA set of file rename operations to stash files while tentatively uninstalling them.cCsi|_g|_dS)N) _save_dirs_moves)selfr+r+r,__init__s z StashedUninstallPathSet.__init__c CsTyt|}Wn!tk r3tdd}YnX||jtjj|<|jS)zStashes a directory. Directories are stashed adjacent to their original location if possible, or else moved/copied into the user's temp dir.kind uninstall)rOSErrorrr}r!r"rV)rr"save_dirr+r+r,_get_directory_stashs  z,StashedUninstallPathSet._get_directory_stashc Cstjj|}tjj|d}}d}x~||kry|j|}PWntk rfYnXtjj||}}q4Wtjj|}tdd}||j|._displayz Would remove:z+Would not remove (might be manually added):z%Would not remove (outside of prefix):zWill actually move:zProceed (y/n)? yn)rr)r{rRr.rrnr )rrrrrrsr+r+r,rs    z$UninstallPathSet._allowed_to_proceedcCsq|jjs&tjd|jjdStjd|jj|jjx!|jj D]}|jqYWdS)z1Rollback the changes previously made by remove().z'Can't roll back %s; was not uninstalledNzRolling back uninstall of %s) rrrrr%rrrrr`)rrr+r+r,rs   zUninstallPathSet.rollbackcCs|jjdS)z?Remove temporary save dir: rollback will no longer be possible.N)rr)rr+r+r,rszUninstallPathSet.commitc s8t|j}t|sAtjd|j|tj||S|ddtj dtj dhDkrtjd|j|||S||}t |}dj t j |j}|jotjj|j}t|jdd}|rZ|jjd rZ|jj| rZ|j|j|jd rx|jd jD]7}tjjtjj|j|} |j| qXWq|jd r|jd r|jd ngx(fd d|jd jDD]^} tjj|j| } |j| |j| d|j| d|j| dqWn|r{tdj |jn||jjdr|j|jtjj|jd} tjjtjj|jd} |j| d| n|r0|jjdr0xt |D]} |j| qWn|rt!|d%} tjj"| j#j$}WdQRX||jkst%dj ||j|j|j|tjjtjj|d} |j| |jntj&d||j|jdr|j'drxt|j(dD]c}t)|r@t*}nt+}|jtjj||t,r%|jtjj||dq%Wg}|j-dd}x-|j.D]}|j/t0||dqW|j-dd }x-|j.D]}|j/t0||d!qWx|D]}|j|qW|S)"Nz1Not uninstalling %s at %s, outside environment %scSsh|]}|r|qSr+r+)rLrWr+r+r,rps z-UninstallPathSet.from_dist..stdlib platstdlibzs z.UninstallPathSet.from_dist..z.pyz.pycz.pyozCannot uninstall {!r}. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.z.eggrzeasy-install.pthz./z .dist-inforBz;Egg-link {} does not match installed location of {} (at {})z)Not sure how to uninstall: %s - Check: %sscriptsz.batgroupconsole_scriptsF gui_scriptsT)1rr?rrrrGsysprefix sysconfigget_pathrformatr to_filenameregg_infor!r"rgetattr _providerr@r/ has_metadata get_metadata splitlinesnormpathr#rrAr]rrFopenrVreadlinestripAssertionErrorrmetadata_isdirmetadata_listdirr rrr get_entry_mapkeysextendr-)clsr% dist_pathr*develop_egg_linkdevelop_egg_link_egg_infoegg_info_existsdistutils_egg_infoinstalled_filer" top_level_pkgeasy_install_eggeasy_install_pthfh link_pointerscriptr(_scripts_to_removernamersr+)rr, from_dists          %     $ zUninstallPathSet.from_distN)rrrrrrr/rrrrr classmethodrr+r+r+r,r@s       rc@s@eZdZddZddZddZddZd S) rcCs"||_t|_d|_dS)N)filer.entries _saved_lines)rrr+r+r,rJs  zUninstallPthEntries.__init__cCsUtjj|}trAtjj|d rA|jdd}|jj|dS)Nr\/)r!r"rVr splitdrivereplacerr/)rrr+r+r,r/Ps zUninstallPthEntries.addcCsZtjd|jtjj|js?tjd|jdSt|jd}|j}||_ WdQRXt dd|Drd}nd}|r|d j |j d  r|d |j d |d.z  rzutf-8zRemoving entry: %swbrr)rrrr!r"rqwarningr readlinesrrQr@encoderr ValueError writelines)rrlinesendlinerr+r+r,r`s*   #  zUninstallPthEntries.removec Csi|jdkr&tjd|jdStjd|jt|jd}|j|jWdQRXdS)Nz.Cannot roll back changes to %s, none were madeFz!Rolling %s back to previous staterT)rrrrrrr)rrr+r+r,r~s zUninstallPthEntries.rollbackN)rrrrr/rrr+r+r+r,rIs    r)= __future__rr<r6loggingr!rr pip._vendorrpip._internal.exceptionsrpip._internal.locationsrrpip._internal.utils.compatrrr pip._internal.utils.loggingr pip._internal.utils.miscr r r rrrrrrpip._internal.utils.temp_dirrrpip._internal.utils.typingrtypingrrrrrrrrrZpip._vendor.pkg_resourcesr getLoggerrrr-r8rFrUrnr{objectr|rrr+r+r+r,s8      @ @    ( 3o