^c@s=dZddlZddlZddlZddlZddlZddlmZddlm Z m Z ddl m Z ddl mZddlm Z mZmZmZmZmZmZmZmZdad Zeed Zd Zd e fd YZdZde fdYZdZ dZ!dS(s\ This module provides classes and functions used to download and manage debuginfos. iN(tPopen(t_tYumBase(tDownloadBaseCallback(t YumBaseError( Rtlog1tlog2t RETURN_OKtRETURN_FAILUREtRETURN_CANCEL_BY_USERtverboset ask_yes_not error_msgtcsqddl}tjtj|jdjkrUjkrUSfd}|S(s Ensures that the function is called using abrt's uid and gid Returns: Either an unchanged function object or a wrapper function object for the function. iNtabrtcsMtjjtjj||}tjtj|S(s Wrapper function around the called function. Sets up uid and gid to match abrt's and after the function finishes rolls its uid and gid back. Returns: Return value of the wrapped function. (tostsetegidtpw_gidtseteuidtpw_uid(targstkwargstretval(Rt current_gidt current_uidtfn(s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pytwrapped)s   (tpwdRtgetuidtgetgidtgetpwnamRR(RRR((RRRRs</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pytensure_abrt_uids   cCs%|d|}td||td|tdj|GH|d}yt|d}Wn+tk r} tdj|| GHtSXtd|gd |d d } | j} | d krtd |std|t j |qn"|j tdj|GHtS|j t|d}tdjd|GHd} ddg} |rx |D]}| d|d7} qaWdd| j g} ntdd=}t| d|d d d|d |d|}|j} WdQX| d kr tdt j |ntdj|GHtSdS( s Unpacks a single rpm located in tmp_dir into destdir. Arguments: package_file_name - name of the rpm file files - files to extract from the rpm tmp_dir - temporary directory where the rpm file is located destdir - destination directory for the rpm package extraction keeprpm - check if the user wants to delete rpms from the tmp directory exact_files - extract only specified files Returns: RETURN_FAILURE in case of a serious problem t/sExtracting %s to %ss%ssExtracting cpio from {0}s/unpacked.cpiotwbsCan't write to '{0}': {1}trpm2cpiotstdouttbufsizeiiscpio written OKskeeprpms = False, removing %ssCan't extract package '{0}'trbs$Caching files from {0} made from {1}s unpacked.cpioR tcpios-idut.t s /dev/nulltwtcwdtstdintstderrNsfiles extracted OKsCan't extract files from '{0}'( RRRtformattopentIOErrorRRtwaitRtunlinktclosetstrip(tpackage_file_nametfilesttmp_dirtdestdirtkeeprpmt exact_filestpackage_full_pathtunpacked_cpio_patht unpacked_cpiotexR"tretcodet file_patternst cpio_argstfilenametnullR&((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pyt unpack_rpmCsN            cCsetraytjtWqatk r]}|jtjkr^ttdjt|q^qaXndS(s* Removes the temporary directory. sCan't remove '{0}': {1}N( tTMPDIRtshutiltrmtreetOSErrorterrnotENOENTR RR-(R=((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pytclean_ups tMyDownloadCallbackcBs eZdZdZdZRS(sR This class serves as a download progress handler for yum's progress bar. cCs5||_d|_d|_d|_tj|dS(sx Sets up instance variables Arguments: total_pkgs - number of packages to download iN(t total_pkgstdownloaded_pkgstlast_pctt last_timeRt__init__(tselfRL((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pyRPs     cCsYt|d}||jkr-tddS||_tjjrtjjd|jd|j||f|dkrHt dj |jd|j||GHqHnt j }|j dkr||_ n|dks|j |ks||j dkrHt dj |jd|j||GH||_ |dkrHd|_ qHntjj dS( s A method used to update the progress Arguments: name - filename frac - progress fracment (0 -> 1) fread - formated string containing BytesRead ftime - formated string containing remaining or elapsed time ids-percentage is the same, not updating progressNs&Downloading (%i of %i) %s: %3u%%is$Downloading ({0} of {1}) {2}: {3:3}%ii(tintRNRtsysR#tisattytwriteRMRLRR-ttimeROtflush(RQtnametfractfreadtftimetpcttt((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pytupdateProgresss*      !  .   (t__name__t __module__t__doc__RPR^(((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pyRKs cCs(tdj|j|jGHidd6S(s0 A callback function for mirror errors. sOProblem '{0!s}' occured while downloading from mirror: '{1!s}'. Trying next oneitfail(RR-t exceptiontmirror(t callBackObj((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pytdownloadErrorCallbacks tDebugInfoDownloadcBsMeZdZdeedZdZdZedZ edZ RS(s> This class is used to manage download of debuginfos. s*debug*cCsd|_||_||_|a||_||_||_tj||j t dGHy|j Wn;t k r}|j t dj|GHtdnX|j dS(NisInitializing yums7Error initializing yum (YumBase.doConfigSetup): '{0!s}'i(t old_stdouttcachedirttmpdirRDtkeeprpmstnoninteractivet repo_patternRRPt mute_stdoutRt doConfigSetupRt unmute_stdoutR-texit(RQtcachettmpRmt keep_rpmsRlR=((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pyRPs"          cCs1tdkr-tj|_tddt_ndS(sJ Links sys.stdout with /dev/null and saves the old stdout is /dev/nullR)N(R RSR#RhR.(RQ((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pyRns  cCs6tdkr2|jdkr*|jt_q2dGHndS(s@ Replaces sys.stdout by stdout saved using mute iis ERR: unmute called without mute?N(R RhRSR#(RQ((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pyRp s cCstjj|jsLytj|jWqLtk rH}d|GHtSXntjj|jsytj|jWqtk r}d|GHtSXntS(NsCan't create tmpdir: %ssCan't create cachedir: %s( RtpathtexistsRjtmakedirsRGRRiR(RQR=((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pytsetup_tmp_dirss  cCsd}d}d}d}|s"tS|js=tdGHtSxn|jjD]]}y!|j|jj|jWqMtk r}tdj |jt |GHqMXqMWtdGHx|jj d|j D]} y|jj | j} |jjdt | jtd| t| dtyt| d tWn)ttfk rh}|GHtd GHnXWqtk r}td j | j|GH|jj| jqXqWtd GHy|jjd dddWn'tk r}tdj |GHnXy|jjd dddWn'tk rI}tdj |GHnXg} i} x|D]} td| |jj| }|r|d| jkr| |dj| nI| g| |d<|t|dj7}|t|dj7}|d7}td| |dq]td| | j| q]Wt|}|jj||jj t!t"dks~t#| dkrtdj t#| GHnt"dks|dkr1tdj |GHtdj |d.|d/}|j$tkrt%| rtdGHt&S|j'}|t(kr.|St)j*|j+}t|j,|j-d0}|d1|krtdj |j+|}|j$ rt%| rtdGHt&Snt)j*|j.}t|j,|j-d2}|d3|kr1tdj |j.|}|j$ r.t%| r.tdGHt&Sq1nx| j/D]\}}||_0d|_1|j2d}t)j3j4|}|j'}|t(kr|S|j2d}d4}|j6d r|d!}td"|yt7j8||j+WqTt9k r}td#j ||GHq>qTXn6t)j3j:|j+|}||_;|j<d$|g}|j=d%|j>d%|j?d&|j@}|d'}|ryt)jA|j+d(|Wnt9k rnXtd)j |GHnItB|||j+|j.|jCd*|}|tkrtd+GHtDtS|d7}q>W|jC rt)j3jE|j+rtd,j |j+GHyt)jF|j+Wqt9k rtGtd-j |j+qXnt(S(5s Downloads rpms into a temporary directory Arguments: package_files_dict - a dict containing {pkg: file list} entries total_pkgs - total number of packages to download download_exact_files - extract only specified files Returns: RETURN_OK if all goes well. RETURN_FAILURE in case it cannot set up either of the directories. is#Error: can't make cachedir, exitings'Can't disable repository '{0!s}': {1!s}sSetting up yum repositoriestpatterntthisreposenabled repo %stskip_if_unavailablet_asyncsACan't disable async download, the output might contain artifacts!sCan't setup {0}: {1}, disablings+Looking for needed packages in repositoriestmdtypetmetadatat cacheonlyis"Error retrieving metadata: '{0!s}'t filelistss#Error retrieving filelists: '{0!s}'syum whatprovides %ssfound pkg for %s: %ssnot found pkg for %ss+Can't find packages for {0} debuginfo filessPackages to download: {0}s;Downloading {0:.2f}Mb, installed size: {1:.2f}Mb. Continue?isDownload cancelled by usersKWarning: Not enough free space in tmp dir '{0}' ({1:.2f}Mb left). Continue?sMWarning: Not enough free space in cache dir '{0}' ({1:.2f}Mb left). Continue?t relativepatht remote_urlsfile:///iscopying from local repo: %ssCannot copy file '{0}': {1}tpkglistt-R's.rpmR sDownloading package {0} failedR9s&Unpacking failed, aborting download...s Removing {0}s/Can't remove %s, probably contains an error logiiiiiiN(HRt setCacheDirRtrepost listEnabledR2t disableRepotidRR-tstrt findReposRmt enableRepotdoSetupRtsetattrtTruetFalset NameErrortAttributeErrort populateSackRtpkgSackt searchFilestkeystappendtfloattsizet installedsizeRKtsetProgressBartsetMirrorFailureCallbackRfR tlenRlR R RxRRtstatvfsRjtf_bsizetf_bavailRit iteritemsRMRrt returnSimpleRutbasenametNonet startswithREtcopyRGtjoint localpatht downloadPkgsRXtversiontreleasetarchR1RCRkRJRvtrmdirR (RQR5tdownload_exact_filestinstalled_sizeRLttodownload_sizeRMtrepoR=trtridt not_foundtpackage_files_dicttdebuginfo_pathtpkgtdnlcbtquestionRtrest tmp_spacet cache_spacetremotetlocalt remote_pathterrtpkg_pathtpkg_nvraR4t unpack_result((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pytdownload)s   (                           *      #( R_R`RaRRRPRnRpRRxR(((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pyRgs  cCs,g|D]!}d||d |df^qS(s Transforms build ids into a path. build_id1=${build_id:0:2} build_id2=${build_id:2} file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" s&%s/usr/lib/debug/.build-id/%s/%s.debugi((tpfxt build_idstb_id((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pytbuild_ids_to_paths cCs.td|}g}xZ|D]R}td|tjj|rTtd|qntd||j|qW|r|}g}n|Sx|D]}td|xd|D]\}||}td|tjj|rtd|qntd||j|qW|r"|}g}q|SqW|S(s Checks for installed debuginfos. Arguments: build_ids - string containing build ids cache_dirs - list of cache directories Returns: List of missing debuginfo files. R s looking: %ss found: %ss not found: %ss looking in %s(RRRRuRvR(Rt cache_dirsR5tmissingRt cache_dirtcache_debuginfo_path((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pytfilter_installed_debuginfos s8             ("RaRSRRVRHREt subprocessRtyumRRt yum.callbacksRt yum.ErrorsRt reportclientRRRRR R R R RDRRRCRJRKRfRgRR(((s</usr/lib64/python2.7/site-packages/reportclient/debuginfo.pyts*     @ ,E B