3 # Copyright (c) 2010, 2011 Intel, Inc.
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
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
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.
24 import zypp #pylint: disable=import-error
25 if not hasattr(zypp, 'PoolQuery') or \
26 not hasattr(zypp.RepoManager, 'loadSolvFile'):
27 raise ImportError("python-zypp in host system cannot support PoolQuery or "
28 "loadSolvFile interface, please update it to enhanced "
29 "version which can be found in download.tizen.org/tools")
32 from mic.kickstart import ksparser
33 from mic.utils import misc, rpmmisc, runner, fs_related
34 from mic.utils.grabber import myurlgrab, TextProgress
35 from mic.utils.proxy import get_proxy_for
36 from mic.utils.errors import CreatorError, RepoError, RpmError
37 from mic.conf import configmgr
43 self.mirrorlist = None
45 self.proxy_username = None
46 self.proxy_password = None
50 self.autorefresh = True
51 self.keeppackages = True
54 from mic.pluginbase import BackendPlugin
55 class Zypp(BackendPlugin):
58 def __init__(self, target_arch, instroot, cachedir, strict_mode = False):
59 self.cachedir = cachedir
60 self.instroot = instroot
61 self.target_arch = target_arch
62 self.strict_mode = strict_mode
64 self.__pkgs_license = {}
65 self.__pkgs_content = {}
66 self.__pkgs_vcsinfo = {}
70 self.repo_manager = None
71 self.repo_manager_options = None
79 self.probFilterFlags = [ rpm.RPMPROB_FILTER_OLDPACKAGE,
80 rpm.RPMPROB_FILTER_REPLACEPKG ]
82 self.has_prov_query = True
83 self.install_debuginfo = False
84 # this can't be changed, it is used by zypp
85 self.tmp_file_path = '/var/tmp'
87 def doFileLogSetup(self, uid, logfile):
88 # don't do the file log for the livecd as it can lead to open fds
89 # being left and an inability to clean up after ourself
101 self.ts_pre.closeDB()
109 def _cleanupRpmdbLocks(self, installroot):
110 # cleans up temporary files left by bdb so that differing
111 # versions of rpm don't cause problems
112 for f in glob.glob(installroot + "/var/lib/rpm/__db*"):
115 def _cleanupZyppJunk(self, installroot):
117 shutil.rmtree(os.path.join(installroot, '.zypp'))
122 self._cleanupRpmdbLocks(self.instroot)
123 # '/var/tmp' is used by zypp to build cache, so make sure
125 if not os.path.exists(self.tmp_file_path ):
126 os.makedirs(self.tmp_file_path)
128 def whatObsolete(self, pkg):
129 query = zypp.PoolQuery()
130 query.addKind(zypp.ResKind.package)
131 query.addDependency(zypp.SolvAttr.obsoletes, pkg.name(), pkg.edition())
132 query.setMatchExact()
133 for pi in query.queryResults(self.Z.pool()):
137 def _zyppQueryPackage(self, pkg):
138 query = zypp.PoolQuery()
139 query.addKind(zypp.ResKind.package)
140 query.addAttribute(zypp.SolvAttr.name, pkg)
141 query.setMatchExact()
142 for pi in query.queryResults(self.Z.pool()):
146 def _splitPkgString(self, pkg):
147 sp = pkg.rsplit(".", 1)
152 sysarch = zypp.Arch(self.target_arch)
153 if not zypp.Arch(arch).compatible_with (sysarch):
158 def selectPackage(self, pkg):
159 """Select a given package or package pattern, can be specified
160 with name.arch or name* or *name
164 self.__initialize_zypp()
166 def markPoolItem(obs, pi):
168 pi.status().setToBeInstalled (zypp.ResStatus.USER)
170 obs.status().setToBeInstalled (zypp.ResStatus.USER)
173 # compare criterion: arch compatibility first, then repo
174 # priority, and version last
177 if str(a1) != str(a2):
178 if a1.compatible_with(a2):
182 # Priority of a repository is an integer value between 0 (the
183 # highest priority) and 99 (the lowest priority)
184 pr1 = int(p1.repoInfo().priority())
185 pr2 = int(p2.repoInfo().priority())
193 (e1, v1, r1) = map(str, [ed1.epoch(), ed1.version(), ed1.release()])
194 (e2, v2, r2) = map(str, [ed2.epoch(), ed2.version(), ed2.release()])
195 return rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
198 startx = pkg.startswith("*")
199 endx = pkg.endswith("*")
200 ispattern = startx or endx
201 name, arch = self._splitPkgString(pkg)
204 q.addKind(zypp.ResKind.package)
207 if startx and not endx:
208 pattern = '%s$' % (pkg[1:])
209 if endx and not startx:
210 pattern = '^%s' % (pkg[0:-1])
212 pattern = '%s' % (pkg[1:-1])
214 q.addAttribute(zypp.SolvAttr.name, pattern)
218 q.addAttribute(zypp.SolvAttr.name, name)
222 q.addAttribute(zypp.SolvAttr.name, pkg)
225 q.queryResults(self.Z.pool()),
226 cmp=lambda x,y: cmpEVR(zypp.asKindPackage(x), zypp.asKindPackage(y)),
228 item = zypp.asKindPackage(pitem)
229 if item.name() in self.excpkgs.keys() and \
230 self.excpkgs[item.name()] == item.repoInfo().name():
232 if item.name() in self.incpkgs.keys() and \
233 self.incpkgs[item.name()] != item.repoInfo().name():
237 obspkg = self.whatObsolete(item)
239 if arch == str(item.arch()):
240 pitem.status().setToBeInstalled (zypp.ResStatus.USER)
242 markPoolItem(obspkg, pitem)
246 # Can't match using package name, then search from packge
247 # provides infomation
248 if found == False and not ispattern:
249 q.addAttribute(zypp.SolvAttr.provides, pkg)
250 q.addAttribute(zypp.SolvAttr.name,'')
253 q.queryResults(self.Z.pool()),
254 cmp=lambda x,y: cmpEVR(zypp.asKindPackage(x), zypp.asKindPackage(y)),
256 item = zypp.asKindPackage(pitem)
257 if item.name() in self.excpkgs.keys() and \
258 self.excpkgs[item.name()] == item.repoInfo().name():
260 if item.name() in self.incpkgs.keys() and \
261 self.incpkgs[item.name()] != item.repoInfo().name():
265 obspkg = self.whatObsolete(item)
266 markPoolItem(obspkg, pitem)
272 raise CreatorError("Unable to find package: %s" % (pkg,))
274 def inDeselectPackages(self, pitem):
275 """check if specified pacakges are in the list of inDeselectPackages
277 item = zypp.asKindPackage(pitem)
279 for pkg in self.to_deselect:
280 startx = pkg.startswith("*")
281 endx = pkg.endswith("*")
282 ispattern = startx or endx
283 pkgname, pkgarch = self._splitPkgString(pkg)
286 if name == pkgname and str(item.arch()) == pkgarch:
292 if startx and name.endswith(pkg[1:]):
294 if endx and name.startswith(pkg[:-1]):
299 def deselectPackage(self, pkg):
300 """collect packages should not be installed"""
301 self.to_deselect.append(pkg)
303 def selectGroup(self, grp, include = ksparser.GROUP_DEFAULT):
304 def compareGroup(pitem):
305 item = zypp.asKindPattern(pitem)
306 return item.repoInfo().priority()
308 self.__initialize_zypp()
311 q.addKind(zypp.ResKind.pattern)
312 for pitem in sorted(q.queryResults(self.Z.pool()), key=compareGroup):
313 item = zypp.asKindPattern(pitem)
314 summary = "%s" % item.summary()
315 name = "%s" % item.name()
316 if name == grp or summary == grp:
318 pitem.status().setToBeInstalled (zypp.ResStatus.USER)
322 if include == ksparser.GROUP_REQUIRED:
324 lambda p: self.deselectPackage(p),
325 grp.default_packages.keys())
329 raise CreatorError("Unable to find pattern: %s" % (grp,))
331 def addRepository(self, name,
335 proxy_username = None,
336 proxy_password = None,
343 # TODO: Handle cost attribute for repos
345 if not self.repo_manager:
346 self.__initialize_repo_manager()
348 if not proxy and url:
349 proxy = get_proxy_for(url)
351 repo = RepositoryStub()
355 repo.proxy_username = proxy_username
356 repo.proxy_password = proxy_password
357 repo.ssl_verify = ssl_verify
358 repo.nocache = nocache
359 repo.baseurl.append(url)
362 self.incpkgs[pkg] = name
365 self.excpkgs[pkg] = name
368 repo.mirrorlist = mirrorlist
370 # Enable gpg check for verifying corrupt packages
372 if priority is not None:
373 # priority 0 has issue in RepoInfo.setPriority
374 repo.priority = priority + 1
377 repo_info = zypp.RepoInfo()
378 repo_info.setAlias(repo.name)
379 repo_info.setName(repo.name)
380 repo_info.setEnabled(repo.enabled)
381 repo_info.setAutorefresh(repo.autorefresh)
382 repo_info.setKeepPackages(repo.keeppackages)
383 baseurl = zypp.Url(repo.baseurl[0].full)
385 baseurl.setQueryParam("ssl_verify", "no")
387 host = urlparse.urlparse(proxy)[1]
388 # scheme, host, path, parm, query, frag = urlparse.urlparse(proxy)
390 proxyinfo = host.rsplit(":", 1)
394 if len(proxyinfo) > 1:
397 if proxy.startswith("socks") and len(proxy.rsplit(':', 1)) == 2:
398 host = proxy.rsplit(':', 1)[0]
399 port = proxy.rsplit(':', 1)[1]
401 # parse user/pass from proxy host
402 proxyinfo = host.rsplit("@", 1)
403 if len(proxyinfo) == 2:
405 # Known Issue: If password contains ":", which should be
406 # quoted, for example, use '123%3Aabc' instead of 123:abc
407 userpassinfo = proxyinfo[0].rsplit(":", 1)
408 if len(userpassinfo) == 2:
409 proxy_username = userpassinfo[0]
410 proxy_password = userpassinfo[1]
411 elif len(userpassinfo) == 1:
412 proxy_username = userpassinfo[0]
414 baseurl.setQueryParam ("proxy", host)
415 baseurl.setQueryParam ("proxyport", port)
417 baseurl.setQueryParam ("proxyuser", proxy_username)
419 baseurl.setQueryParam ("proxypass", proxy_password)
421 baseurl.setQueryParam ("proxy", "_none_")
423 self.repos.append(repo)
425 repo_info.addBaseUrl(baseurl)
427 if repo.priority is not None:
428 repo_info.setPriority(repo.priority)
430 # this hack is used to change zypp credential file location
431 # the default one is $HOME/.zypp, which cause conflicts when
432 # installing some basic packages, and the location doesn't
433 # have any interface actually, so use a tricky way anyway
435 if 'HOME' in os.environ:
436 homedir = os.environ['HOME']
437 os.environ['HOME'] = '/'
439 os.environ['HOME'] = '/'
441 self.repo_manager.addRepository(repo_info)
443 # save back the $HOME env
445 os.environ['HOME'] = homedir
447 del os.environ['HOME']
449 self.__build_repo_cache(name)
451 except RuntimeError as e:
452 raise CreatorError(str(e))
454 msger.verbose('repo: %s was added' % name)
457 def installHasFile(self, file):
460 def preInstall(self, pkg):
461 self.pre_pkgs.append(pkg)
463 def checkPackage(self, pkg):
464 self.check_pkgs.append(pkg)
466 def _get_local_packages(self):
467 """Return a list of rpm path to be local installed.
468 This is the hook where subclasses may specify a set of rpms which
469 it requires to be installed locally.
470 This returns an empty list by default.
471 Note, subclasses should usually chain up to the base class
472 implementation of this hook.
474 cropts = configmgr.create
475 if cropts['local_pkgs_path']:
476 if os.path.isdir(cropts['local_pkgs_path']):
478 os.path.join(cropts['local_pkgs_path'], '*.rpm'))
479 elif os.path.splitext(cropts['local_pkgs_path'])[-1] == '.rpm':
480 return [cropts['local_pkgs_path']]
482 def __localinst_packages(self):
483 for rpm_path in self._get_local_packages():
484 self.installLocal(rpm_path)
485 def runInstall(self, checksize = 0):
486 os.environ["HOME"] = "/"
487 os.environ["LD_PRELOAD"] = ""
488 self.buildTransaction()
489 self.__localinst_packages()
491 todo = zypp.GetResolvablesToInsDel(self.Z.pool())
492 installed_pkgs = todo._toInstall
495 for pitem in installed_pkgs:
496 if not zypp.isKindPattern(pitem) and \
497 not self.inDeselectPackages(pitem):
498 item = zypp.asKindPackage(pitem)
501 if item.name() in self.check_pkgs:
502 self.check_pkgs.remove(item.name())
504 if not self.install_debuginfo or str(item.arch()) == "noarch":
507 dipkg = self._zyppQueryPackage("%s-debuginfo" % item.name())
509 ditem = zypp.asKindPackage(dipkg)
512 msger.warning("No debuginfo rpm found for: %s" \
516 raise CreatorError('Packages absent in image: %s' % ','.join(self.check_pkgs))
518 # record all pkg and the content
519 localpkgs = self.localpkgs.keys()
522 if pkg.name() in localpkgs:
523 hdr = rpmmisc.readRpmHeader(self.ts, self.localpkgs[pkg.name()])
524 pkg_long_name = misc.RPM_FMT % {
527 'version': hdr['version'],
528 'release': hdr['release']
530 license = hdr['license']
533 pkg_long_name = misc.RPM_FMT % {
536 'version': pkg.edition().version(),
537 'release': pkg.edition().release()
540 license = pkg.license()
542 if license in self.__pkgs_license.keys():
543 self.__pkgs_license[license].append(pkg_long_name)
545 self.__pkgs_license[license] = [pkg_long_name]
547 total_count = len(dlpkgs)
549 download_total_size = sum(map(lambda x: int(x.downloadSize()), dlpkgs))
550 localpkgs = self.localpkgs.keys()
552 msger.info("Checking packages cached ...")
554 # Check if it is cached locally
555 if po.name() in localpkgs:
558 local = self.getLocalPkgPath(po)
559 name = str(po.repoInfo().name())
561 repo = filter(lambda r: r.name == name, self.repos)[0]
564 nocache = repo.nocache if repo else False
566 if os.path.exists(local):
567 if nocache or self.checkPkg(local) !=0:
570 download_total_size -= int(po.downloadSize())
572 cache_avail_size = misc.get_filesystem_avail(self.cachedir)
573 if cache_avail_size < download_total_size:
574 raise CreatorError("No enough space used for downloading.")
576 # record the total size of installed pkgs
577 install_total_size = sum(map(lambda x: int(x.installSize()), dlpkgs))
578 # check needed size before actually download and install
580 # FIXME: for multiple partitions for loop type, check fails
581 # skip the check temporarily
582 #if checksize and install_total_size > checksize:
583 # raise CreatorError("No enough space used for installing, "
584 # "please resize partition size in ks file")
586 download_count = total_count - cached_count
587 msger.info("Packages: %d Total, %d Cached, %d Missed" \
588 % (total_count, cached_count, download_count))
591 if download_count > 0:
592 msger.info("Downloading packages ...")
593 self.downloadPkgs(dlpkgs, download_count)
594 except CreatorError as e:
595 raise CreatorError("Package download failed: %s" %(e,))
598 self.installPkgs(dlpkgs)
599 except (RepoError, RpmError):
601 except Exception as e:
602 raise CreatorError("Package installation failed: %s" % (e,))
604 def getVcsInfo(self):
605 if self.__pkgs_vcsinfo:
609 self.__initialize_transaction()
611 mi = self.ts.dbMatch()
613 lname = misc.RPM_FMT % {
616 'version': hdr['version'],
617 'release': hdr['release']
620 self.__pkgs_vcsinfo[lname] = hdr['VCS']
622 # if rpm not support VCS, set to None
623 self.__pkgs_vcsinfo[lname] = None
625 return self.__pkgs_vcsinfo
627 def getAllContent(self):
628 if self.__pkgs_content:
629 return self.__pkgs_content
632 self.__initialize_transaction()
634 mi = self.ts.dbMatch()
636 lname = misc.RPM_FMT % {
639 'version': hdr['version'],
640 'release': hdr['release']
642 self.__pkgs_content[lname] = hdr['FILENAMES']
644 return self.__pkgs_content
646 def getPkgsLicense(self):
647 return self.__pkgs_license
649 def getFilelist(self, pkgname):
654 self.__initialize_transaction()
656 mi = self.ts.dbMatch('name', pkgname)
658 return header['FILENAMES']
660 def __initialize_repo_manager(self):
661 if self.repo_manager:
664 # Clean up repo metadata
665 shutil.rmtree(self.cachedir + "/etc", ignore_errors = True)
666 shutil.rmtree(self.cachedir + "/solv", ignore_errors = True)
667 shutil.rmtree(self.cachedir + "/raw", ignore_errors = True)
669 zypp.KeyRing.setDefaultAccept( zypp.KeyRing.ACCEPT_UNSIGNED_FILE
670 | zypp.KeyRing.ACCEPT_VERIFICATION_FAILED
671 | zypp.KeyRing.ACCEPT_UNKNOWNKEY
672 | zypp.KeyRing.TRUST_KEY_TEMPORARILY
675 self.repo_manager_options = \
676 zypp.RepoManagerOptions(zypp.Pathname(self.instroot))
678 self.repo_manager_options.knownReposPath = \
679 zypp.Pathname(self.cachedir + "/etc/zypp/repos.d")
681 self.repo_manager_options.repoCachePath = \
682 zypp.Pathname(self.cachedir)
684 self.repo_manager_options.repoRawCachePath = \
685 zypp.Pathname(self.cachedir + "/raw")
687 self.repo_manager_options.repoSolvCachePath = \
688 zypp.Pathname(self.cachedir + "/solv")
690 self.repo_manager_options.repoPackagesCachePath = \
691 zypp.Pathname(self.cachedir + "/packages")
693 self.repo_manager = zypp.RepoManager(self.repo_manager_options)
695 def __build_repo_cache(self, name):
696 repo = self.repo_manager.getRepositoryInfo(name)
697 if self.repo_manager.isCached(repo) or not repo.enabled():
700 msger.info('Refreshing repository: %s ...' % name)
701 self.repo_manager.buildCache(repo, zypp.RepoManager.BuildIfNeeded)
703 def __initialize_zypp(self):
707 zconfig = zypp.ZConfig_instance()
709 # Set system architecture
711 zconfig.setSystemArchitecture(zypp.Arch(self.target_arch))
713 msger.info("zypp architecture is <%s>" % zconfig.systemArchitecture())
715 # repoPackagesCachePath is corrected by this
716 self.repo_manager = zypp.RepoManager(self.repo_manager_options)
717 repos = self.repo_manager.knownRepositories()
719 if not repo.enabled():
721 self.repo_manager.loadFromCache(repo)
723 self.Z = zypp.ZYppFactory_instance().getZYpp()
724 if configmgr.create['block_recommends']:
725 msger.info("zypp not install recommend packages")
726 self.Z.resolver().setOnlyRequires(True)
727 self.Z.initializeTarget(zypp.Pathname(self.instroot))
728 self.Z.target().load()
730 def buildTransaction(self):
731 if not self.Z.resolver().resolvePool():
732 probs = self.Z.resolver().problems()
734 for problem in probs:
735 msger.warning("repo problem: %s, %s" \
736 % (problem.description().decode("utf-8"),
737 problem.details().decode("utf-8")))
739 raise RepoError("found %d resolver problem, abort!" \
742 def getLocalPkgPath(self, po):
743 repoinfo = po.repoInfo()
744 cacheroot = repoinfo.packagesPath()
745 location = po.location()
746 rpmpath = str(location.filename())
747 pkgpath = "%s/%s" % (cacheroot, os.path.basename(rpmpath))
750 def installLocal(self, pkg, po=None, updateonly=False):
752 self.__initialize_transaction()
754 solvfile = "%s/.solv" % (self.cachedir)
756 rc, out = runner.runtool([fs_related.find_binary_path("rpms2solv"),
759 f = open(solvfile, "w+")
763 warnmsg = self.repo_manager.loadSolvFile(solvfile,
764 os.path.basename(pkg))
766 msger.warning(warnmsg)
770 msger.warning('Can not get %s solv data.' % pkg)
772 hdr = rpmmisc.readRpmHeader(self.ts, pkg)
773 arch = zypp.Arch(hdr['arch'])
774 sysarch = zypp.Arch(self.target_arch)
776 if arch.compatible_with (sysarch):
777 pkgname = hdr['name']
778 self.localpkgs[pkgname] = pkg
779 self.selectPackage(pkgname)
780 msger.info("Marking %s to be installed" % (pkg))
783 msger.warning("Cannot add package %s to transaction. "
784 "Not a compatible architecture: %s" \
785 % (pkg, hdr['arch']))
787 def downloadPkgs(self, package_objects, count):
788 localpkgs = self.localpkgs.keys()
789 progress_obj = TextProgress(count)
791 for po in package_objects:
792 if po.name() in localpkgs:
795 filename = self.getLocalPkgPath(po)
796 if os.path.exists(filename):
797 if self.checkPkg(filename) == 0:
800 dirn = os.path.dirname(filename)
801 if not os.path.exists(dirn):
804 url = self.get_url(po)
805 proxies = self.get_proxies(po)
808 filename = myurlgrab(url.full, filename, proxies, progress_obj)
813 def preinstallPkgs(self):
815 self.__initialize_transaction()
818 cb = rpmmisc.RPMInstallCallback(self.ts_pre)
819 cb.headmsg = "Preinstall"
820 installlogfile = "%s/__catched_stderr.buf" % (self.instroot)
822 # start to catch stderr output from librpm
823 msger.enable_logstderr(installlogfile)
825 errors = self.ts_pre.run(cb.callback, '')
827 msger.disable_logstderr()
828 self.ts_pre.closeDB()
831 if errors is not None:
833 msger.warning('scriptlet or other non-fatal errors occurred '
834 'during transaction.')
839 raise RepoError('Could not run transaction.')
840 def show_unresolved_dependencies_msg(self, unresolved_dependencies):
841 for pkg, need, needflags, sense, key in unresolved_dependencies:
843 package = '-'.join(pkg)
845 if needflags == rpm.RPMSENSE_LESS:
846 deppkg = ' < '.join(need)
847 elif needflags == rpm.RPMSENSE_EQUAL:
848 deppkg = ' = '.join(need)
849 elif needflags == rpm.RPMSENSE_GREATER:
850 deppkg = ' > '.join(need)
852 deppkg = '-'.join(need)
854 if sense == rpm.RPMDEP_SENSE_REQUIRES:
855 msger.warning("[%s] Requires [%s], which is not provided" \
858 elif sense == rpm.RPMDEP_SENSE_CONFLICTS:
859 msger.warning("[%s] Conflicts with [%s]" % (package, deppkg))
861 def installPkgs(self, package_objects):
863 self.__initialize_transaction()
866 self._cleanupRpmdbLocks(self.instroot)
867 self._cleanupZyppJunk(self.instroot)
870 for flag in self.probFilterFlags:
872 self.ts.setProbFilter(probfilter)
873 self.ts_pre.setProbFilter(probfilter)
875 localpkgs = self.localpkgs.keys()
877 for po in package_objects:
879 if pkgname in localpkgs:
880 rpmpath = self.localpkgs[pkgname]
882 rpmpath = self.getLocalPkgPath(po)
884 if not os.path.exists(rpmpath):
885 # Maybe it is a local repo
886 rpmuri = self.get_url(po)
887 if rpmuri.startswith("file:/"):
890 if not os.path.exists(rpmpath):
891 raise RpmError("Error: %s doesn't exist" % rpmpath)
893 h = rpmmisc.readRpmHeader(self.ts, rpmpath)
895 if pkgname in self.pre_pkgs:
896 msger.verbose("pre-install package added: %s" % pkgname)
897 self.ts_pre.addInstall(h, rpmpath, 'u')
899 self.ts.addInstall(h, rpmpath, 'u')
901 unresolved_dependencies = self.ts.check()
902 if not unresolved_dependencies:
904 self.preinstallPkgs()
907 cb = rpmmisc.RPMInstallCallback(self.ts)
908 installlogfile = "%s/__catched_stderr.buf" % (self.instroot)
910 # start to catch stderr output from librpm
911 msger.enable_logstderr(installlogfile)
913 errors = self.ts.run(cb.callback, '')
915 msger.disable_logstderr()
919 if errors is not None:
921 msger.warning('scriptlet or other non-fatal errors occurred '
922 'during transaction.')
924 raise CreatorError("mic failes to install some packages")
928 raise RepoError('Could not run transaction.')
931 self.show_unresolved_dependencies_msg(unresolved_dependencies)
932 raise RepoError("Unresolved dependencies, transaction failed.")
934 def __initialize_transaction(self):
936 self.ts = rpm.TransactionSet(self.instroot)
937 # Set to not verify DSA signatures.
938 self.ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
941 self.ts_pre = rpm.TransactionSet(self.instroot)
942 # Just unpack the files, don't run scripts
943 self.ts_pre.setFlags(rpm.RPMTRANS_FLAG_ALLFILES | rpm.RPMTRANS_FLAG_NOSCRIPTS)
944 # Set to not verify DSA signatures.
945 self.ts_pre.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
947 def checkPkg(self, pkg):
949 if not os.path.exists(pkg):
951 ret = rpmmisc.checkRpmIntegrity('rpm', pkg)
953 msger.warning("package %s is damaged: %s" \
954 % (os.path.basename(pkg), pkg))
958 def _add_prob_flags(self, *flags):
960 if flag not in self.probFilterFlags:
961 self.probFilterFlags.append(flag)
963 def get_proxies(self, pobj):
969 repoinfo = pobj.repoInfo()
970 reponame = "%s" % repoinfo.name()
971 repos = filter(lambda r: r.name == reponame, self.repos)
972 repourl = str(repoinfo.baseUrls()[0])
975 proxy = repos[0].proxy
977 proxy = get_proxy_for(repourl)
979 proxies = {str(repourl.split(':')[0]): str(proxy)}
983 def get_url(self, pobj):
987 name = str(pobj.repoInfo().name())
989 repo = filter(lambda r: r.name == name, self.repos)[0]
993 location = pobj.location()
994 location = str(location.filename())
995 if location.startswith("./"):
996 location = location[2:]
998 return repo.baseurl[0].join(location)
1000 def package_url(self, pkgname):
1005 (e1, v1, r1) = map(str, [ed1.epoch(), ed1.version(), ed1.release()])
1006 (e2, v2, r2) = map(str, [ed2.epoch(), ed2.version(), ed2.release()])
1007 return rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
1010 self.__initialize_zypp()
1012 q = zypp.PoolQuery()
1013 q.addKind(zypp.ResKind.package)
1015 q.addAttribute(zypp.SolvAttr.name, pkgname)
1016 items = sorted(q.queryResults(self.Z.pool()),
1017 cmp=lambda x,y: cmpEVR(zypp.asKindPackage(x), zypp.asKindPackage(y)),
1021 item = zypp.asKindPackage(items[0])
1022 url = self.get_url(item)
1023 proxies = self.get_proxies(item)
1024 return (url, proxies)