3 ÅÀfZvã@sÄddlmZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddlZddl m Z m Z ddlZddlmZddlmZddlZy$ddlmZmZmZmZdd„ZWnLek �rd d „Zydd lmZWnek rþd d„ZYnXYnXd Zee dƒe dƒgƒZee dƒe dƒdgƒZe�rdddl m!Z!m"Z"m#Z#ddl$m%Z%m&Z&m'Z'n(ddl!m!Z!m"Z"m#Z#ddl(m%Z%m&Z&m'Z'ej)j*Gdd„dej+j,ƒƒZ-ej)j*Gdd„de-ƒƒZ.dS)é)Úprint_functionN)Ú_Úlogger)ÚPY3)Úucd)ÚnameÚversionÚcodenameÚos_release_attrcCstƒtƒtƒfS)N)rrr ©r r ú/usr/lib/python3.6/copr.pyÚlinux_distribution.sr cCsdS)NÚr )rr r r r 1sr )r cCsrtdƒ�`}i}xF|D]>}y$|jƒjdƒ\}}|jdƒ||<Wqtk rPYqXqW|d|ddfSQRXdS)Nz/etc/os-releaseú=ú"ÚNAMEZ VERSION_ID)ÚopenÚrstripÚsplitÚstripÚ ValueError)Zos_release_fileZos_release_dataÚlineZos_release_keyZos_release_valuer r r r 7s   ÚcoprÚyesÚyÚnoÚnr)Ú ConfigParserÚ NoOptionErrorÚNoSectionError)ÚurlopenÚ HTTPErrorÚURLErrorc@s eZdZdZdZdZdZdZdZedeZ d8Z e d ƒZ d Z e d ƒZed d „ƒZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Zed$d%„ƒZd&d'„Zd(d)„Zd*d+„Z d,d-„Z!d.d/„Z"d0d1„Z#ed2d3„ƒZ$ed4d5„ƒZ%ed6d7„ƒZ&dS)9Ú CoprCommandz Copr plugin for DNF Nzcopr.fedorainfracloud.orgZfedoraZhttpsi»z://rz Interact with Copr repositories.Ta” enable name/project [chroot] disable name/project remove name/project list --installed/enabled/disabled list --available-by-user=NAME search project Examples: copr enable rhscl/perl516 epel-6-x86_64 copr enable ignatenkobrain/ocltoys copr disable rhscl/perl516 copr remove rhscl/perl516 copr list --enabled copr list --available-by-user=ignatenkobrain copr search tests c Cs˜|jddddddddgd �|jƒ}|jd d td ƒd �|jdd tdƒd �|jdd tdƒd �|jddtdƒd�|jdtdƒd�|jddd�dS)NÚ subcommandéÚhelpÚenableÚdisableÚremoveÚlistÚsearch)ÚnargsÚchoicesz --installedÚ store_truez.List all installed Copr repositories (default))Úactionr&z --enabledzList enabled Copr repositoriesz --disabledzList disabled Copr repositoriesz--available-by-userrz-List available Copr repositories by user NAME)Úmetavarr&z--hubz(Specify an instance of Copr to work with)r&ÚargÚ*)r,)Ú add_argumentZadd_mutually_exclusive_groupr)ÚparserZ list_optionr r r Ú set_argparserps    zCoprCommand.set_argparsercCsŽ|jjjjdkrdSd}tƒ}g}|jjjd}tjj |t dƒ}tjj |ƒr¨|j |ƒ|j |ƒ|jddƒrž|jddƒrž|jddƒ}|jddƒ}||g|_n ddg|_xHtjtjj |t dƒƒD],}|jdƒrÂtjj |t d|ƒ} |j | ƒqÂWg} t|jjƒ�r|jjdjd ƒ} t| ƒd k�rV|jj�rVtjtd ƒtd ƒƒtjjtd ƒƒ‚nL|jj �r‚t| ƒd k�r‚|j|_|j|_n t| ƒd k�rš| d}n|jj}|�rH|�rHd|_|j t |dd�ƒ|j!||ddƒ} | �rH|j!||d|j"ƒ} |j!||d|j#ƒ} | |_| d| |_t$| ƒ|j#k�rH|jd| 7_|jd| 7_|j�sŠd|k�rr||_|j"d||_n|jddƒd|_||_dS)Nrrz.confÚmainÚ distributionÚ releaseverFz.dú/ézError: z^specify Copr hub either with `--hub` or using `copr_hub/copr_username/copr_projectname` formatzmultiple hubs specifiedT)ÚreverseÚhostnameÚprotocolÚportz://ú:r%)%ÚcliZcommandÚoptsrÚbaseÚconfZpluginconfpathÚosÚpathÚjoinÚ PLUGIN_CONFÚisfileÚappendÚreadZ has_optionÚgetÚ chroot_configÚlistdirÚendswithÚlenr1rÚhubrÚcriticalrÚdnfÚCliErrorÚdefault_hostnameÚ copr_hostnameÚ default_urlÚcopr_urlÚsortedÚ_read_config_itemÚdefault_protocolÚ default_portÚint)ÚselfZcopr_hubZcopr_plugin_configZ config_filesZ config_pathZdefault_config_filer7r8ÚfilenameZ config_fileÚprojectr<r=r>r r r Ú configure„sl                 zCoprCommand.configurec Cs*y |j||ƒSttfk r$|SXdS)N)rKrr)r]ÚconfigrPZsectionÚdefaultr r r rYÐs zCoprCommand._read_config_itemcCstjjdj|jƒƒƒdS)Nz{0} )ÚsysÚstderrÚwriteÚformatr)r]Útextr r r Ú_user_warning_before_promptÖsz'CoprCommand._user_warning_before_promptc Csä|jjd}|dkr&|jjj|ƒdS|dkrl|jjrH|j|jjƒdS|j|jj j d|jj |jj ƒdSy|jj d}WnLttfk rÈtjtdƒtdƒƒ|jjj|ƒtjjtdƒƒ‚YnXy\|jj d}t|jj ƒdkrøtjjtdƒƒ‚|jd ƒ|_t|jƒd k�r$tjjtd ƒƒ‚Wn*tk �rP|jƒ}|jd ƒ|_YnX|d k�rj|j|ƒdS|jd ƒ}t|ƒdk�rªtjtdƒtdƒƒtjjtdƒƒ‚nexactly two additional parameters to copr command are requiredr%ézToo many arguments.ú-r:zOBad format of optional chroot. The format is distribution-version-architecture.r+r9zEuse format `copr_username/copr_projectname` to reference copr projectzbad copr project formatz{0}/_copr:{1}:{2}:{3}.repor'a Enabling a Copr repository. Please note that this repository is not part of the main distribution, and quality may vary. The Fedora Project does not exercise any power over the contents of this repository beyond the rules outlined in the Copr FAQ at , and packages are not held to any quality or security level. Please do not file bug reports about these packages in Fedora Bugzilla. In case of problems, contact the owner of this repository. z!Do you really want to enable {0}?z Repository successfully enabled.r(z!Repository successfully disabled.r)z Repository successfully removed.zUnknown subcommand {}.)rir:)(rAr$r@Z optparserZ print_helpZavailable_by_userÚ_list_user_projectsÚ_list_installed_repositoriesrBrCZreposdirÚenabledZdisabledr1rÚ IndexErrorrrQrrRrSrOÚ exceptionsÚErrorrÚ chroot_partsÚ _guess_chrootÚ_searchrfÚ get_reposdirrUÚ_sanitize_usernameÚ _need_rootrFÚ _ask_userÚ_download_repoÚinfoÚ_runtime_deps_warningÚ _disable_repoÚ _remove_repo) r]r$Ú project_nameÚchrootr_Ú copr_usernameÚcopr_projectnameÚ repo_filenameryÚmsgr r r ÚrunÙsŠ                     zCoprCommand.runcCsˆ|jjdƒd}tjd|j|ƒ}|j|jko8tjd|ƒ}tjd|ƒ}|jjr`| rh| rhdSn|shdStjd|ƒrxdStjd|ƒrˆdS|j } | r–|s | r¤|r¤dSd} tjd |ƒrÞ|jd d ƒ\} } } }| d| d|}n‚tjd|ƒ�r2|jd dƒ}|j d d ƒdjd dƒd} | d|dd|d}n.|jd dƒ}|j d|dd|d}d} | �sn|d7}| �r||d7}t |ƒ| S)Nr9r%z_copr:Z_copr_z_copr:|^_copr_zcopr:.*:.*:.*:mlz coprdep:.*Fzcopr:r?r:rjrirTz (disabled)z *éÿÿÿÿ) ÚrepofilerÚreÚmatchrUrWrVrArPrmÚrsplitrTÚprint)r]Úrepo_idÚrepoÚ enabled_onlyÚ disabled_onlyÚ file_nameZ match_newZ match_oldZ match_anyrmÚold_reporrUZ copr_ownerZcopr_dirr‚Z copr_namer r r Ú_list_repo_file8sB       zCoprCommand._list_repo_filecCsFd}x,|jjjƒD]\}}|j||||ƒrd}qW|rBttdƒƒdS)NFTz�* These coprs have repo file with an old format that contains no information about Copr hub - the default one was assumed. Re-enable the project to fix this.)rBÚreposÚitemsr�r‰r)r]Z directoryrŒr�r�rŠr‹r r r rlis z(CoprCommand._list_installed_repositoriesc CsÖdj|ƒ}|j|}|jj|dd�}ytj|jƒƒ}Wn*tk r`tj j t dƒj|ƒƒ‚YnX|j |ƒt dƒj|ƒ}|j |ƒxL|dD]@}dj||dƒ}|d p°t d ƒ} |jjjt|ƒ| ƒ}t|ƒqŽWdS) Nz!/api_3/project/list?ownername={0}zw+)Úmodez+Can't parse repositories for username '{}'.zList of {} coprsr’z {0}/{1} : rÚ descriptionzNo description given)rfrWrBr ÚjsonÚloadsrJrrRrorprÚ_check_json_outputÚ_print_match_sectionÚoutputÚ fmtKeyValFillrr‰) r]Z user_nameÚapi_pathÚurlÚresÚ json_parseÚ section_textÚitemr‚Údescr r r rkss"    zCoprCommand._list_user_projectsc CsÔdj|ƒ}|j|}|jj|dd�}ytj|jƒƒ}Wn*tk r`tj j t dƒj|ƒƒ‚YnX|j |ƒt dƒj|ƒ}|j |ƒxJ|dD]>}dj|dƒ}|d p®t d ƒ} |jjjt|ƒ| ƒ}t|ƒqŽWdS) Nz/api_3/project/search?query={}zw+)r“zCan't parse search for '{}'.z Matched: {}r’z{0} : Z full_namer”zNo description given.)rfrWrBr r•r–rJrrRrorprr—r˜r™ršrr‰) r]Zqueryr›rœr�ržrŸr r‚r¡r r r rsˆs     zCoprCommand._searchcCs|jjj|ƒ}t|ƒdS)N)rBr™Z fmtSectionr‰)r]rgZ formattedr r r r˜œsz CoprCommand._print_match_sectioncCsj|jstjjdƒd|_tjjdj|jƒƒƒ|jjƒrf|jjj sb|jj j dj|ƒdj|ƒd� rfdSdS)NÚ Fz{0} z {} [y/N]: z {} [Y/n]: )r‚Zdefaultyes_msgT) Ú first_warningrcrdrerfrrBZ _promptWantedrCZassumenor™Z userconfirm)r]ryr‚r r r Ú_ask_user_no_raise s  zCoprCommand._ask_user_no_raisecCs |j||ƒstjjtdƒƒ‚dS)NzSafe and good answer. Exiting.)r¤rRrorpr)r]ryr‚r r r rw¬s zCoprCommand._ask_usercCs tjƒdkrtjjtdƒƒ‚dS)Nrz/This command has to be run under the root user.)rDÚgeteuidrRrorpr)Úclsr r r rv°s zCoprCommand._need_rootcs|j‰ˆdks&ˆddks&ˆddkr,tƒ‰|jjjd}t‡fdd„dDƒƒrŠd ˆkrbd |}n&d td ƒkrxd |}ndjˆd|ƒ}nˆdˆkrÂtj dƒ}dˆkr°dj|ƒ}ndjˆd|ƒ}nPdˆkrútj dƒ}dˆkrèdj|ƒ}ndjˆd|ƒ}ndˆdj ddƒd}|S)z2 Guess which chroot is equivalent to this machine NrFr%Zbasearchcsg|] }|ˆk‘qSr r )Ú.0r)Údistr r ú ¿sz-CoprCommand._guess_chroot..ÚFedoraú Fedora LinuxZRawhidezfedora-rawhide-ZrawhideZredhat_support_product_versionzfedora-{0}-{1}ZMageiaz%{distro_arch}ZCauldronzmageia-cauldron-{}zmageia-{0}-{1}ZopenSUSEz%{_target_cpu}Z Tumbleweedzopensuse-tumbleweed-{}zopensuse-leap-{0}-{1}zepel-%s-x86_64Ú.)rªr«) rLr rBrCÚ substitutionsÚanyr rfÚrpmZ expandMacror)r]Zdistarchr~r )r¨r rr·s,        zCoprCommand._guess_chrootcCs´dj|jdd…ƒ}|jd}dj|||ƒ}y*t|j|ƒ}tjj|ƒrRtj|ƒW�n^t k �rl}zø|j dkržt dƒj|j||j t |ƒƒ}t jj|ƒ‚t dƒ}|jjdƒ} | �r>tj| ƒjdƒ} tj| ƒ} |t d ƒjdj|jƒ|ƒ7}| jd ƒ�r0|t d ƒd jd d„| d Dƒƒ7}|t dƒj|ƒ7}t jj|ƒ‚n|t dƒj|ƒ7}t jj|ƒ‚WYdd}~XnJtk �r´}z,t dƒj|j||jjƒ}t jj|ƒ‚WYdd}~XnX|jƒ} | jdƒ} tjd| ƒ�rútjj|jjjd| dd…dƒ}|j|j k�rR|j!dddƒj!|j"dƒj!dddƒj!ddƒj!ddƒ} tjj| ƒ�rRtj| ƒt#|dƒ�.}|j$| ƒx|j%ƒD]} |j$| ƒ�qrWWdQRXtj&|t'j(t'j)Bt'j*Bt'j+BƒdS) Nrjr%z%/coprs/{0}/repo/{1}/dnf.repo?arch={2}i”z Request to {0} failed: {1} - {2}z+It wasn't possible to enable this project. zCopr-Error-Datazutf-8z1Repository '{0}' does not exist in project '{1}'.zavailable chrootsz Available repositories: z, css|]}dj|ƒVqdS)z'{}'N)rf)r§Úxr r r ú òsz-CoprCommand._download_repo..z¿ If you want to enable a non-default repository, use the following command: 'dnf copr enable {0} ' But note that the installed repo file will likely need a manual modification.zProject {0} does not exist.zFailed to connect to {0}: {1}z\[copr:rriz.repoz_copr:Ú_coprrr?Zgroup_ú@Úwbr„r„éþÿÿÿ),rFrqrfr rWrDrEÚexistsr)r!ÚcoderÚstrrRrorpZheadersrKÚbase64Z b64decodeÚdecoder•r–r"ÚreasonÚstrerrorÚreadliner†r‡rBrCrtrVÚreplacerUrreÚ readlinesÚchmodÚstatÚS_IRUSRÚS_IWUSRÚS_IRGRPÚS_IROTH)r]r}r�Z short_chrootZarchr›ZresponseÚeZ error_msgZ error_dataZerror_data_decodedZ first_linerZold_repo_filenameÚfr r r rxÜsX           $   zCoprCommand._download_repocsÔ|jjdd�|jjƒ|j|j|ƒ|ƒ‰g}x(ˆjjƒD]}|jdƒrJq:|j|ƒq:W|s`dSt dƒ}t j dƒ‰|j dj ‡‡fdd „|Dƒƒƒ}|j|t d ƒƒsÐx,|D]$}|jjjˆj||jjjd d iƒq¨WdS) a, In addition to the main copr repo (that has repo ID prefixed with `copr:`), the repofile might contain additional repositories that serve as runtime dependencies. This method informs the user about the additional repos and provides an option to disable them. T)r‘zcopr:NaºMaintainer of the enabled Copr repository decided to make it dependent on other repositories. Such repositories are usually necessary for successful installation of RPMs from the main Copr repository (they provide runtime dependencies). Be aware that the note about quality and bug-reporting above applies here too, Fedora Project doesn't control the content. Please review the list: {0} These repositories have been enabled automatically.r%z cs*g|]"}djtˆƒ|ˆjj|dƒd�‘qS)z){num:2}. [{repoid}] baseurl={baseurl}Úbaseurl)ZnumÚrepoidrÈ)rfÚnextÚcfgZgetValue)r§rÉ)Úcounterr‹r r r©9sz5CoprCommand._runtime_deps_warning..z!Do you want to keep them enabled?rmÚ0)rBÚresetZread_all_reposÚ_get_copr_reporurËÚsectionsÚ startswithrIrÚ itertoolsÚcountrfrFr¤rCÚwrite_raw_configfiler…r­)r]rr€Z runtime_depsrŠryZdepr )rÌr‹r rzs*      z!CoprCommand._runtime_deps_warningc CsÐdj|jjddƒd|j|ƒ|ƒ}||jjkrÄdj|j|ƒ|ƒ}}||jjkrÀd|jj|jkrÀ|jj|jjdƒd }y.|jddƒdjddƒd}||jkr¦dSWqÄtk r¼YqÄXndS|jj|S) Nzcopr:{0}:{1}:{2}r?r%rz{0}-{1}r²r9rir„) rfrUrˆrurBr‘r…rrn)r]rr€rŠrŽrUr r r rÏFs     zCoprCommand._get_copr_repocCst|j||ƒ}|s,tjjtdj|j||ƒƒƒ‚ytj|j ƒWn2t k rn}ztjjt |ƒƒ‚WYdd}~XnXdS)Nz&Failed to remove copr repo {0}/{1}/{2}) rÏrRrorprrfrUrDr)r…ÚOSErrorr¸)r]rr€r‹rÆr r r r|\s zCoprCommand._remove_repocCsd|j||ƒ}|dkr,tjjtdj||ƒƒƒ‚x2|jjƒD]$}|jj j |j ||jj j ddiƒq8WdS)Nz!Failed to disable copr repo {}/{}rmrÍ) rÏrRrorprrfrËrÐrBrCrÔr…r­)r]rr€r‹rŠr r r r{hs  zCoprCommand._disable_repoc Cs<ytj|jƒƒ}Wn$tk r6tjjtdƒƒdSX|S)z¤ Wrapper around response from server check data and print nice error in case of some error (and return None) otherwise return json object. zUnknown response from server.N)r•r–rJrrRr@rSr)r¦rÇr™r r r Ú _get_datats zCoprCommand._get_datacCs"d|krtjjdj|dƒƒ‚dS)NÚerrorz{})rRrorprf)r¦Zjson_objr r r r—‚szCoprCommand._check_json_outputcCs&|ddkrdj|dd…ƒS|SdS)Nrr³zgroup_{}r%)rf)r¦rr r r ru‡s zCoprCommand._sanitize_username)r)'Ú__name__Ú __module__Ú __qualname__Ú__doc__rLrTZ default_hubrZr[rVÚaliasesrÚsummaryr£ÚusageÚ staticmethodr5r`rYrhrƒr�rlrkrsr˜r¤rwÚ classmethodrvrrrxrzrÏr|r{rÖr—rur r r r r#PsD  L_1   %82   r#c@sDeZdZdZdZedƒZdZdd„Zdd„Z e d d „ƒZ d d „Z d S)ÚPlaygroundCommandz Playground plugin for DNF Ú playgroundz$Interact with Playground repository.z [enable|disable|upgrade]c Cs0|jƒ|jtdƒtdƒƒdj|jƒ}|jj|dd�}|j|ƒ}|jƒ|ddkrft j j tdƒƒ‚xÄ|d D]¸}d j|d |d ƒ}d j|jj j |jddƒƒ}yj||dkr²wpdj|j||ƒ}|jj|dd�}|j|ƒ}|jƒ|oúd|koú|ddk�r |j||ƒWqpt jjk �r&YqpXqpWdS)Nz!Enabling a Playground repository.zDo you want to continue?z{0}/api/playground/list/zw+)r“r™ÚokzUnknown response from server.r‘z{0}/{1}ZusernameZcoprnamez{}/_playground_{}.repor9rjZchrootsz{0}/api/coprs/{1}/detail/{2}/)rvrwrrfrWrBr rÖÚcloserRr@rSrCrtr¾rxrorp) r]r~Zapi_urlrÇr™r‹r}r�Zoutput2r r r Ú _cmd_enable—s8         zPlaygroundCommand._cmd_enablecCs6|jƒx(tjdj|jjjƒƒD]}|j|ƒq WdS)Nz{}/_playground_*.repo)rvÚglobrfrBrCrtr|)r]r�r r r Ú _cmd_disable·szPlaygroundCommand._cmd_disablecCs|jdddddgd�dS)Nr$r%r'r(Úupgrade)r,r-)r3)r4r r r r5¼szPlaygroundCommand.set_argparsercCs¦tjjdƒ‚|jjd}|jƒ}|dkrB|j|ƒtjt dƒƒn`|dkrb|j ƒtjt dƒƒn@|dkrŒ|j ƒ|j|ƒtjt dƒƒntjjt d ƒj |ƒƒ‚dS) Nz%Playground is temporarily unsupportedrr'z-Playground repositories successfully enabled.r(z.Playground repositories successfully disabled.rèz-Playground repositories successfully updated.zUnknown subcommand {}.) rRrorprAr$rrrårryrrçrf)r]r$r~r r r rƒÁs    zPlaygroundCommand.runN)râ) rØrÙrÚrÛrÜrrÝrÞrårçrßr5rƒr r r r rá�s  rá)/Z __future__rrærÒr•rDr†ZshutilrÁrcr¹ZdnfpluginscorerrrRZ dnf.pycomprZdnf.i18nrr¯Zdistrorrr r r Ú ImportErrorÚplatformrGÚsetZYESZNOZ configparserrrrZurllib.requestr r!r"Zurllib2ZpluginZregister_commandr@ZCommandr#rár r r r ÚsP      B