$.VfޑfddlZddlZddlZddlZddlZddlZddlZddlmZddl Z ddl Z ddl Z ddl m Z ddlmZddlmZddlmZddlmZdd lmZdd lmZdd lmZdd lmZdd lmZddlmZGddeZGddeZ GddeZ!GddeZ"Gdde Z#GddZ$y)N) attrgetter)InstallProgress)AcquireProgress) SourcesList) itervaluesbuild_skeleton_apt)StringIO)append_text_file)create_text_file)read_binary_file)read_text_file) touch_fileceZdZdZy)TransactionErrorz)Raised when the transaction fails to run.N__name__ __module__ __qualname____doc__B/usr/lib/python3/dist-packages/landscape/lib/apt/package/facade.pyrrs3rrceZdZdZdZdZy)DependencyErrorz9Raised when a needed dependency wasn't explicitly marked.c||_yN)packages)selfrs r__init__zDependencyError.__init__"s   rc djdj|jDcgc] }t|c}Scc}w)NzMissing dependencies: {}, )formatjoinrstrr packages r__str__zDependencyError.__str__%s:)00 II-1]];'W;   ;sA N)rrrrr!r)rrrrrsC! rrceZdZdZy) ChannelErrorz"Raised when channels fail to load.Nrrrrr+r+-s,rr+ceZdZdZdZy)LandscapeAcquireProgresscy)aDOverride trying to get the column count of the buffer. We always send the output to a file, not to a terminal, so the default width (80 columns) is fine for us. Overriding this method means that we don't have to care about fcntl.ioctl API differences for different Python versions. Nr)r dummys r_winchzLandscapeAcquireProgress._winch2srcy)zOverride updating the acquire progress, which needs a tty. Under Python3, StringIO.fileno() raises UnsupportedOperation instead of an AttributeError. This would be uncaught by apt, thus we force a NOOP here. Tr)r owners rpulsezLandscapeAcquireProgress.pulse<srN)rrrr0r3rrrr-r-1s  rr-c6eZdZdZdZfdZfdZdZxZS)LandscapeInstallProgressNcXt|}tj||_|S)aOverride to find out whether dpkg exited or not. The C{run()} method returns os.WEXITSTATUS(res) without checking os.WIFEXITED(res) first, so it can signal that everything is ok, even though something causes dpkg not to exit cleanly. Save whether dpkg exited cleanly into the C{dpkg_exited} attribute. If dpkg exited cleanly the exit code can be used to determine whether there were any errors. If dpkg didn't exit cleanly it should mean that something went wrong. )super wait_childos WIFEXITED dpkg_exited)r res __class__s rr8z#LandscapeInstallProgress.wait_childKs(g "<<, rct|}|dk(r*tj|_|j t_|S)z6Fork and override the excepthook in the child process.r)r7forksys excepthookold_excepthook_prevent_dpkg_apport_error)r pidr=s rr?zLandscapeInstallProgress.fork[s5gln !8#&..D !<d=Z?d>Z@y)C AptFacadeatWrapper for tasks using Apt. This object wraps Apt features, in a way that makes using and testing these features slightly more comfortable. @param root: The root dir of the Apt configuration files. @ivar refetch_package_index: Whether to refetch the package indexes when reloading the channels, or reuse the existing local database. z/var/lib/dpkg/statusNc||_g|_|j7|j|jjd|jgtj j ||_d|_i|_ i|_ g|_ t|_ d|_g|_g|_g|_d|_y)Nz--root)rootdirF)_root _dpkg_args_ensure_dir_structureextendaptcacheCache_cache_channels_loaded _pkg2hash _hash2pkg_version_installsset_package_installs_global_upgrade_version_removals_version_hold_creations_version_hold_removalsrefetch_package_index)r roots rr!zAptFacade.__init__s  :: !  & & ( OO " "Hdjj#9 :iioodo3 %!#!$$!#')$&(#%*"rc|jd}|jd|jd|jd|jd}|jd|jd|jdttjj |d d tjj |d |_tjj |j st|j d tjjtjj |d s*ttjj |d yy)Nzetc/aptzetc/apt/sources.list.dzvar/cache/apt/archives/partialzvar/lib/apt/lists/partialz var/lib/dpkgzvar/lib/dpkg/infozvar/lib/dpkg/updateszvar/lib/dpkg/triggers availablestatusz trusted.gpg.dz trusted.gpg) _ensure_sub_dirr r9pathr% _dpkg_statusexistsisdirr)r apt_dirdpkg_dirs rrTzAptFacade._ensure_dir_structures&&y1 56 => 89''7 01 34 45h ;F=E>>F;F<c>|jry|jy)z6Reload the channels if they haven't been reloaded yet.N)rZrrvs rensure_channels_reloadedz"AptFacade.ensure_channels_reloadeds   rc@tjjdS)NzDir::Etc::sourceparts)apt_pkgconfigfind_dirrvs r_sourceparts_directoryz AptFacade._sourceparts_directorys~~&&'>??rcVtjj|jdS)z@Return the path to the source.list file for the facade channels.z_landscape-internal-facade.list)r9rkr%rrvs rrz$AptFacade._get_internal_sources_list!s#ww||  ' ' -  rcb|j}d}||jdr |rdnd}d|d}d||d |}|r#|d jd j|z }tj j |rt|jd } || vry|d z }t||y) a!Add a deb URL which points to a repository. @param url: The base URL of the repository. @param codename: The dist in the repository. @param components: The components to be included. @param trusted: Whether validation should be skipped (if local). rhNzfile:yesnoz [ trusted=z ] zdeb  z {} ) r startswithr$r%r9rkrmrsplitr ) r urlcodename componentstrustedsources_file_pathsource_options trusted_val sources_linecurrent_contents radd_channel_apt_debzAptFacade.add_channel_apt_deb(s!;;=  3>>'#:#*%K)+c:Nn-cU!H:>  ELL*)=> >L 77>>+ ,,->?EEdKO. *L9rcV|j||jd|dddy)zAdd a directory with packages as a channel. @param path: The path to the directory containing the packages. A Packages file is created in the directory with information about the deb files. zfile://z./NT)r)_create_packages_filer)r rks radd_channel_deb_dirzAptFacade.add_channel_deb_dirEs2 ""4(   74&!14t Lrc|j}tjj|rtj|yy)zClear the channels that have been added through the facade. Channels that weren't added through the facade (i.e. /etc/apt/sources.list and /etc/apt/sources.list.d) won't be removed. N)rr9rkrmremove)r rs rclear_channelszAptFacade.clear_channelsRs6!;;= 77>>+ , II' ( -rcxttj|}ttjj |ddd5}t |D]M\}}|dkDr|jdtjj ||}|j||O dddy#1swYyxYw)z0Create a Packages file in a directory with debs.Packageswbr N) rr9listdirrrkr% enumeratewritewrite_package_stanza)r deb_dirrdestifilenamedeb_files rrzAptFacade._create_packages_file]s"**W-. "'',,w 3T1 = :(2 : 8q5JJu%77<<:))(D9  : : : :s AB00B9ct}t|drd|_|j|Dcgc]L}|js>|j |j dj|j|jdNc}Scc}w)zReturn a list of channels configured. A channel is a deb line in sources.list or sources.list.d. It's represented by a dict with baseurl, distribution, components, and type keys. deb822Tr)baseurl distributionrtype) rhasattrrrefreshdisableduridistr%compsrr rentrys rrzAptFacade.get_channelsgs{#} < *"&L   "&  >> !99 % !hhu{{3     sABct}t|drd|_|j|D]}|j d|j y)z#Remove all the configured channels.rTFN)rrrr set_enabledsavers rreset_channelszAptFacade.reset_channels~sP"} < *"&L   "! %E   e $ %rc t|}tj|}|jj d}|j t jj|}t jj|}t|}tj|j} tj|j} tj|j} t!j"|} d|fdt%|fd| fd| fd| fg} | j'|t j(| Dcgc]\}}t!j*||c}}ycc}}w#t,$rHt!j.| t j(| }|j'|j1dYywxYw) zWrite a stanza for the package to a Packages file. @param deb_path: The path to the deb package. @param dest: A writable package file. controlFilenameSizeMD5sumSHA1SHA256rN)rapt_instDebFiler extractdatacloser9rkbasenamegetsizerhashlibmd5 hexdigestsha1sha256r TagSectionr&rREWRITE_PACKAGE_ORDER TagRewriteAttributeErrorrewrite_sectionr)r deb_pathrrdebrrsizecontentsrrr tag_sectionnew_tagskvsections rrzAptFacade.write_package_stanzasz >x(++)))477##H-wwx(#H-kk(#--/||H%//1)335((1  " SY  sO TN v    0   --6>?da##Aq)? @ 0----G JJw~~g. / 0s%. E= E7.E=7E==AG Gc@tjjdS)z1Return the architecture APT is configured to use.APT::Architecture)rrgetrvs rget_archzAptFacade.get_archs~~!!"566rc|d}tjjdtjjd|tjjd|}|jj d|S)zkSet the architecture that APT should use. Setting multiple architectures isn't supported. NrhzAPT::ArchitectureszAPT::Architectures::r)rrrr^rYr)r architectureresults rset_archzAptFacade.set_archsi  L 121<@##$7F  rct||dS)aReturn a skeleton for the provided package. The skeleton represents the basic structure of the package. @param pkg: Package to build skeleton from. @param with_info: If True, the skeleton will include information useful for sending data to the server. Such information isn't necessary if the skeleton will be used to build a hash. @return: a L{PackageSkeleton} object. T)r with_unicoder )r pkgrs rrzAptFacade.get_package_skeletons"#NNrcP|jj|j|fS)ziReturn a hash from the given package. @param version: an L{apt.package.Version} object. )r[rr(r{s rget_package_hashzAptFacade.get_package_hashs" ~~!!7??G"<==rc6|jjS)z=Get the hashes of all the packages available in the channels.)r[valuesrvs rget_package_hasheszAptFacade.get_package_hashess~~$$&&rc8|jj|S)zGet the package having the provided hash. @param hash: The hash the package should have. @return: The L{apt.package.Package} that has the given hash. )r\r)r hashs rget_package_by_hashzAptFacade.get_package_by_hashs~~!!$''rc4||jjk(S)z!Is the package version installed?)r( installedr{s rryzAptFacade.is_package_installeds'//3333rc|jS)z*Is the package available for installation?) downloadabler{s ris_package_availablezAptFacade.is_package_availables###rc|jjr|jjsy||jjkDS)z8Is the package an upgrade for another installed package?F)r( is_upgradablerr{s ris_package_upgradezAptFacade.is_package_upgrades3,,GOO4M4M2222rc.|jjS)z;Was the package auto-installed, but isn't required anymore?)r(is_auto_removabler{s ris_package_autoremovablez"AptFacade.is_package_autoremovables000rcNt|dsy|j|jk(S)z2Is the package for the facade's main architecture? shortnameT)rrr"r's rrzAptFacade._is_main_architectures& w ,||w0000rcP|jjtjk(S)zIs the package marked as held?)_pkgselected_stater SELSTATE_HOLDr's rrzzAptFacade._is_package_helds||**g.C.CCCrcz|jDcgc]}|jj|k(r|c}Scc}w)zGet all available packages matching the provided name. @param name: The name the returned packages should have. )rwr(r)r rr|s rget_packages_by_namezAptFacade.get_packages_by_name s? ,,. ##t+    s"8c|jry|js&|js|js||jvSy)a]Is the package broken? It's considered broken if it's one that we marked for install, but it's not marked for install, upgrade or downgrade anymore. Before Trusty, checking is_inst_broken was enough, but in Trusty the behaviour changed, so the package simply gets unmarked for installation. TF)is_inst_brokenmarked_installmarked_upgrademarked_downgrader_r's r_is_package_brokenzAptFacade._is_package_brokens?  ! !&&**,,d444 4rc|jDchc])}|j|jr |j+c}Scc}w)z/Return the packages that are in a broken state.)rwr.r(r{s r_get_broken_packageszAptFacade._get_broken_packages)sC ,,. &&w7 OO   s.Ac|jr |jgS|js |jr|j|jgS|j r |jgSy)a]Return the versions that will be changed for the package. Apt gives us that a package is going to be changed and have variables set on the package to indicate what will change. We need to convert that into a list of versions that will be either installed or removed, which is what the server expects to get. N)r+ candidater,r-r marked_deleter's r_get_changed_versionszAptFacade._get_changed_versions1s_  ! !%%& &  ! !W%=%=%%w'8'89 9  %%& &rc|Dcgc]}|j|f}}t}|jjD]?|j s|j }|j fd|DA|j|}|rt|Dcgc]\}}| c}}t|dkDScc}wcc}}w)aCheck that the changes Apt will do have all been requested. @raises DependencyError: If some change hasn't been explicitly requested. @return: C{True} if all the changes that Apt will perform have been requested. c3&K|]}|f ywrr).0r|r(s r z+AptFacade._check_changes..Ts*'.'"*sr) r(r^rY get_changesrr4r differencerlen)r requested_changesr| all_changesversions_to_be_changedr dependenciesr(s `r_check_changeszAptFacade._check_changesAs7H +2W__g &  "%{{..0 G--g611':H " ) )*2:*   .88E !1=>-Wg> )*Q..! ?s C C c|jj}|jr)|dj|j|jz }d}|jj|j vr|j |jj}|j s |jrN|jj}||j jvr|j j}d|d}||z }|S)zAReturn a string representation of a specific dependency relation.z ({} {})z but is not installablez but z is to be installed) target_pkgr target_verr$ comp_typerYrr+r2r|r9)r dep_relationinforeason dep_packager|s r_get_unmet_relation_infoz"AptFacade._get_unmet_relation_info^s&&++  " " J%%&&'' D+  " " ' '4;; 6++l&=&=&B&BCK$$ (B(B%//77dkk&=&=&??)33;;G  )<=  rc|dv}|jj}|D]i}|jD]T}|j}|jt j k(s|j|s>|j|rP|ccSk| S)a+Return whether a dependency is satisfied. For positive dependencies (Pre-Depends, Depends) it means that one of its targets is going to be installed. For negative dependencies (Conflicts, Breaks), it means that none of its targets are going to be installed. )Breaks Conflicts) rY _depcache all_targets parent_pkg current_staterCURSTATE_INSTALLEDr+r3)r dependencydep_type is_positivedepcacheor_deptargetr(s r_is_dependency_satisfiedz"AptFacade._is_dependency_satisfiedqs&== ;;((  'F ,,. ' ++))W-G-GG..w7"009&& ' 'rc  |j}|sydg}t|tdD] d}t fd|jD}dD]}|j j |g}|D]}|j||rg}|D]"} |j|j| $d jd |d } d d t| zz} |j| | j|zd }|r|jd j jddj|S)aGet information about unmet dependencies in the cache state. Go through all the broken packages and say which dependencies haven't been satisfied. @return: A string with dependency information like what you get from apt-get. rhz/The following packages have unmet dependencies:r)keyFc3VK|] }|jk(s|j"ywr)r(_cand)r7rr(s rr8z7AptFacade._get_unmet_dependency_info..s%199;Os))) PreDependsDependsrLrKz z: z or rTz {}: {}zUnknown dependency errorr)r0rrnextr] depends_listrrXappendrIrr;r%r$) r broken_packagesall_infofound_dependency_errorr2rSr?rRrelation_infosrErF or_dividerr(s @r_get_unmet_dependency_infoz$AptFacade._get_unmet_dependency_infosc335EFo:f3EF G%* "!%!7!7IM 2(5599(BG ". 2J44ZJ %'N(2 &-- 99,G  ~Rz+J$JK-1* 2 2*%% 2- 8yy""rcvdtjd<dtjd<dtjd<y)zW Set the environment to avoid attempts by apt to interact with a user. noninteractiveDEBIAN_FRONTENDnoneAPT_LISTCHANGES_FRONTENDAPT_LISTBUGS_FRONTENDN)r9environrvs r_set_frontend_noninteractivez&AptFacade._set_frontend_noninteractives1)9 $%17 -..4 *+rc|jtjjdtjj ddy)zV Setup environment and apt options for successful package operations. z DPkg::optionszDPkg::options::z--force-confoldN)rorrrr^rvs r_setup_dpkg_for_changesz!AptFacade._setup_dpkg_for_changess8 ))+_-,.?@rc t|jdkDxst|jdkD}|sy|jDcgc]}|j|s|}}|rWt ddj dj t|Dcgc]}|jjc}z|jD]}|j||jD]}|j|ycc}wcc}w)z> Perform pending hold operations on packages. rNz0Cannot perform the changes, since the following zpackages are not installed: {}r#z#Package holds successfully changed.) r;rbrcryrr$r%rr(rrr)r hold_changesr| not_installeds r_perform_hold_changeszAptFacade._perform_hold_changess# ,, - 1 44../!3  77 ,,W5   "B299II,2-+@ '$OO00  33 +G  ! !' * +22 .G  $ $W - .51 s C> Dc$t}tj\}}tjd}tjd}tj |dtj |dt } d}||jkrd}|dkDrFtj|jtjd|j|z dd|dz } |jjt|||j s t#d  |j%t'|z} | tj |dtj |dtj2| S#t"$rD} |j%t'|z} t)| j*dd z| z}Yd} ~ d} ~ wt,j.j0$rD} |j%t'|z} t)| j*dd z| z}Yd} ~ nd} ~ wwxYw||jkr #tj |dtj |dtj2|wxYw) zd Commit cached APT operations and give feedback on the results as a string. rrNz8dpkg process might be in use. Retrying package changes. dz retries remaining.)fetch_progressinstall_progresszdpkg didn't exit cleanly.z Package operation log: )r tempfilemkstempr9dupdup2r5max_dpkg_retriestimesleepdpkg_retry_sleeploggingwarningrYcommitr-r;rFgetvaluerrargsrVrWLockFailedExceptionr) r fetch_outputfdinstall_output_path old_stdout old_stderrrz dpkg_trieserror result_textexc exceptions r_commit_package_changesz!AptFacade._commit_package_changessm z #+"2"2"4 VVAY VVAY  A A359 +J 5 55>JJt445OO500:=a@A-- a  KK&&'? 'M)9',77)*EFF80#/"7"7"9N+=#K  ! GGJ " GGJ " II) *E# "."7"7"9N+=#K- 89%&Eyy44"."7"7"9N+=#K-!q)89%&E C 5 55f GGJ " GGJ " II) *sJA#I '=F %!I H6:G I  H62:H1,I 1H66I AJc|jD]}||jjk(r||j_|jj xs|jj }|jj d||j j|j|j|jj|j|jjy)NF)auto_fix from_user) r]r(rr2is_auto_installed mark_installr_addrr$protect)r fixerr| is_manuals r_preprocess_installszAptFacade._preprocess_installs5s-- 0G'//333)0GOO %OO---9888  OO ( (%9 ( M  " " & &w 7 KK,, - MM'//.. // 0rc Tt}|jDchc]}|j}}|jDchc]}|j|vr |j}}|jD]}|j |jr%|j |jj |j|vrR|jjd|j|jj|j|jj|j|jj |j|r2tdjdj!t#|ycc}wcc}w#t$rY;wxYw)NF)rzDCan't perform the changes, since the following packages are held: {}r#)r^r]r(rarzrr mark_deleterr$rrinstall_protectrrr$r%r)r rheld_package_namesr|package_installspackage_upgradess r_preprocess_removeszAptFacade._preprocess_removesOsx U,0+A+A 'GOO   11 "22 OO  -- G$$W__5"&&w';';<"22 OO ' ' ' 7 KK,, - MM'//.. / LL-- . %%'! ( "%vdii7I0J&KL  =  ."  sF!F F F'&F'cV|jr|jjdyy)NT) dist_upgrade)r`rYupgradervs r_preprocess_global_upgradez$AptFacade._preprocess_global_upgradevs%    KK  T  2 rc*|j}||k7rA |jd|j}||k7rt|jyy#t$r1}t|j ddz|jzd}~wwxYw)zQ Attempt to automatically resolve problems with broken packages. TrrN)r0resolverrgrFr)r ralready_broken_packagesnow_broken_packagesrs r_resolve_broken_packagesz"AptFacade._resolve_broken_packageszs#779 "9 9 N d# '+&?&?&A#&*AA*4+J+J+LMMB : &JJqMD(4+J+J+LL sA B!,B  Bct|jdd}|j|j|s|jsgS|j }t j |jj}|j||j|j||j|||Sr) r]rUrar`r0rProblemResolverrYrMrrrr)r version_changesrrs r_preprocess_package_changesz%AptFacade._preprocess_package_changess003t556t';';I"&";";"='' (=(=> !!%( '')   ' %%e-DErcf|j}|j|sy|jS)zD Perform pending install/remove/upgrade operations. N)rr@r)r rs r_perform_package_changesz"AptFacade._perform_package_changess2::<""?3++--rc|j|j}|j}g}||j|||j|t |dkDrdj |Sy)z9 Perform the pending package operations. Nrr)rqrurrar;r%)r hold_result_textpackage_result_textresultss rperform_changeszAptFacade.perform_changessy $$&557";;=  * NN. /  ' NN+ , w'(4$3 11D  *  /:&**#X5A"5HM^04%N3N" . %/$/54rrM)%rrr9rr@r{roperatorrrVrrapt.progress.baserapt.progress.textraptsources.sourceslistrtwisted.python.compatrskeletonr landscape.lib.compatr landscape.lib.fsr r rrr Exceptionrrr+r-r5rMrrrrs    --.,()---+'4y4  i  -9-*-7-7`V 4V 4r