enhance sorting for version comparsion in zypp
[tools/mic.git] / plugins / backend / zypppkgmgr.py
1 #!/usr/bin/python -tt
2 #
3 # Copyright (c) 2010, 2011 Intel, Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation; version 2 of the License
8 #
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 # for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc., 59
16 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 import os
19 import shutil
20 import urlparse
21 import rpm
22
23 import zypp
24 if not hasattr(zypp, 'PoolQuery') or \
25    not hasattr(zypp.RepoManager, 'loadSolvFile'):
26     raise ImportError("python-zypp in host system cannot support PoolQuery or "
27                       "loadSolvFile interface, please update it to enhanced "
28                       "version which can be found in repo.meego.com/tools")
29
30 from mic import msger
31 from mic.kickstart import ksparser
32 from mic.utils import misc, rpmmisc, runner, fs_related
33 from mic.utils.proxy import get_proxy_for
34 from mic.utils.errors import CreatorError, RepoError, RpmError
35 from mic.imager.baseimager import BaseImageCreator
36
37 class RepositoryStub:
38     def __init__(self):
39         self.name = None
40         self.baseurl = []
41         self.mirrorlist = None
42         self.proxy = None
43         self.proxy_username = None
44         self.proxy_password = None
45
46         self.enabled = True
47         self.autorefresh = True
48         self.keeppackages = True
49         self.priority = None
50
51 from mic.pluginbase import BackendPlugin
52 class Zypp(BackendPlugin):
53     name = 'zypp'
54
55     def __init__(self, target_arch, instroot, cachedir):
56         self.cachedir = cachedir
57         self.instroot  = instroot
58         self.target_arch = target_arch
59
60         self.__pkgs_license = {}
61         self.__pkgs_content = {}
62         self.repos = []
63         self.to_deselect = []
64         self.localpkgs = {}
65         self.repo_manager = None
66         self.repo_manager_options = None
67         self.Z = None
68         self.ts = None
69         self.probFilterFlags = []
70         self.incpkgs = {}
71         self.excpkgs = {}
72
73         self.has_prov_query = True
74
75     def doFileLogSetup(self, uid, logfile):
76         # don't do the file log for the livecd as it can lead to open fds
77         # being left and an inability to clean up after ourself
78         pass
79
80     def closeRpmDB(self):
81         pass
82
83     def close(self):
84         if self.ts:
85             self.ts.closeDB()
86             self.ts = None
87
88         self.closeRpmDB()
89
90         if not os.path.exists("/etc/fedora-release") and \
91            not os.path.exists("/etc/meego-release"):
92             for i in range(3, os.sysconf("SC_OPEN_MAX")):
93                 try:
94                     os.close(i)
95                 except:
96                     pass
97
98     def __del__(self):
99         self.close()
100
101     def _cleanupRpmdbLocks(self, installroot):
102         # cleans up temporary files left by bdb so that differing
103         # versions of rpm don't cause problems
104         import glob
105         for f in glob.glob(installroot + "/var/lib/rpm/__db*"):
106             os.unlink(f)
107
108     def setup(self):
109         self._cleanupRpmdbLocks(self.instroot)
110
111     def whatObsolete(self, pkg):
112         query = zypp.PoolQuery()
113         query.addKind(zypp.ResKind.package)
114         query.addAttribute(zypp.SolvAttr.obsoletes, pkg)
115         query.setMatchExact()
116         for pi in query.queryResults(self.Z.pool()):
117             return pi
118         return None
119
120     def _splitPkgString(self, pkg):
121         sp = pkg.rsplit(".",1)
122         name = sp[0]
123         arch = None
124         if len(sp) == 2:
125             arch = sp[1]
126             sysarch = zypp.Arch(self.target_arch)
127             if not zypp.Arch(arch).compatible_with (sysarch):
128                 arch = None
129                 name = ".".join(sp)
130         return name, arch
131
132     def selectPackage(self, pkg):
133         """Select a given package or package pattern, can be specified
134         with name.arch or name* or *name
135         """
136
137         if not self.Z:
138             self.__initialize_zypp()
139
140         def markPoolItem(obs, pi):
141             if obs == None:
142                 pi.status().setToBeInstalled (zypp.ResStatus.USER)
143             else:
144                 obs.status().setToBeInstalled (zypp.ResStatus.USER)
145
146         def cmpEVR(ed1, ed2):
147             (e1, v1, r1) = map(str, [ed1.epoch(), ed1.version(), ed1.release()])
148             (e2, v2, v2) = map(str, [ed2.epoch(), ed2.version(), ed2.release()])
149             return rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
150
151         found = False
152         startx = pkg.startswith("*")
153         endx = pkg.endswith("*")
154         ispattern = startx or endx
155         name, arch = self._splitPkgString(pkg)
156
157         q = zypp.PoolQuery()
158         q.addKind(zypp.ResKind.package)
159
160         if ispattern:
161             if startx and not endx:
162                 pattern = '%s$' % (pkg[1:])
163             if endx and not startx:
164                 pattern = '^%s' % (pkg[0:-1])
165             if endx and startx:
166                 pattern = '%s' % (pkg[1:-1])
167             q.setMatchRegex()
168             q.addAttribute(zypp.SolvAttr.name,pattern)
169
170         elif arch:
171             q.setMatchExact()
172             q.addAttribute(zypp.SolvAttr.name,name)
173
174         else:
175             q.setMatchExact()
176             q.addAttribute(zypp.SolvAttr.name,pkg)
177
178         for item in sorted(
179                         q.queryResults(self.Z.pool()),
180                         cmp=lambda x,y: cmpEVR(x.edition(), y.edition()),
181                         reverse=True):
182
183             if item.name() in self.excpkgs.keys() and \
184                self.excpkgs[item.name()] == item.repoInfo().name():
185                 continue
186             if item.name() in self.incpkgs.keys() and \
187                self.incpkgs[item.name()] != item.repoInfo().name():
188                 continue
189
190             found = True
191             obspkg = self.whatObsolete(item.name())
192             if arch:
193                 if arch == str(item.arch()):
194                     item.status().setToBeInstalled (zypp.ResStatus.USER)
195             else:
196                 markPoolItem(obspkg, item)
197             if not ispattern:
198                 break
199
200         # Can't match using package name, then search from packge
201         # provides infomation
202         if found == False and not ispattern:
203             q.addAttribute(zypp.SolvAttr.provides, pkg)
204             q.addAttribute(zypp.SolvAttr.name,'')
205
206             for item in sorted(
207                             q.queryResults(self.Z.pool()),
208                             cmp=lambda x,y: cmpEVR(x.edition(), y.edition()),
209                             reverse=True):
210                 if item.name() in self.excpkgs.keys() and \
211                    self.excpkgs[item.name()] == item.repoInfo().name():
212                     continue
213                 if item.name() in self.incpkgs.keys() and \
214                    self.incpkgs[item.name()] != item.repoInfo().name():
215                     continue
216
217                 found = True
218                 obspkg = self.whatObsolete(item.name())
219                 markPoolItem(obspkg, item)
220                 break
221
222         if found:
223             return None
224         else:
225             raise CreatorError("Unable to find package: %s" % (pkg,))
226
227     def inDeselectPackages(self, item):
228         """check if specified pacakges are in the list of inDeselectPackages
229         """
230
231         name = item.name()
232         for pkg in self.to_deselect:
233             startx = pkg.startswith("*")
234             endx = pkg.endswith("*")
235             ispattern = startx or endx
236             pkgname, pkgarch = self._splitPkgString(pkg)
237             if not ispattern:
238                 if pkgarch:
239                     if name == pkgname and str(item.arch()) == pkgarch:
240                         return True;
241                 else:
242                     if name == pkgname:
243                         return True;
244             else:
245                 if startx and name.endswith(pkg[1:]):
246                         return True;
247                 if endx and name.startswith(pkg[:-1]):
248                         return True;
249
250         return False;
251
252     def deselectPackage(self, pkg):
253         """collect packages should not be installed"""
254         self.to_deselect.append(pkg)
255
256     def selectGroup(self, grp, include = ksparser.GROUP_DEFAULT):
257         if not self.Z:
258             self.__initialize_zypp()
259         found = False
260         q=zypp.PoolQuery()
261         q.addKind(zypp.ResKind.pattern)
262         for item in q.queryResults(self.Z.pool()):
263             summary = "%s" % item.summary()
264             name = "%s" % item.name()
265             if name == grp or summary == grp:
266                 found = True
267                 item.status().setToBeInstalled (zypp.ResStatus.USER)
268                 break
269
270         if found:
271             if include == ksparser.GROUP_REQUIRED:
272                 map(
273                     lambda p: self.deselectPackage(p),
274                     grp.default_packages.keys())
275
276             return None
277         else:
278             raise CreatorError("Unable to find pattern: %s" % (grp,))
279
280     def addRepository(self, name,
281                             url = None,
282                             mirrorlist = None,
283                             proxy = None,
284                             proxy_username = None,
285                             proxy_password = None,
286                             inc = None,
287                             exc = None,
288                             ssl_verify = True,
289                             cost=None,
290                             priority=None):
291         # TODO: Handle cost attribute for repos
292
293         if not self.repo_manager:
294             self.__initialize_repo_manager()
295
296         if not proxy and url:
297             proxy = get_proxy_for(url)
298
299         repo = RepositoryStub()
300         repo.name = name
301         repo.id = name
302         repo.proxy = proxy
303         repo.proxy_username = proxy_username
304         repo.proxy_password = proxy_password
305         repo.ssl_verify = ssl_verify
306         repo.baseurl.append(url)
307         if inc:
308             for pkg in inc:
309                 self.incpkgs[pkg] = name
310         if exc:
311             for pkg in exc:
312                 self.excpkgs[pkg] = name
313
314         # check LICENSE files
315         if not rpmmisc.checkRepositoryEULA(name, repo):
316             msger.warning('skip repo:%s for failed EULA confirmation' % name)
317             return None
318
319         if mirrorlist:
320             repo.mirrorlist = mirrorlist
321
322         # Enable gpg check for verifying corrupt packages
323         repo.gpgcheck = 1
324         if priority:
325             repo.priority = priority
326         self.repos.append(repo)
327
328         try:
329             repo_info = zypp.RepoInfo()
330             repo_info.setAlias(repo.name)
331             repo_info.setName(repo.name)
332             repo_info.setEnabled(repo.enabled)
333             repo_info.setAutorefresh(repo.autorefresh)
334             repo_info.setKeepPackages(repo.keeppackages)
335             baseurl = zypp.Url(repo.baseurl[0])
336             if not ssl_verify:
337                 baseurl.setQueryParam("ssl_verify", "no")
338             if proxy:
339                 scheme, host, path, parm, query, frag = urlparse.urlparse(proxy)
340
341                 proxyinfo = host.split(":")
342                 host = proxyinfo[0]
343
344                 port = "80"
345                 if len(proxyinfo) > 1:
346                     port = proxyinfo[1]
347
348                 if proxy.startswith("socks") and len(proxy.rsplit(':', 1)) == 2:
349                     host = proxy.rsplit(':', 1)[0]
350                     port = proxy.rsplit(':', 1)[1]
351
352                 baseurl.setQueryParam ("proxy", host)
353                 baseurl.setQueryParam ("proxyport", port)
354
355             repo_info.addBaseUrl(baseurl)
356
357             if repo.priority:
358                 repo_info.setPriority(repo.priority)
359
360             self.repo_manager.addRepository(repo_info)
361
362             self.__build_repo_cache(name)
363
364         except RuntimeError, e:
365             raise CreatorError(str(e))
366
367         msger.verbose('repo: %s was added' % name)
368         return repo
369
370     def installHasFile(self, file):
371         return False
372
373     def runInstall(self, checksize = 0):
374         os.environ["HOME"] = "/"
375         self.buildTransaction()
376
377         todo = zypp.GetResolvablesToInsDel(self.Z.pool())
378         installed_pkgs = todo._toInstall
379         dlpkgs = []
380         for item in installed_pkgs:
381             if not zypp.isKindPattern(item) and \
382                not self.inDeselectPackages(item):
383                 dlpkgs.append(item)
384
385         # record all pkg and the content
386         localpkgs = self.localpkgs.keys()
387         for pkg in dlpkgs:
388             license = ''
389             if pkg.name() in localpkgs:
390                 hdr = rpmmisc.readRpmHeader(self.ts, self.localpkgs[pkg.name()])
391                 pkg_long_name = misc.RPM_FMT % {
392                                     'name': hdr['name'],
393                                     'arch': hdr['arch'],
394                                     'ver_rel': '%s-%s' % (hdr['version'],
395                                                           hdr['release']),
396                                 }
397                 license = hdr['license']
398
399             else:
400                 pkg_long_name = misc.RPM_FMT % {
401                                     'name': pkg.name(),
402                                     'arch': pkg.arch(),
403                                     'ver_rel': pkg.edition(),
404                                 }
405
406                 package = zypp.asKindPackage(pkg)
407                 license = package.license()
408
409             self.__pkgs_content[pkg_long_name] = {} #TBD: to get file list
410
411             if license in self.__pkgs_license.keys():
412                 self.__pkgs_license[license].append(pkg_long_name)
413             else:
414                 self.__pkgs_license[license] = [pkg_long_name]
415
416         total_count = len(dlpkgs)
417         cached_count = 0
418         download_total_size = sum(map(lambda x: int(x.downloadSize()), dlpkgs))
419         localpkgs = self.localpkgs.keys()
420
421         msger.info("Checking packages cache and packages integrity ...")
422         for po in dlpkgs:
423             # Check if it is cached locally
424             if po.name() in localpkgs:
425                 cached_count += 1
426             else:
427                 local = self.getLocalPkgPath(po)
428                 if os.path.exists(local):
429                     if self.checkPkg(local) != 0:
430                         os.unlink(local)
431                     else:
432                         download_total_size -= int(po.downloadSize())
433                         cached_count += 1
434         cache_avail_size = misc.get_filesystem_avail(self.cachedir)
435         if cache_avail_size < download_total_size:
436             raise CreatorError("No enough space used for downloading.")
437
438         # record the total size of installed pkgs
439         install_total_size = sum(map(lambda x: int(x.installSize()), dlpkgs))
440         # check needed size before actually download and install
441
442         # FIXME: for multiple partitions for loop type, check fails
443         #        skip the check temporarily
444         #if checksize and install_total_size > checksize:
445         #    raise CreatorError("No enough space used for installing, "
446         #                       "please resize partition size in ks file")
447
448         download_count =  total_count - cached_count
449         msger.info("%d packages to be installed, "
450                    "%d packages gotten from cache, "
451                    "%d packages to be downloaded" \
452                    % (total_count, cached_count, download_count))
453
454         try:
455             if download_count > 0:
456                 msger.info("Downloading packages ...")
457             self.downloadPkgs(dlpkgs, download_count)
458
459             self.installPkgs(dlpkgs)
460
461         except (RepoError, RpmError):
462             raise
463         except Exception, e:
464             raise CreatorError("Package installation failed: %s" % (e,))
465
466     def getAllContent(self):
467         return self.__pkgs_content
468
469     def getPkgsLicense(self):
470         return self.__pkgs_license
471
472     def __initialize_repo_manager(self):
473         if self.repo_manager:
474             return
475
476         # Clean up repo metadata
477         shutil.rmtree(self.cachedir + "/etc", ignore_errors = True)
478         shutil.rmtree(self.cachedir + "/solv", ignore_errors = True)
479         shutil.rmtree(self.cachedir + "/raw", ignore_errors = True)
480
481         zypp.KeyRing.setDefaultAccept( zypp.KeyRing.ACCEPT_UNSIGNED_FILE
482                                      | zypp.KeyRing.ACCEPT_VERIFICATION_FAILED
483                                      | zypp.KeyRing.ACCEPT_UNKNOWNKEY
484                                      | zypp.KeyRing.TRUST_KEY_TEMPORARILY
485                                      )
486
487         self.repo_manager_options = \
488                 zypp.RepoManagerOptions(zypp.Pathname(self.instroot))
489
490         self.repo_manager_options.knownReposPath = \
491                 zypp.Pathname(self.cachedir + "/etc/zypp/repos.d")
492
493         self.repo_manager_options.repoCachePath = \
494                 zypp.Pathname(self.cachedir)
495
496         self.repo_manager_options.repoRawCachePath = \
497                 zypp.Pathname(self.cachedir + "/raw")
498
499         self.repo_manager_options.repoSolvCachePath = \
500                 zypp.Pathname(self.cachedir + "/solv")
501
502         self.repo_manager_options.repoPackagesCachePath = \
503                 zypp.Pathname(self.cachedir + "/packages")
504
505         self.repo_manager = zypp.RepoManager(self.repo_manager_options)
506
507     def __build_repo_cache(self, name):
508         repo = self.repo_manager.getRepositoryInfo(name)
509         if self.repo_manager.isCached(repo) or not repo.enabled():
510             return
511
512         msger.info('Refreshing repository: %s ...' % name)
513         self.repo_manager.buildCache(repo, zypp.RepoManager.BuildIfNeeded)
514
515     def __initialize_zypp(self):
516         if self.Z:
517             return
518
519         zconfig = zypp.ZConfig_instance()
520
521         # Set system architecture
522         if self.target_arch:
523             zconfig.setSystemArchitecture(zypp.Arch(self.target_arch))
524
525         msger.info("zypp architecture is <%s>" % zconfig.systemArchitecture())
526
527         # repoPackagesCachePath is corrected by this
528         self.repo_manager = zypp.RepoManager(self.repo_manager_options)
529         repos = self.repo_manager.knownRepositories()
530         for repo in repos:
531             if not repo.enabled():
532                 continue
533             self.repo_manager.loadFromCache(repo)
534
535         self.Z = zypp.ZYppFactory_instance().getZYpp()
536         self.Z.initializeTarget(zypp.Pathname(self.instroot))
537         self.Z.target().load()
538
539     def buildTransaction(self):
540         if not self.Z.resolver().resolvePool():
541             probs = self.Z.resolver().problems()
542
543             for problem in probs:
544                 msger.warning("repo problem: %s, %s" \
545                               % (problem.description().decode("utf-8"),
546                                  problem.details().decode("utf-8")))
547
548             raise RepoError("found %d resolver problem, abort!" \
549                             % len(probs))
550
551     def getLocalPkgPath(self, po):
552         repoinfo = po.repoInfo()
553         cacheroot = repoinfo.packagesPath()
554         location= zypp.asKindPackage(po).location()
555         rpmpath = str(location.filename())
556         pkgpath = "%s/%s" % (cacheroot, os.path.basename(rpmpath))
557         return pkgpath
558
559     def installLocal(self, pkg, po=None, updateonly=False):
560         if not self.ts:
561             self.__initialize_transaction()
562
563         solvfile = "%s/.solv" % (self.cachedir)
564
565         rc, out = runner.runtool([fs_related.find_binary_path("rpms2solv"),
566                                   pkg])
567         if rc == 0:
568             f = open(solvfile, "w+")
569             f.write(out)
570             f.close()
571
572             warnmsg = self.repo_manager.loadSolvFile(solvfile,
573                                                      os.path.basename(pkg))
574             if warnmsg:
575                 msger.warning(warnmsg)
576
577             os.unlink(solvfile)
578         else:
579             msger.warning('Can not get %s solv data.' % pkg)
580
581         hdr = rpmmisc.readRpmHeader(self.ts, pkg)
582         arch = zypp.Arch(hdr['arch'])
583         sysarch = zypp.Arch(self.target_arch)
584
585         if arch.compatible_with (sysarch):
586             pkgname = hdr['name']
587             self.localpkgs[pkgname] = pkg
588             self.selectPackage(pkgname)
589             msger.info("Marking %s to be installed" % (pkg))
590
591         else:
592             msger.warning("Cannot add package %s to transaction. "
593                           "Not a compatible architecture: %s" \
594                           % (pkg, hdr['arch']))
595
596     def downloadPkgs(self, package_objects, count):
597         localpkgs = self.localpkgs.keys()
598         progress_obj = rpmmisc.TextProgress(count)
599
600         for po in package_objects:
601             if po.name() in localpkgs:
602                 continue
603
604             filename = self.getLocalPkgPath(po)
605             if os.path.exists(filename):
606                 if self.checkPkg(filename) == 0:
607                     continue
608
609             dirn = os.path.dirname(filename)
610             if not os.path.exists(dirn):
611                 os.makedirs(dirn)
612
613             baseurl = str(po.repoInfo().baseUrls()[0])
614             index = baseurl.find("?")
615             if index > -1:
616                 baseurl = baseurl[:index]
617
618             proxy = self.get_proxy(po.repoInfo())
619             proxies = {}
620             if proxy:
621                 proxies = {str(proxy.split(":")[0]):str(proxy)}
622
623             location = zypp.asKindPackage(po).location()
624             location = str(location.filename())
625             if location.startswith("./"):
626                 location = location[2:]
627
628             url = baseurl + "/%s" % location
629
630             try:
631                 filename = rpmmisc.myurlgrab(url,
632                                              filename,
633                                              proxies,
634                                              progress_obj)
635             except CreatorError:
636                 self.close()
637                 raise
638
639     def installPkgs(self, package_objects):
640         if not self.ts:
641             self.__initialize_transaction()
642
643         # Set filters
644         probfilter = 0
645         for flag in self.probFilterFlags:
646             probfilter |= flag
647         self.ts.setProbFilter(probfilter)
648
649         localpkgs = self.localpkgs.keys()
650
651         for po in package_objects:
652             pkgname = po.name()
653             if pkgname in localpkgs:
654                 rpmpath = self.localpkgs[pkgname]
655             else:
656                 rpmpath = self.getLocalPkgPath(po)
657
658             if not os.path.exists(rpmpath):
659                 # Maybe it is a local repo
660                 baseurl = str(po.repoInfo().baseUrls()[0])
661                 baseurl = baseurl.strip()
662
663                 location = zypp.asKindPackage(po).location()
664                 location = str(location.filename())
665
666                 if baseurl.startswith("file:/"):
667                     rpmpath = baseurl[5:] + "/%s" % (location)
668
669             if not os.path.exists(rpmpath):
670                 raise RpmError("Error: %s doesn't exist" % rpmpath)
671
672             h = rpmmisc.readRpmHeader(self.ts, rpmpath)
673             self.ts.addInstall(h, rpmpath, 'u')
674
675         unresolved_dependencies = self.ts.check()
676         if not unresolved_dependencies:
677             self.ts.order()
678             cb = rpmmisc.RPMInstallCallback(self.ts)
679             installlogfile = "%s/__catched_stderr.buf" % (self.instroot)
680
681             # start to catch stderr output from librpm
682             msger.enable_logstderr(installlogfile)
683
684             errors = self.ts.run(cb.callback, '')
685             # stop catch
686             msger.disable_logstderr()
687             self.ts.closeDB()
688             self.ts = None
689
690             if errors is not None:
691                 if len(errors) == 0:
692                     msger.warning('scriptlet or other non-fatal errors occurred '
693                                   'during transaction.')
694
695                 else:
696                     for e in errors:
697                         msger.warning(e[0])
698                     raise RepoError('Could not run transaction.')
699
700         else:
701             for pkg, need, needflags, sense, key in unresolved_dependencies:
702                 package = '-'.join(pkg)
703
704                 if needflags == rpm.RPMSENSE_LESS:
705                     deppkg = ' < '.join(need)
706                 elif needflags == rpm.RPMSENSE_EQUAL:
707                     deppkg = ' = '.join(need)
708                 elif needflags == rpm.RPMSENSE_GREATER:
709                     deppkg = ' > '.join(need)
710                 else:
711                     deppkg = '-'.join(need)
712
713                 if sense == rpm.RPMDEP_SENSE_REQUIRES:
714                     msger.warning("[%s] Requires [%s], which is not provided" \
715                                   % (package, deppkg))
716
717                 elif sense == rpm.RPMDEP_SENSE_CONFLICTS:
718                     msger.warning("[%s] Conflicts with [%s]" %(package,deppkg))
719
720             raise RepoError("Unresolved dependencies, transaction failed.")
721
722     def __initialize_transaction(self):
723         if not self.ts:
724             self.ts = rpm.TransactionSet(self.instroot)
725             # Set to not verify DSA signatures.
726             self.ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
727
728     def checkPkg(self, pkg):
729         ret = 1
730         if not os.path.exists(pkg):
731             return ret
732         ret = rpmmisc.checkRpmIntegrity('rpm', pkg)
733         if ret != 0:
734             msger.warning("package %s is damaged: %s" \
735                           % (os.path.basename(pkg), pkg))
736
737         return ret
738
739     def _add_prob_flags(self, *flags):
740         for flag in flags:
741            if flag not in self.probFilterFlags:
742                self.probFilterFlags.append(flag)
743
744     def get_proxy(self, repoinfo):
745         proxy = None
746         reponame = "%s" % repoinfo.name()
747         for repo in self.repos:
748             if repo.name == reponame:
749                 proxy = repo.proxy
750                 break
751
752         if proxy:
753             return proxy
754         else:
755             repourl = str(repoinfo.baseUrls()[0])
756             return get_proxy_for(repourl)