1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import rpmUtils
18 import rpmUtils.miscutils
19 import rpmUtils.arch
20
24 """
25 This class computes and keeps track of updates and obsoletes.
26 initialize, add installed packages, add available packages (both as
27 unique lists of name, arch, ver, rel, epoch tuples), add an optional dict
28 of obsoleting packages with obsoletes and what they obsolete ie::
29 foo, i386, 0, 1.1, 1: bar >= 1.1.
30 """
31
32 - def __init__(self, instlist, availlist):
67
69 for key in keys:
70 if key not in dict_:
71 continue
72 dict_[key] = filter(value.__ne__, dict_[key])
73 if not dict_[key]:
74 del dict_[key]
75
77 (n, a, e, v, r) = pkgtup
78 if dict_.has_key((n, a)):
79 dict_[(n, a)] = filter((e,v,r).__ne__, dict_[(n, a)])
80 if not dict_[(n, a)]:
81 del dict_[(n, a)]
82 if dict_.has_key((n, None)):
83 dict_[(n, None)] = filter((e,v,r).__ne__, dict_[(n, None)])
84 if not dict_[(n, None)]:
85 del dict_[(n, None)]
86
88 """remove available pkgtup that is no longer available"""
89 if pkgtup not in self.available:
90 return
91 self.available.remove(pkgtup)
92 self._delFromNADict(self.availdict, pkgtup)
93
94 self._delFromDict(self.updating_dict, self.updatesdict.get(pkgtup, []), pkgtup)
95 self._delFromDict(self.updatesdict, self.updating_dict.get(pkgtup, []), pkgtup)
96
97 if self.rawobsoletes.has_key(pkgtup):
98 if self._obsoletes_by_name:
99 for name, flag, version in self.rawobsoletes[pkgtup]:
100 self._delFromDict(self._obsoletes_by_name, [name], (flag, version, pkgtup))
101 del self.rawobsoletes[pkgtup]
102
103 self._delFromDict(self.obsoleted_dict, self.obsoleting_dict.get(pkgtup, []), pkgtup)
104 self._delFromDict(self.obsoleting_dict, self.obsoleted_dict.get(pkgtup, []), pkgtup)
105
107 if self.debug:
108 print msg
109
111 """return lists of (e,v,r) tuples as value of a dict keyed on (n, a)
112 optionally will return a (n, None) entry with all the a for that
113 n in tuples of (a,e,v,r)"""
114
115 returndict = {}
116 for (n, a, e, v, r) in pkglist:
117 if not returndict.has_key((n, a)):
118 returndict[(n, a)] = []
119 returndict[(n, a)].append((e,v,r))
120
121 if Nonelists:
122 if not returndict.has_key((n, None)):
123 returndict[(n, None)] = []
124 returndict[(n, None)].append((a, e, v, r))
125
126 return returndict
127
128
130 """takes a list of (e, v, r) tuples and returns the newest one"""
131 if len(evrlist)==0:
132 raise rpmUtils.RpmUtilsError, "Zero Length List in returnNewest call"
133
134 if len(evrlist)==1:
135 return evrlist[0]
136
137 (new_e, new_v, new_r) = evrlist[0]
138
139 for (e, v, r) in evrlist[1:]:
140 rc = rpmUtils.miscutils.compareEVR((e, v, r), (new_e, new_v, new_r))
141 if rc > 0:
142 new_e = e
143 new_v = v
144 new_r = r
145 return (new_e, new_v, new_r)
146
147
149 """returns a list of package tuples in a list (n, a, e, v, r)
150 takes a package name, a list of archs, and a list of pkgs in
151 (n, a, e, v, r) form."""
152 returnlist = []
153 high_vertup = None
154 for pkgtup in pkglist:
155 (n, a, e, v, r) = pkgtup
156
157
158 if name == n and a in archlist:
159 vertup = (e, v, r)
160 if (high_vertup is None or
161 (_vertup_cmp(high_vertup, vertup) < 0)):
162 high_vertup = vertup
163 returnlist = []
164 if vertup == high_vertup:
165 returnlist.append(pkgtup)
166
167 return returnlist
168
170 """remove any accidental duplicates in updates"""
171
172 for tup in self.updatesdict:
173 if len(self.updatesdict[tup]) > 1:
174 mylist = self.updatesdict[tup]
175 self.updatesdict[tup] = rpmUtils.miscutils.unique(mylist)
176
177
179 """accept a list of packages to check to see if anything obsoletes them
180 return an obsoleted_dict in the format of makeObsoletedDict"""
181 if self._obsoletes_by_name is None:
182 self._obsoletes_by_name = {}
183 for pkgtup, obsoletes in self.rawobsoletes.iteritems():
184 for name, flag, version in obsoletes:
185 self._obsoletes_by_name.setdefault(name, []).append(
186 (flag, version, pkgtup) )
187
188 obsdict = {}
189 pkgdict = self.makeNADict(pkglist, 1)
190
191 for pkgtup in pkglist:
192 (name, arch, epoch, ver, rel) = pkgtup
193 for obs_flag, obs_version, obsoleting in self._obsoletes_by_name.get(name, []):
194 if obs_flag in [None, 0] and name == obsoleting[0]: continue
195 if rpmUtils.miscutils.rangeCheck( (name, obs_flag, obs_version), pkgtup):
196 obsdict.setdefault(obsoleting, []).append(pkgtup)
197
198 obslist = obsdict.keys()
199 if newest:
200 obslist = self._reduceListNewestByNameArch(obslist)
201
202 returndict = {}
203 for new in obslist:
204 for old in obsdict[new]:
205 if not returndict.has_key(old):
206 returndict[old] = []
207 returndict[old].append(new)
208
209 return returndict
210
212 """figures out what things available obsolete things installed, returns
213 them in a dict attribute of the class."""
214
215 obsdict = {}
216
217
218
219
220
221
222
223
224
225 obs_arches = {}
226 for (n, a, e, v, r) in self.rawobsoletes:
227 if not obs_arches.has_key(n):
228 obs_arches[n] = []
229 obs_arches[n].append(a)
230
231 for pkgtup in self.rawobsoletes:
232 (name, arch, epoch, ver, rel) = pkgtup
233 for (obs_n, flag, (obs_e, obs_v, obs_r)) in self.rawobsoletes[(pkgtup)]:
234 if self.installdict.has_key((obs_n, None)):
235 for (rpm_a, rpm_e, rpm_v, rpm_r) in self.installdict[(obs_n, None)]:
236 if flag in [None, 0] or \
237 rpmUtils.miscutils.rangeCheck((obs_n, flag, (obs_e, obs_v, obs_r)),
238 (obs_n, rpm_a, rpm_e, rpm_v, rpm_r)):
239
240 willInstall = 1
241 if self.installdict.has_key((name, None)):
242 for (ins_a, ins_e, ins_v, ins_r) in self.installdict[(name, None)]:
243 pkgver = (epoch, ver, rel)
244 installedver = (ins_e, ins_v, ins_r)
245 if self.returnNewest((pkgver, installedver)) == installedver:
246 willInstall = 0
247 break
248 if rpm_a != arch and rpm_a in obs_arches[name]:
249 willInstall = 0
250 if willInstall:
251 if not obsdict.has_key(pkgtup):
252 obsdict[pkgtup] = []
253 obsdict[pkgtup].append((obs_n, rpm_a, rpm_e, rpm_v, rpm_r))
254 self.obsoletes = obsdict
255 self.makeObsoletedDict()
256
258 """creates a dict of obsoleted packages -> [obsoleting package], this
259 is to make it easier to look up what package obsoletes what item in
260 the rpmdb"""
261 self.obsoleted_dict = {}
262 for new in self.obsoletes:
263 for old in self.obsoletes[new]:
264 if not self.obsoleted_dict.has_key(old):
265 self.obsoleted_dict[old] = []
266 self.obsoleted_dict[old].append(new)
267 self.obsoleting_dict = {}
268 for obsoleted, obsoletings in self.obsoleted_dict.iteritems():
269 for obsoleting in obsoletings:
270 self.obsoleting_dict.setdefault(obsoleting, []).append(obsoleted)
271
273 """check for key lists as populated then commit acts of evil to
274 determine what is updated and/or obsoleted, populate self.updatesdict
275 """
276
277
278
279
280
281
282
283
284
285
286
287
288
289 simpleupdate = []
290 complexupdate = []
291
292 updatedict = {}
293
294
295
296 newpkgs = self.availdict
297
298 archlist = self._archlist
299 for (n, a) in newpkgs.keys():
300 if a not in archlist:
301
302 del newpkgs[(n, a)]
303 continue
304
305
306
307 for (n, a) in newpkgs:
308 (new_e,new_v,new_r) = self.returnNewest(newpkgs[(n, a)])
309 for (e, v, r) in newpkgs[(n, a)][:]:
310 if (new_e, new_v, new_r) != (e, v, r):
311 newpkgs[(n, a)].remove((e, v, r))
312
313 for (n, a) in newpkgs:
314
315 if self.installdict.has_key((n, a)):
316 for (rpm_e, rpm_v, rpm_r) in self.installdict[(n, a)]:
317 try:
318 (e, v, r) = self.returnNewest(newpkgs[(n,a)])
319 except rpmUtils.RpmUtilsError:
320 continue
321 else:
322 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r))
323 if rc <= 0:
324 try:
325 newpkgs[(n, a)].remove((e, v, r))
326 except ValueError:
327 pass
328
329
330 for na in newpkgs.keys():
331 all_arches = map(lambda x: (na[1], x[0], x[1], x[2]), newpkgs[na])
332 newpkgs.setdefault((na[0], None), []).extend(all_arches)
333
334
335 for nakey in newpkgs.keys():
336 if len(newpkgs[nakey]) == 0:
337 del newpkgs[nakey]
338
339
340
341
342 for (n, a) in newpkgs:
343 if a is None:
344 continue
345
346 if (n, None) in self.installdict:
347 installarchs = []
348 availarchs = []
349 for (a, e, v ,r) in newpkgs[(n, None)]:
350 availarchs.append(a)
351 for (a, e, v, r) in self.installdict[(n, None)]:
352 installarchs.append(a)
353
354 if len(availarchs) > 1 or len(installarchs) > 1:
355 self.debugprint('putting %s in complex update' % n)
356 complexupdate.append(n)
357 else:
358
359 self.debugprint('putting %s in simple update' % n)
360 simpleupdate.append((n, a))
361
362
363
364
365 for (n, a) in simpleupdate:
366
367 if n in self.exactarchlist:
368 if self.installdict.has_key((n, a)):
369 (rpm_e, rpm_v, rpm_r) = self.returnNewest(self.installdict[(n, a)])
370 if newpkgs.has_key((n,a)):
371 (e, v, r) = self.returnNewest(newpkgs[(n, a)])
372 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r))
373 if rc > 0:
374
375 if not updatedict.has_key((n, a, rpm_e, rpm_v, rpm_r)):
376 updatedict[(n, a, rpm_e, rpm_v, rpm_r)] = []
377 updatedict[(n, a, rpm_e, rpm_v, rpm_r)].append((n, a, e, v, r))
378
379 else:
380
381
382
383
384 (rpm_a, rpm_e, rpm_v, rpm_r) = self.installdict[(n, None)][0]
385 if newpkgs.has_key((n, None)):
386 for (a, e, v, r) in newpkgs[(n, None)]:
387 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r))
388 if rc > 0:
389
390 if not updatedict.has_key((n, rpm_a, rpm_e, rpm_v, rpm_r)):
391 updatedict[(n, rpm_a, rpm_e, rpm_v, rpm_r)] = []
392 updatedict[(n, rpm_a, rpm_e, rpm_v, rpm_r)].append((n, a, e, v, r))
393
394
395
396
397
398
399
400
401
402
403
404 archlists = []
405 if self._is_multilib:
406 if rpmUtils.arch.multilibArches.has_key(self.myarch):
407 biarches = [self.myarch]
408 else:
409 biarches = [self.myarch, rpmUtils.arch.arches[self.myarch]]
410 biarches.append('noarch')
411
412 multicompat = self._multilib_compat_arches[0]
413 multiarchlist = rpmUtils.arch.getArchList(multicompat)
414 archlists = [ set(biarches), set(multiarchlist) ]
415
416 else:
417 archlists = [ set(archlist) ]
418
419
420 for n in complexupdate:
421 for thisarchlist in archlists:
422
423
424 tmplist = []
425 for (a, e, v, r) in self.installdict[(n, None)]:
426 tmplist.append((n, a, e, v, r))
427
428 highestinstalledpkgs = self.returnHighestVerFromAllArchsByName(n,
429 thisarchlist, tmplist)
430 hipdict = self.makeNADict(highestinstalledpkgs, 0)
431
432
433 if n in self.exactarchlist:
434 tmplist = []
435 for (a, e, v, r) in newpkgs[(n, None)]:
436 tmplist.append((n, a, e, v, r))
437 highestavailablepkgs = self.returnHighestVerFromAllArchsByName(n,
438 thisarchlist, tmplist)
439
440 hapdict = self.makeNADict(highestavailablepkgs, 0)
441
442 for (n, a) in hipdict:
443 if (n, a) in hapdict:
444 self.debugprint('processing %s.%s' % (n, a))
445
446 (rpm_e, rpm_v, rpm_r) = hipdict[(n, a)][0]
447 (e, v, r) = hapdict[(n, a)][0]
448 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r))
449 if rc > 0:
450
451 if not updatedict.has_key((n, a, rpm_e, rpm_v, rpm_r)):
452 updatedict[(n, a, rpm_e, rpm_v, rpm_r)] = []
453 updatedict[(n, a, rpm_e, rpm_v, rpm_r)].append((n, a, e, v, r))
454 else:
455 self.debugprint('processing %s' % n)
456
457
458 instarchs = []
459 for (n,a) in hipdict:
460 instarchs.append(a)
461
462 rpm_a = rpmUtils.arch.getBestArchFromList(instarchs, myarch=self.myarch)
463 if rpm_a is None:
464 continue
465
466 tmplist = []
467 for (a, e, v, r) in newpkgs[(n, None)]:
468 tmplist.append((n, a, e, v, r))
469 highestavailablepkgs = self.returnHighestVerFromAllArchsByName(n,
470 thisarchlist, tmplist)
471
472 hapdict = self.makeNADict(highestavailablepkgs, 0)
473 availarchs = []
474 for (n,a) in hapdict:
475 availarchs.append(a)
476 a = rpmUtils.arch.getBestArchFromList(availarchs, myarch=self.myarch)
477 if a is None:
478 continue
479
480 (rpm_e, rpm_v, rpm_r) = hipdict[(n, rpm_a)][0]
481 (e, v, r) = hapdict[(n, a)][0]
482 rc = rpmUtils.miscutils.compareEVR((e, v, r), (rpm_e, rpm_v, rpm_r))
483 if rc > 0:
484
485 if not updatedict.has_key((n, rpm_a, rpm_e, rpm_v, rpm_r)):
486 updatedict[(n, rpm_a, rpm_e, rpm_v, rpm_r)] = []
487 updatedict[(n, rpm_a, rpm_e, rpm_v, rpm_r)].append((n, a, e, v, r))
488
489 self.updatesdict = updatedict
490 self.makeUpdatingDict()
491
493 """creates a dict of available packages -> [installed package], this
494 is to make it easier to look up what package will be updating what
495 in the rpmdb"""
496 self.updating_dict = {}
497 for old in self.updatesdict:
498 for new in self.updatesdict[old]:
499 if not self.updating_dict.has_key(new):
500 self.updating_dict[new] = []
501 self.updating_dict[new].append(old)
502
504 """returns a set of pkg naevr tuples reduced based on name or arch"""
505 returnlist = []
506
507 if name or arch:
508 for (n, a, e, v, r) in pkglist:
509 if name:
510 if name == n:
511 returnlist.append((n, a, e, v, r))
512 continue
513 if arch:
514 if arch == a:
515 returnlist.append((n, a, e, v, r))
516 continue
517 else:
518 returnlist = pkglist
519
520 return returnlist
521
522
524 """returns updates for packages in a list of tuples of:
525 (updating naevr, installed naevr)"""
526 returnlist = []
527 for oldtup in self.updatesdict:
528 for newtup in self.updatesdict[oldtup]:
529 returnlist.append((newtup, oldtup))
530
531
532 tmplist = []
533 if name:
534 for ((n, a, e, v, r), oldtup) in returnlist:
535 if name != n:
536 tmplist.append(((n, a, e, v, r), oldtup))
537 if arch:
538 for ((n, a, e, v, r), oldtup) in returnlist:
539 if arch != a:
540 tmplist.append(((n, a, e, v, r), oldtup))
541
542 for item in tmplist:
543 try:
544 returnlist.remove(item)
545 except ValueError:
546 pass
547
548 return returnlist
549
551 """returns updating packages in a list of (naevr) tuples"""
552 returnlist = []
553
554 for oldtup in self.updatesdict:
555 for newtup in self.updatesdict[oldtup]:
556 returnlist.append(newtup)
557
558 returnlist = self.reduceListByNameArch(returnlist, name, arch)
559
560 return returnlist
561
562
563
565 """returns obsoletes for packages in a list of tuples of:
566 (obsoleting naevr, installed naevr). You can specify name and/or
567 arch of the installed package to narrow the results.
568 You can also specify newest=1 to get the set of newest pkgs (name, arch)
569 sorted, that obsolete something"""
570
571 tmplist = []
572 obslist = self.obsoletes.keys()
573 if newest:
574 obslist = self._reduceListNewestByNameArch(obslist)
575
576 for obstup in obslist:
577 for rpmtup in self.obsoletes[obstup]:
578 tmplist.append((obstup, rpmtup))
579
580
581 returnlist = []
582 if name or arch:
583 for (obstup, (n, a, e, v, r)) in tmplist:
584 if name:
585 if name == n:
586 returnlist.append((obstup, (n, a, e, v, r)))
587 continue
588 if arch:
589 if arch == a:
590 returnlist.append((obstup, (n, a, e, v, r)))
591 continue
592 else:
593 returnlist = tmplist
594
595 return returnlist
596
597
598
600 """returns obsoletes for packages in a list of tuples of:
601 (obsoleting naevr, installed naevr). You can specify name and/or
602 arch of the obsoleting package to narrow the results.
603 You can also specify newest=1 to get the set of newest pkgs (name, arch)
604 sorted, that obsolete something"""
605
606 tmplist = []
607 obslist = self.obsoletes.keys()
608 if newest:
609 obslist = self._reduceListNewestByNameArch(obslist)
610
611 for obstup in obslist:
612 for rpmtup in self.obsoletes[obstup]:
613 tmplist.append((obstup, rpmtup))
614
615
616 returnlist = []
617 if name or arch:
618 for ((n, a, e, v, r), insttup) in tmplist:
619 if name:
620 if name == n:
621 returnlist.append(((n, a, e, v, r), insttup))
622 continue
623 if arch:
624 if arch == a:
625 returnlist.append(((n, a, e, v, r), insttup))
626 continue
627 else:
628 returnlist = tmplist
629
630 return returnlist
631
632
633
635 """returns obsoleting packages in a list of naevr tuples of just the
636 packages that obsolete something that is installed. You can specify
637 name and/or arch of the obsoleting packaging to narrow the results.
638 You can also specify newest=1 to get the set of newest pkgs (name, arch)
639 sorted, that obsolete something"""
640
641 tmplist = self.obsoletes.keys()
642 if newest:
643 tmplist = self._reduceListNewestByNameArch(tmplist)
644
645 returnlist = self.reduceListByNameArch(tmplist, name, arch)
646
647 return returnlist
648
650 """returns a list of pkgtuples obsoleting the package in name"""
651 returnlist = []
652 for new in self.obsoletes:
653 for obstup in self.obsoletes[new]:
654 (n, a, e, v, r) = obstup
655 if n == name:
656 returnlist.append(new)
657 continue
658 return returnlist
659
660
661
663 """returns a naevr tuple of the packages that are neither installed
664 nor an update - this may include something that obsoletes an installed
665 package"""
666 updates = {}
667 inst = {}
668 tmplist = []
669
670 for pkgtup in self.getUpdatesList():
671 updates[pkgtup] = 1
672
673 for pkgtup in self.installed:
674 inst[pkgtup] = 1
675
676 for pkgtup in self.available:
677 if pkgtup not in updates and pkgtup not in inst:
678 tmplist.append(pkgtup)
679
680 returnlist = self.reduceListByNameArch(tmplist, name, arch)
681
682 return returnlist
683
684
685
687 """return list of newest packages based on name, arch matching
688 this means(in name.arch form): foo.i386 and foo.noarch are not
689 compared to each other for highest version only foo.i386 and
690 foo.i386 will be compared"""
691 highdict = {}
692 for pkgtup in tuplelist:
693 (n, a, e, v, r) = pkgtup
694 if not highdict.has_key((n, a)):
695 highdict[(n, a)] = pkgtup
696 else:
697 pkgtup2 = highdict[(n, a)]
698 (n2, a2, e2, v2, r2) = pkgtup2
699 rc = rpmUtils.miscutils.compareEVR((e,v,r), (e2, v2, r2))
700 if rc > 0:
701 highdict[(n, a)] = pkgtup
702
703 return highdict.values()
704
705
706
707
708
709
710
711
712