PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /usr/lib/python2.7/site-packages/yum
Viewing File: /usr/lib/python2.7/site-packages/yum/packageSack.py
#!/usr/bin/python -tt # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Copyright 2006 Duke University """ Classes for manipulating and querying groups of packages. """ from Errors import PackageSackError import warnings import re import fnmatch import misc from packages import parsePackages import rpmUtils.miscutils from rpmUtils.miscutils import compareEVR class PackageSackVersion: def __init__(self): self._num = 0 self._chksum = misc.Checksums(['sha1']) def __str__(self): return "%u:%s" % (self._num, self._chksum.hexdigest()) def __eq__(self, other): if other is None: return False if type(other) in (type(''), type(u'')): return str(self) == other if self._num != other._num: return False if self._chksum.digest() != other._chksum.digest(): return False return True def __ne__(self, other): return not (self == other) def update(self, pkg, csum): self._num += 1 self._chksum.update(str(pkg)) if csum is not None: self._chksum.update(csum[0]) self._chksum.update(csum[1]) class PackageSackBase(object): """Base class that provides the interface for PackageSacks.""" def __init__(self): self.added = {} def __len__(self): return len(self.returnPackages()) def __iter__(self): ret = self.returnPackages() if hasattr(ret, '__iter__'): return ret.__iter__() else: return iter(ret) def __cmp__(self, other): if other is None: return 1 s_repos = list(self.added) o_repos = list(other.added) if len(s_repos) != len(o_repos): return len(s_repos) - len(o_repos) for (s_repo, o_repo) in zip(sorted(s_repos), sorted(o_repos)): ret = cmp(s_repo, o_repo) if ret: return ret return 0 def setCompatArchs(self, compatArchs): raise NotImplementedError() def populate(self, repo, mdtype, callback, cacheOnly): raise NotImplementedError() def packagesByTuple(self, pkgtup): """return a list of package objects by (n,a,e,v,r) tuple""" warnings.warn('packagesByTuple() will go away in a future version of Yum.\n', DeprecationWarning, stacklevel=2) return self.searchPkgTuple(pkgtup) def searchNevra(self, name=None, epoch=None, ver=None, rel=None, arch=None): """return list of pkgobjects matching the nevra requested""" raise NotImplementedError() def searchNames(self, names=[], return_pkgtups=False): raise NotImplementedError() def searchPO(self, po): """return list of package objects matching the name, epoch, ver, rel, arch of the package object passed in""" return self.searchNevra(name=po.name, epoch=po.epoch, ver=po.ver, rel=po.rel, arch=po.arch) def searchPkgTuple(self, pkgtup): """return list of pkgobject matching the (n,a,e,v,r) tuple""" (n,a,e,v,r) = pkgtup return self.searchNevra(name=n, arch=a, epoch=e, ver=v, rel=r) def contains(self, name=None, arch=None, epoch=None, ver=None, rel=None, po=None): """return if there are any packages in the sack that match the given NAEVR or the NAEVR of the given po""" if po: name = po.name arch = po.arch epoch = po.epoch ver = po.version rel = po.release return bool(self.searchNevra(name=name, arch=arch, epoch=epoch, ver=ver, rel=rel)) def getProvides(self, name, flags=None, version=(None, None, None)): """return dict { packages -> list of matching provides }""" raise NotImplementedError() def getRequires(self, name, flags=None, version=(None, None, None)): """return dict { packages -> list of matching requires }""" raise NotImplementedError() def searchRequires(self, name): """return list of package requiring the name (any evr and flag)""" raise NotImplementedError() def searchProvides(self, name): """return list of package providing the name (any evr and flag)""" raise NotImplementedError() def searchConflicts(self, name): """return list of package conflicting with the name (any evr and flag)""" raise NotImplementedError() def searchObsoletes(self, name): """return list of package obsoleting the name (any evr and flag)""" raise NotImplementedError() def returnObsoletes(self, newest=False): """returns a dict of obsoletes dict[obsoleting pkgtuple] = [list of obs]""" raise NotImplementedError() def have_fastReturnFileEntries(self): """ Is calling pkg.returnFileEntries(primary_only=True) faster than using searchFiles(). """ raise NotImplementedError() def searchFiles(self, name): """return list of packages by filename""" raise NotImplementedError() def addPackage(self, obj): """add a pkgobject to the packageSack""" raise NotImplementedError() def buildIndexes(self): """builds the useful indexes for searching/querying the packageSack This should be called after all the necessary packages have been added/deleted""" raise NotImplementedError() def delPackage(self, obj): """delete a pkgobject""" raise NotImplementedError() def returnPackages(self, repoid=None, patterns=None, ignore_case=False): """return list of all packages""" raise NotImplementedError() def addPackageExcluder(self, repoid, excluderid, excluder, *args): """ Add an "excluder" for all packages in the repo/sack. Can basically do anything based on nevra, changes lots of exclude decisions from "preload package; test; delPackage" into "load excluder". Excluderid is used so the caller doesn't have to track "have I loaded the excluder for this repo.", it's probably only useful when repoid is None ... if it turns out utterly worthless then it's still not a huge wart. """ raise NotImplementedError() def simpleVersion(self, main_only=False, groups={}): """ Return a simple version for all available packages. """ def _up_revs(arepos, repoid, rev, pkg, csum): arevs = arepos.setdefault(repoid, {}) rpsv = arevs.setdefault(None, PackageSackVersion()) rpsv.update(pkg, csum) if rev is not None: rpsv = arevs.setdefault(rev, PackageSackVersion()) rpsv.update(pkg, csum) main = PackageSackVersion() arepos = {} main_grps = {} arepos_grps = {} for pkg in sorted(self.returnPackages()): csum = pkg.returnIdSum() main.update(pkg, csum) for group in groups: if pkg.name in groups[group]: if group not in main_grps: main_grps[group] = PackageSackVersion() arepos_grps[group] = {} main_grps[group].update(pkg, csum) if main_only: continue rev = pkg.repo.repoXML.revision _up_revs(arepos, pkg.repoid, rev, pkg, csum) for group in groups: if pkg.name in groups[group]: _up_revs(arepos_grps[group], pkg.repoid, rev, pkg, csum) if groups: return [main, arepos, main_grps, arepos_grps] return [main, arepos] def returnNewestByNameArch(self, naTup=None, patterns=None, ignore_case=False): """return list of newest packages based on name, arch matching this means(in name.arch form): foo.i386 and foo.noarch are not compared to each other for highest version only foo.i386 and foo.i386 will be compared Note that given: foo-1.i386; foo-2.i386 and foo-3.x86_64 The last _two_ pkgs will be returned, not just one of them. """ raise NotImplementedError() def returnNewestByName(self, name=None, patterns=None, ignore_case=False): """return list of newest packages based on name matching this means(in name.arch form): foo.i386 and foo.noarch will be compared to each other for highest version.""" raise NotImplementedError() def simplePkgList(self, patterns=None, ignore_case=False): """returns a list of pkg tuples (n, a, e, v, r)""" raise NotImplementedError() def printPackages(self): raise NotImplementedError() def excludeArchs(self, archlist): """exclude incompatible arches. archlist is a list of compatible arches""" raise NotImplementedError() def searchPackages(self, fields, criteria_re, callback): raise NotImplementedError() def searchAll(self, arg, query_type): raise NotImplementedError() def matchPackageNames(self, pkgspecs): """take a list strings and match the packages in the sack against it this will match against: name name.arch name-ver-rel.arch name-ver name-ver-rel epoch:name-ver-rel.arch name-epoch:ver-rel.arch return [exact matches], [glob matches], [unmatch search terms] """ # Setup match() for the search we're doing matched = [] exactmatch = [] unmatched = set(pkgspecs) specs = {} for p in pkgspecs: specs[p] = misc.compile_pattern(p) # We don't use simplePkgList() here because that loads all of the # rpmdb, if we are Eg. doing a "remove PackageKit". pkgs = self.returnPackages(patterns=unmatched) for pkgtup in [pkg.pkgtup for pkg in pkgs]: (n,a,e,v,r) = pkgtup names = set(( n, '%s.%s' % (n, a), '%s-%s-%s.%s' % (n, v, r, a), '%s-%s' % (n, v), '%s-%s-%s' % (n, v, r), '%s:%s-%s-%s.%s' % (e, n, v, r, a), '%s-%s:%s-%s.%s' % (n, e, v, r, a), )) for (term,query) in specs.items(): if term in names: exactmatch.append(self.searchPkgTuple(pkgtup)[0]) unmatched.discard(term) else: for n in names: if query(n): matched.append(self.searchPkgTuple(pkgtup)[0]) unmatched.discard(term) return misc.unique(exactmatch), misc.unique(matched), list(unmatched) def returnLeafNodes(self, repoid=None): """returns a list of package objects that are not required by any other package in this repository""" def _return_all_provides(po): """ Return all the provides, via. yield. """ # These are done one by one, so that we get lazy loading for prov in po.provides_names: yield prov for prov in po.filelist: yield prov for prov in po.dirlist: yield prov for prov in po.ghostlist: yield prov # fixme - maybe cache this list? req = {} orphans = [] # prebuild the req dict for po in self.returnPackages(repoid=repoid): if not po.requires_names: continue for r in po.requires_names: if r not in req: req[r] = set() if len(req[r]) > 1: # We only need to know if another pkg. continue # reqs. the provide. So 2 pkgs. is enough. req[r].add(po.name) for po in self.returnPackages(repoid=repoid): preq = 0 for p in _return_all_provides(po): if p in req: # If this pkg provides something that is required by # anything but itself (or another version of itself) it # isn't an orphan. if len(req[p]) > 1 or po.name not in req[p]: preq += 1 break if preq == 0: orphans.append(po) return orphans class MetaSack(PackageSackBase): """Represents the aggregate of multiple package sacks, such that they can all be treated as one unified sack.""" def __init__(self): PackageSackBase.__init__(self) self.sacks = {} self.compatarchs = None def __len__(self): ret = 0 for sack in sorted(self.sacks.values()): ret += len(sack) return ret def dropCachedData(self): for sack in self.sacks.values(): if hasattr(sack, 'dropCachedData'): sack.dropCachedData() def addSack(self, repoid, sack): """Adds a repository's packageSack to this MetaSack.""" self.sacks[repoid] = sack # Make sure the new sack follows the same rules we have been given. sack.setCompatArchs(self.compatarchs) def populate(self, repo, mdtype, callback, cacheOnly): self.sacks[repo.id].populate(repo, mdtype, callback, cacheOnly) def setCompatArchs(self, compatArchs): for sack in self.sacks.values(): sack.setCompatArchs(compatArchs) def packagesByTuple(self, pkgtup): """return a list of package objects by (n,a,e,v,r) tuple""" warnings.warn('packagesByTuple() will go away in a future version of Yum.\n', DeprecationWarning, stacklevel=2) return self._computeAggregateListResult("packagesByTuple", pkgtup) def searchNevra(self, name=None, epoch=None, ver=None, rel=None, arch=None): """return list of pkgobjects matching the nevra requested""" return self._computeAggregateListResult("searchNevra", name, epoch, ver, rel, arch) def searchNames(self, names=[], return_pkgtups=False): return self._computeAggregateListResult("searchNames", names, return_pkgtups) def getProvides(self, name, flags=None, version=(None, None, None)): """return dict { packages -> list of matching provides }""" return self._computeAggregateDictResult("getProvides", name, flags, version) def getRequires(self, name, flags=None, version=(None, None, None)): """return dict { packages -> list of matching requires }""" return self._computeAggregateDictResult("getRequires", name, flags, version) def searchRequires(self, name): """return list of package requiring the name (any evr and flag)""" return self._computeAggregateListResult("searchRequires", name) def searchProvides(self, name): """return list of package providing the name (any evr and flag)""" return self._computeAggregateListResult("searchProvides", name) def searchConflicts(self, name): """return list of package conflicting with the name (any evr and flag)""" return self._computeAggregateListResult("searchConflicts", name) def searchObsoletes(self, name): """return list of package obsoleting the name (any evr and flag)""" return self._computeAggregateListResult("searchObsoletes", name) def returnObsoletes(self, newest=False): """returns a dict of obsoletes dict[obsoleting pkgtuple] = [list of obs]""" if not newest: return self._computeAggregateDictResult("returnObsoletes") obsdict = self._computeAggregateDictResult("returnObsoletes") names = set((obstup[0] for obstup in obsdict)) nobsdict = {} last_name = '' last_pkg = None last_pkgtup = None # It takes about 0.2 of a second to convert these into packages, just # so we can sort them, which is ~40% of this functions time. So we sort # the pkgtups "by hand". def _pkgtup_nevr_cmp(x, y): """ Compare two pkgtup's (ignore arch): n, a, e, v, r. """ ret = cmp(x[0], y[0]) if ret: return ret # This is negated so we get higher versions first, in the list. return -compareEVR((x[2], x[3], x[4]), (y[2], y[3], y[4])) def _pkgtup_nevr_eq(x, y): return _pkgtup_nevr_cmp(x, y) == 0 for pkgtup in sorted(self.searchNames(names, return_pkgtups=True), cmp=_pkgtup_nevr_cmp): name = pkgtup[0] if last_name == name and not _pkgtup_nevr_eq(last_pkgtup, pkgtup): continue last_name = name last_pkgtup = pkgtup if pkgtup in obsdict: nobsdict[pkgtup] = obsdict[pkgtup] return nobsdict def searchFiles(self, name): """return list of packages by filename""" return self._computeAggregateListResult("searchFiles", name) def addPackage(self, obj): """Add a pkgobject to the packageSack. This is a meaningless operation for the MetaSack.""" pass def buildIndexes(self): """builds the useful indexes for searching/querying the packageSack This should be called after all the necessary packages have been added/deleted""" for sack in self.sacks.values(): sack.buildIndexes() def delPackage(self, obj): """Delete a pkgobject if it exists in every sub-sack.""" obj.repo.sack.delPackage(obj) def returnPackages(self, repoid=None, patterns=None, ignore_case=False): """Returns a list of packages. Note that the packages are always filtered to those matching the patterns/case. An optional repoid allows you to easily get data for a specific repo. """ if not repoid: return self._computeAggregateListResult("returnPackages", None, patterns, ignore_case) return self.sacks[repoid].returnPackages(patterns=patterns, ignore_case=ignore_case) def addPackageExcluder(self, repoid, excluderid, excluder, *args): """ Add an "excluder" for all packages in the repo/sack. Can basically do anything based on nevra, changes lots of exclude decisions from "preload package; test; delPackage" into "load excluder". Excluderid is used so the caller doesn't have to track "have I loaded the excluder for this repo.", it's probably only useful when repoid is None ... if it turns out utterly worthless then it's still not a huge wart. """ if not repoid: calr = self._computeAggregateListResult return calr("addPackageExcluder", None, excluderid, excluder, *args) return self.sacks[repoid].addPackageExcluder(None, excluderid,excluder, *args) def returnNewestByNameArch(self, naTup=None, patterns=None, ignore_case=False): """return list of newest packages based on name, arch matching this means(in name.arch form): foo.i386 and foo.noarch are not compared to each other for highest version only foo.i386 and foo.i386 will be compared. Note that given: foo-1.i386; foo-2.i386 and foo-3.x86_64 The last _two_ pkgs will be returned, not just one of them. """ calr = self._computeAggregateListResult pkgs = calr("returnNewestByNameArch", naTup, patterns, ignore_case) pkgs = packagesNewestByNameArch(pkgs) if not pkgs and (naTup or patterns): ui_pats = ", ".join(patterns or []) raise PackageSackError, 'No Package Matching %s' % ui_pats return pkgs def returnNewestByName(self, name=None, patterns=None, ignore_case=False): """return list of newest packages based on name matching this means(in name.arch form): foo.i386 and foo.noarch will be compared to each other for highest version.""" pkgs = self._computeAggregateListResult("returnNewestByName", name, patterns, ignore_case) pkgs = packagesNewestByName(pkgs) if not pkgs and (name or patterns): if name: ui_pats = name else: ui_pats = ", ".join(patterns or []) raise PackageSackError, 'No Package Matching %s' % ui_pats return pkgs def simplePkgList(self, patterns=None, ignore_case=False): """returns a list of pkg tuples (n, a, e, v, r)""" return self._computeAggregateListResult("simplePkgList", patterns, ignore_case) def printPackages(self): for sack in self.sacks.values(): sack.printPackages() def excludeArchs(self, archlist): """exclude incompatible arches. archlist is a list of compatible arches""" for sack in self.sacks.values(): sack.excludeArchs(archlist) def searchPackages(self, fields, criteria_re, callback): return self._computeAggregateDictResult("searchPackages", fields, criteria_re, callback) def searchAll(self, arg, query_type): return self._computeAggregateListResult("searchAll", arg, query_type) def matchPackageNames(self, pkgspecs): matched = [] exactmatch = [] unmatched = None for sack in self.sacks.values(): if hasattr(sack, "matchPackageNames"): e, m, u = [], [], [] try: e, m, u = sack.matchPackageNames(pkgspecs) except PackageSackError: continue exactmatch.extend(e) matched.extend(m) if unmatched is None: unmatched = set(u) else: unmatched = unmatched.intersection(set(u)) matched = misc.unique(matched) exactmatch = misc.unique(exactmatch) if unmatched is None: unmatched = [] else: unmatched = list(unmatched) return exactmatch, matched, unmatched def _computeAggregateListResult(self, methodName, *args): result = [] for sack in sorted(self.sacks.values()): if hasattr(sack, methodName): method = getattr(sack, methodName) try: sackResult = apply(method, args) except PackageSackError: continue if sackResult: result.extend(sackResult) return result def _computeAggregateDictResult(self, methodName, *args): result = {} for sack in sorted(self.sacks.values()): if hasattr(sack, methodName): method = getattr(sack, methodName) try: sackResult = apply(method, args) except PackageSackError: continue if sackResult: result.update(sackResult) return result class PackageSack(PackageSackBase): """represents sets (sacks) of Package Objects""" def __init__(self): PackageSackBase.__init__(self) self.nevra = {} #nevra[(Name, Epoch, Version, Release, Arch)] = [] self.obsoletes = {} #obs[obsoletename] = [pkg1, pkg2, pkg3] #the package lists are packages that obsolete the key name self.requires = {} #req[reqname] = [pkg1, pkg2, pkg3] #the package lists are packages that require the key name self.provides = {} #ditto of above but for provides self.conflicts = {} #ditto of above but for conflicts self.filenames = {} # duh self.pkgsByRepo = {} #pkgsByRepo['repoid']= [pkg1, pkg2, pkg3] self.pkgsByID = {} #pkgsById[pkgid] = [pkg1, pkg2] (should really only ever be one value but #you might have repos with the same package in them self.compatarchs = None # dict of compatible archs for addPackage self.indexesBuilt = 0 def __len__(self): ret = 0 for repo in self.pkgsByRepo: ret += len(self.pkgsByRepo[repo]) return ret def _checkIndexes(self, failure='error'): """check to see if the indexes are built, if not do what failure demands either error out or build the indexes, default is to error out""" if not self.indexesBuilt: if failure == 'error': raise PackageSackError, 'Indexes not yet built, cannot search' elif failure == 'build': self.buildIndexes() def dropCachedData(self): """ Do nothing, mainly for the testing code. """ self.clearIndexes() def setCompatArchs(self, compatarchs): self.compatarchs = compatarchs def searchNevra(self, name=None, epoch=None, ver=None, rel=None, arch=None): """return list of pkgobjects matching the nevra requested""" self._checkIndexes(failure='build') if (name, epoch, ver, rel, arch) in self.nevra: return self.nevra[(name, epoch, ver, rel, arch)] elif name is not None: pkgs = self.nevra.get((name, None, None, None, None), []) else: pkgs = [] for pkgsbyRepo in self.pkgsByRepo.itervalues(): pkgs.extend(pkgsbyRepo) result = [ ] for po in pkgs: if ((name and name!=po.name) or (epoch and epoch!=po.epoch) or (ver and ver!=po.ver) or (rel and rel!=po.rel) or (arch and arch!=po.arch)): continue result.append(po) return result def searchNames(self, names=[], return_pkgtups=False): """return list of pkgobjects matching the names requested""" self._checkIndexes(failure='build') result = [] done = set() for name in names: if name in done: continue done.add(name) result.extend(self.nevra.get((name, None, None, None, None), [])) if return_pkgtups: return [pkg.pkgtup for pkg in result] return result def getProvides(self, name, flags=None, version=(None, None, None)): """return dict { packages -> list of matching provides }""" self._checkIndexes(failure='build') if version is None: version = (None, None, None) elif type(version) in (str, type(None), unicode): version = rpmUtils.miscutils.stringToVersion(version) result = { } for po in self.provides.get(name, []): hits = po.matchingPrcos('provides', (name, flags, version)) if hits: result[po] = hits if name[0] == '/': hit = (name, None, (None, None, None)) for po in self.searchFiles(name): result.setdefault(po, []).append(hit) return result def getRequires(self, name, flags=None, version=(None, None, None)): """return dict { packages -> list of matching requires }""" self._checkIndexes(failure='build') if version is None: version = (None, None, None) elif type(version) in (str, type(None), unicode): version = rpmUtils.miscutils.stringToVersion(version) result = { } for po in self.requires.get(name, []): hits = po.matchingPrcos('requires', (name, flags, version)) if hits: result[po] = hits return result def searchPrco(self, name, prcotype): self._checkIndexes(failure='build') prcodict = getattr(self, prcotype) (n,f,(e,v,r)) = misc.string_to_prco_tuple(name) basic_results = [] results = [] if n in prcodict: basic_results.extend(prcodict[n]) for po in basic_results: if po.checkPrco(prcotype, (n, f, (e,v,r))): results.append(po) if prcotype != "provides": return results if not misc.re_filename(n): return results results.extend(self.searchFiles(n)) return misc.unique(results) def searchRequires(self, name): """return list of package requiring the item requested""" return self.searchPrco(name, 'requires') def searchProvides(self, name): """return list of package providing the item requested""" return self.searchPrco(name, 'provides') def searchConflicts(self, name): """return list of package conflicting with item requested""" return self.searchPrco(name, 'conflicts') def searchObsoletes(self, name): """return list of package obsoleting the item requested""" return self.searchPrco(name, 'obsoletes') def returnObsoletes(self, newest=False): """returns a dict of obsoletes dict[obsoleting pkgtuple] = [list of obs]""" obs = {} for po in self.returnPackages(): if len(po.obsoletes) == 0: continue obs.setdefault(po.pkgtup, []).extend(po.obsoletes) if not newest: return obs # FIXME - this is slooooooooooooooooooooooooooooooow # get the dict back newest_tups = set((pkg.pkgtup for pkg in self.returnNewestByName())) # go through each of the keys of the obs dict and see if it is in the # sack of newest pkgs - if it is not - remove the entry togo = [] for obstup in obs: if obstup not in newest_tups: togo.append(obstup) for obstup in togo: del obs[obstup] return obs def have_fastReturnFileEntries(self): """ Is calling pkg.returnFileEntries(primary_only=True) faster than using searchFiles(). """ return True def searchFiles(self, name): """ Return list of packages by filename. """ self._checkIndexes(failure='build') if name in self.filenames: return self.filenames[name] else: return [] def _addToDictAsList(self, dict, key, data): if key not in dict: dict[key] = [] #if data not in dict[key]: - if I enable this the whole world grinds to a halt # need a faster way of looking for the object in any particular list dict[key].append(data) def _delFromListOfDict(self, dict, key, data): if key not in dict: return try: dict[key].remove(data) except ValueError: pass if len(dict[key]) == 0: # if it's an empty list of the dict, then kill it del dict[key] def addPackage(self, obj): """add a pkgobject to the packageSack""" repoid = obj.repoid (name, arch, epoch, ver, rel) = obj.pkgtup if not self.compatarchs or arch in self.compatarchs: self._addToDictAsList(self.pkgsByRepo, repoid, obj) if self.indexesBuilt: self._addPackageToIndex(obj) def buildIndexes(self): """builds the useful indexes for searching/querying the packageSack This should be called after all the necessary packages have been added/deleted""" self.clearIndexes() for repoid in self.pkgsByRepo: for obj in self.pkgsByRepo[repoid]: self._addPackageToIndex(obj) self.indexesBuilt = 1 def clearIndexes(self): # blank out the indexes self.obsoletes = {} self.requires = {} self.provides = {} self.conflicts = {} self.filenames = {} self.nevra = {} self.pkgsByID = {} self.indexesBuilt = 0 def _addPackageToIndex(self, obj): # store the things provided just on name, not the whole require+version # this lets us reduce the set of pkgs to search when we're trying to depSolve for (n, fl, (e,v,r)) in obj.returnPrco('obsoletes'): self._addToDictAsList(self.obsoletes, n, obj) for (n, fl, (e,v,r)) in obj.returnPrco('requires'): self._addToDictAsList(self.requires, n, obj) for (n, fl, (e,v,r)) in obj.returnPrco('provides'): self._addToDictAsList(self.provides, n, obj) for (n, fl, (e,v,r)) in obj.returnPrco('conflicts'): self._addToDictAsList(self.conflicts, n, obj) for ftype in obj.returnFileTypes(): for file in obj.returnFileEntries(ftype): self._addToDictAsList(self.filenames, file, obj) self._addToDictAsList(self.pkgsByID, obj.id, obj) (name, arch, epoch, ver, rel) = obj.pkgtup self._addToDictAsList(self.nevra, (name, epoch, ver, rel, arch), obj) self._addToDictAsList(self.nevra, (name, None, None, None, None), obj) def _delPackageFromIndex(self, obj): for (n, fl, (e,v,r)) in obj.returnPrco('obsoletes'): self._delFromListOfDict(self.obsoletes, n, obj) for (n, fl, (e,v,r)) in obj.returnPrco('requires'): self._delFromListOfDict(self.requires, n, obj) for (n, fl, (e,v,r)) in obj.returnPrco('provides'): self._delFromListOfDict(self.provides, n, obj) for (n, fl, (e,v,r)) in obj.returnPrco('conflicts'): self._delFromListOfDict(self.conflicts, n, obj) for ftype in obj.returnFileTypes(): for file in obj.returnFileEntries(ftype): self._delFromListOfDict(self.filenames, file, obj) self._delFromListOfDict(self.pkgsByID, obj.id, obj) (name, arch, epoch, ver, rel) = obj.pkgtup self._delFromListOfDict(self.nevra, (name, epoch, ver, rel, arch), obj) self._delFromListOfDict(self.nevra, (name, None, None, None, None), obj) def delPackage(self, obj): """delete a pkgobject""" self._delFromListOfDict(self.pkgsByRepo, obj.repoid, obj) if self.indexesBuilt: self._delPackageFromIndex(obj) def returnPackages(self, repoid=None, patterns=None, ignore_case=False): """return list of all packages, takes optional repoid""" returnList = [] if repoid is None: for repo in self.pkgsByRepo: returnList.extend(self.pkgsByRepo[repo]) else: try: returnList = self.pkgsByRepo[repoid] except KeyError: # nothing to return pass if patterns: returnList = parsePackages(returnList, patterns, not ignore_case, unique='repo-pkgkey') returnList = returnList[0] + returnList[1] return returnList def returnNewestByNameArch(self, naTup=None, patterns=None, ignore_case=False): """return list of newest packages based on name, arch matching this means(in name.arch form): foo.i386 and foo.noarch are not compared to each other for highest version only foo.i386 and foo.i386 will be compared Note that given: foo-1.i386; foo-2.i386 and foo-3.x86_64 The last _two_ pkgs will be returned, not just one of them. """ highdict = {} # If naTup is set, only iterate through packages that match that # name if (naTup): self._checkIndexes(failure='build') where = self.nevra.get((naTup[0],None,None,None,None)) if (not where): raise PackageSackError, 'No Package Matching %s.%s' % naTup else: where = self.returnPackages(patterns=patterns, ignore_case=ignore_case) for pkg in where: if (pkg.name, pkg.arch) not in highdict: highdict[(pkg.name, pkg.arch)] = pkg else: pkg2 = highdict[(pkg.name, pkg.arch)] if pkg.verGT(pkg2): highdict[(pkg.name, pkg.arch)] = pkg if naTup: if naTup in highdict: return [highdict[naTup]] else: raise PackageSackError, 'No Package Matching %s.%s' % naTup return highdict.values() def returnNewestByName(self, name=None, patterns=None, ignore_case=False): """return list of newest packages based on name matching this means(in name.arch form): foo.i386 and foo.noarch will be compared to each other for highest version.""" highdict = {} if patterns is None and name is not None: pkgs = self.searchNevra(name=name) else: pkgs = self.returnPackages(patterns=patterns, ignore_case=ignore_case) for pkg in pkgs: if pkg.name not in highdict: highdict[pkg.name] = [pkg] else: pkg2 = highdict[pkg.name][0] if pkg.verGT(pkg2): highdict[pkg.name] = [pkg] if pkg.verEQ(pkg2): highdict[pkg.name].append(pkg) if name: if name in highdict: return highdict[name] else: raise PackageSackError, 'No Package Matching %s' % name #this is a list of lists - break it back out into a single list returnlist = [] for polst in highdict.values(): for po in polst: returnlist.append(po) return returnlist def simplePkgList(self, patterns=None, ignore_case=False): """returns a list of pkg tuples (n, a, e, v, r) optionally from a single repoid""" # Don't cache due to excludes return [pkg.pkgtup for pkg in self.returnPackages(patterns=patterns, ignore_case=False)] def printPackages(self): for pkg in self.returnPackages(): print pkg def excludeArchs(self, archlist): """exclude incompatible arches. archlist is a list of compatible arches""" for pkg in self.returnPackages(): if pkg.arch not in archlist: self.delPackage(pkg) def searchPackages(self, fields, criteria_re, callback): matches = {} for po in self.returnPackages(): tmpvalues = [] for field in fields: value = getattr(po, field) if value and criteria_re.search(value): tmpvalues.append(value) if len(tmpvalues) > 0: if callback: callback(po, tmpvalues) matches[po] = tmpvalues return matches def packagesNewestByName(pkgs): """ Does the same as PackageSack.returnNewestByName(). Note that given: foo-1.i386; foo-2.i386 and foo-3.x86_64""" newest = {} for pkg in pkgs: key = pkg.name # Can't use pkg.__cmp__ because it takes .arch into account cval = 1 if key in newest: cval = pkg.verCMP(newest[key][0]) if cval > 0: newest[key] = [pkg] elif cval == 0: newest[key].append(pkg) ret = [] for vals in newest.itervalues(): ret.extend(vals) return ret def packagesNewestByNameArch(pkgs): """ Does the same as PackageSack.returnNewestByNameArch() The last _two_ pkgs will be returned, not just one of them.""" newest = {} for pkg in pkgs: key = (pkg.name, pkg.arch) if key in newest and pkg.verLE(newest[key]): continue newest[key] = pkg return newest.values() class ListPackageSack(PackageSack): """Derived class from PackageSack to build new Sack from list of pkgObjects - like one returned from self.returnNewestByNameArch() or self.returnNewestByName()""" def __init__(self, Objlist=None): PackageSack.__init__(self) if Objlist is not None: self.addList(Objlist) def addList(self, ObjList): for pkgobj in ObjList: self.addPackage(pkgobj)