commit 7f49e9ef65bc592c31f881c8ab83275cfa3c9283
Author: Yi Yang <[email protected]>
Date:   Wed Nov 17 16:21:21 2010 +0800

    Add zypper package manager implementation
    
    Note: with this commit, mic2 can work without yum dependency, but
    this commit depends on libzypp-bindings, currently this implementation
    is just experimental and still undergoing changes.

diff --git a/mic/appcreate/nand.py b/mic/appcreate/nand.py
index 9d56835..30c27f5 100644
--- a/mic/appcreate/nand.py
+++ b/mic/appcreate/nand.py
@@ -282,7 +282,14 @@ class NandImageCreator(ApplianceImageCreator):
         yum_conf = self._mktemp(prefix = "yum.conf-")
 
         self._required_pkgs = self._get_required_packages()
-        pkg_manager = self.get_pkg_manager()
+
+        keep_record = None
+        if self._include_src:
+            keep_record = 'include_src'
+        if self._recording_pkgs in ('name', 'content'):
+            keep_record = self._recording_pkgs
+
+        pkg_manager = self.get_pkg_manager(keep_record, target_arch = 
self.target_arch)
         pkg_manager.setup(yum_conf, self._instroot)
 
         for repo in kickstart.get_repos(self.ks, repo_urls):
@@ -332,6 +339,8 @@ class NandImageCreator(ApplianceImageCreator):
             except CreatorError, e:
                 raise CreatorError("%s" % (e,))
         finally:
+            if keep_record:
+                self._pkgs_content = pkg_manager.getAllContent()
             pkg_manager.closeRpmDB()
             pkg_manager.close()
             os.unlink(yum_conf)
diff --git a/mic/imgcreate/creator.py b/mic/imgcreate/creator.py
index ee78b92..90fe744 100644
--- a/mic/imgcreate/creator.py
+++ b/mic/imgcreate/creator.py
@@ -785,7 +785,7 @@ class ImageCreator(object):
         keep_record = None
         if self._include_src:
             keep_record = 'include_src'
-        if self._recording_pkgs in ('name', 'contents'):
+        if self._recording_pkgs in ('name', 'content'):
             keep_record = self._recording_pkgs
 
         pkg_manager = self.get_pkg_manager(keep_record, target_arch = 
self.target_arch)
@@ -1080,7 +1080,7 @@ class ImageCreator(object):
         pkgmgr_instance = self.pkgmgr.get_default_pkg_manager()
         if not pkgmgr_instance:
             raise CreatorError("No pakcgae manager available")
-        return pkgmgr_instance(recording_pkgs, target_arch)
+        return pkgmgr_instance(self, recording_pkgs, target_arch)
 
 class LoopImageCreator(ImageCreator):
     """Installs a system into a loopback-mountable filesystem image.
diff --git a/mic/imgcreate/pkgmanagers/__init__.py 
b/mic/imgcreate/pkgmanagers/__init__.py
index 4114403..d5f461e 100644
--- a/mic/imgcreate/pkgmanagers/__init__.py
+++ b/mic/imgcreate/pkgmanagers/__init__.py
@@ -46,6 +46,6 @@ class pkgManager:
                     exec("pkgmgr = %s._pkgmgr" % pkgmgrmod)
                     self.register_pkg_manager(pkgmgr[0], pkgmgr[1])
                 except:
-                    raise
+                    continue
         if not self.managers.keys():
             raise CreatorError("No packag manager available")
diff --git a/mic/imgcreate/pkgmanagers/yumpkgmgr.py 
b/mic/imgcreate/pkgmanagers/yumpkgmgr.py
index b19be72..2855606 100644
--- a/mic/imgcreate/pkgmanagers/yumpkgmgr.py
+++ b/mic/imgcreate/pkgmanagers/yumpkgmgr.py
@@ -33,9 +33,12 @@ import subprocess
 
 from mic.imgcreate.errors import *
 from mic.imgcreate.fs import *
+from mic.imgcreate.creator import ImageCreator
 
 class Yum(yum.YumBase):
-    def __init__(self, recording_pkgs=None, target_arch = None):
+    def __init__(self, creator, recording_pkgs=None, target_arch = None):
+        if not isinstance(creator, ImageCreator):
+            raise CreatorError("Invalid argument: creator")
         yum.YumBase.__init__(self)
         if target_arch:
             if rpmUtils.arch.arches.has_key(target_arch):
@@ -45,6 +48,7 @@ class Yum(yum.YumBase):
 
         self.__recording_pkgs = recording_pkgs
         self.__pkgs_content = {}
+        self.creator = creator
 
     def doFileLogSetup(self, uid, logfile):
         # don't do the file log for the livecd as it can lead to open fds
diff --git a/mic/imgcreate/pkgmanagers/zypperpkgmgr.py 
b/mic/imgcreate/pkgmanagers/zypperpkgmgr.py
index 567ff8a..f3e2002 100644
--- a/mic/imgcreate/pkgmanagers/zypperpkgmgr.py
+++ b/mic/imgcreate/pkgmanagers/zypperpkgmgr.py
@@ -1,7 +1,568 @@
 #!/usr/bin/python
 
+import os
+import sys
+import glob
+import re
+import zypp
+import rpm
+import shutil
+import tempfile
+import urlparse
+import urllib2 as u2
+from mic.imgcreate.errors import *
+from mic.imgcreate.creator import ImageCreator
+import pykickstart.parser
+from mic.imgcreate.fs import *
+from mic.imgcreate.misc import *
+from mic.imgcreate.rpmmisc import *
+
+class RepositoryStub:
+    def __init__(self):
+        self.name = None
+        self.baseurl = []
+        self.mirrorlist = None
+        self.proxy = None
+        self.proxy_username = None
+        self.proxy_password = None
+        self.includepkgs = None
+        self.includepkgs = None
+        self.exclude = None
+
+        self.enabled = True
+        self.autorefresh = True
+        self.keeppackages = True
+
+class RepoError(CreatorError):
+    pass
+
+class RpmError(CreatorError):
+    pass
+
 class Zypper:
-    def __init__(self, recording_pkgs=None, target_arch = None):
+    def __init__(self, creator, recording_pkgs=None, target_arch = None):
+        if not isinstance(creator, ImageCreator):
+            raise CreatorError("Invalid argument: creator")
+
+        self.__recording_pkgs = recording_pkgs
+        self.__pkgs_content = {}
+        self.creator = creator
+        self.repos = []
+        self.packages = []
+        self.patterns = []
+        self.localpkgs = {}
+        self.repo_manager = None
+        self.repo_manager_options = None
+        self.Z = None
+        self.ts = None
+
+    def doFileLogSetup(self, uid, logfile):
+        # don't do the file log for the livecd as it can lead to open fds
+        # being left and an inability to clean up after ourself
         pass
 
+    def closeRpmDB(self):
+        pass
+
+    def close(self):
+        try:
+            os.unlink(self.installroot + "/yum.conf")
+        except:
+            pass
+        self.closeRpmDB()
+        if not os.path.exists("/etc/fedora-release") and not 
os.path.exists("/etc/meego-release"):
+            for i in range(3, os.sysconf("SC_OPEN_MAX")):
+                try:
+                    os.close(i)
+                except:
+                    pass
+
+    def __del__(self):
+        pass
+
+    def _writeConf(self, confpath, installroot):
+        conf  = "[main]\n"
+        conf += "installroot=%s\n" % installroot
+        conf += "cachedir=/var/cache/yum\n"
+        conf += "plugins=0\n"
+        conf += "reposdir=\n"
+        conf += "failovermethod=priority\n"
+        conf += "http_caching=packages\n"
+
+        f = file(confpath, "w+")
+        f.write(conf)
+        f.close()
+
+        os.chmod(confpath, 0644)
+
+    def _cleanupRpmdbLocks(self, installroot):
+        # cleans up temporary files left by bdb so that differing
+        # versions of rpm don't cause problems
+        for f in glob.glob(installroot + "/var/lib/rpm/__db*"):
+            os.unlink(f)
+
+    def setup(self, confpath, installroot):
+        self._writeConf(confpath, installroot)
+        self._cleanupRpmdbLocks(installroot)
+        self.installroot = installroot
+
+    def selectPackage(self, pkg):
+        """Select a given package.  Can be specified with name.arch or name*"""
+        if not self.Z:
+            self.__initialize_zypp()
+
+        found = False
+        for item in self.Z.pool():
+            kind = "%s" % item.kind()
+            if kind == "package":
+                name = "%s" % item.name()
+                if name == pkg:
+                    found = True
+                    if name not in self.packages:
+                        self.packages.append(name)
+                        item.status().setToBeInstalled (zypp.ResStatus.USER)
+
+        if found:
+            return None
+        else:
+            raise CreatorError("Unable to find package: %s" % (pkg,))
+
+    def deselectPackage(self, pkg):
+        if not self.Z:
+            self.__initialize_zypp()
+
+        """Deselect package.  Can be specified as name.arch or name*"""
+        sp = pkg.rsplit(".", 2)
+        found = False
+        for item in self.Z.pool():
+            kind = "%s" % item.kind()
+            if kind == "package":
+                name = "%s" % item.name()
+                if name == sp[0]:
+                    found = True
+                    if  item.status().isInstalled():
+                        item.status().setToBeUninstalled (zypp.ResStatus.USER)
+                    if name in self.packages:
+                        self.packages.remove(name)
+        
+
+    def selectGroup(self, grp, include = pykickstart.parser.GROUP_DEFAULT):
+        if not self.Z:
+            self.__initialize_zypp()
+        found = False
+        for item in self.Z.pool():
+            kind = "%s" % item.kind()
+            if kind == "pattern":
+                summary = "%s" % item.summary()
+                name = "%s" % item.name()
+                if name == grp.name or summary == grp.name:
+                    found = True
+                    if name not in self.patterns:
+                        self.patterns.append(name)
+                        item.status().setToBeInstalled (zypp.ResStatus.USER)
+        if found:
+            if include == pykickstart.parser.GROUP_REQUIRED:
+                map(lambda p: self.deselectPackage(p), 
grp.default_packages.keys())
+            elif include == pykickstart.parser.GROUP_ALL:
+                map(lambda p: self.selectPackage(p), 
grp.optional_packages.keys())
+            return None
+        else:
+            raise CreatorError("Unable to find pattern: %s" % (grp.name,))
+
+    def __checkAndDownloadURL(self, u2opener, url, savepath):
+        try:
+            if u2opener:
+                f = u2opener.open(url)
+            else:
+                f = u2.urlopen(url)
+        except u2.HTTPError, httperror:
+            if httperror.code in (404, 503):
+                return None
+            else:
+                raise CreatorError(httperror)
+        except OSError, oserr:
+            if oserr.errno == 2:
+                return None
+            else:
+                raise CreatorError(oserr)
+        except IOError, oserr:
+            if hasattr(oserr, "reason") and oserr.reason.errno == 2:
+                return None
+            else:
+                raise CreatorError(oserr)
+        except u2.URLError, err:
+            raise CreatorError(err)
+
+        # save to file
+        licf = open(savepath, "w")
+        licf.write(f.read())
+        licf.close()
+        f.close()
+
+        return savepath
+
+    def __pagerFile(self, savepath):
+        if os.path.splitext(savepath)[1].upper() in ('.HTM', '.HTML'):
+            pagers = ('w3m', 'links', 'lynx', 'less', 'more')
+        else:
+            pagers = ('less', 'more')
+
+        file_showed = None
+        for pager in pagers:
+            try:
+                subprocess.call([pager, savepath])
+            except OSError:
+                continue
+            else:
+                file_showed = True
+                break
+        if not file_showed:
+            f = open(savepath)
+            print f.read()
+            f.close()
+            raw_input('press <ENTER> to continue...')
+
+    def checkRepositoryEULA(self, name, repo):
+        """ This function is to check the LICENSE file if provided. """
+
+        # when proxy needed, make urllib2 follow it
+        proxy = repo.proxy
+        proxy_username = repo.proxy_username
+        proxy_password = repo.proxy_password
+
+        handlers = []
+        auth_handler = 
u2.HTTPBasicAuthHandler(u2.HTTPPasswordMgrWithDefaultRealm())
+        u2opener = None
+        if proxy:
+            if proxy_username:
+                proxy_netloc = urlparse.urlsplit(proxy).netloc
+                if proxy_password:
+                    proxy_url = 'http://%s:%...@%s' % (proxy_username, 
proxy_password, proxy_netloc)
+                else:
+                    proxy_url = 'http://%...@%s' % (proxy_username, 
proxy_netloc)
+            else:
+                proxy_url = proxy
+
+            proxy_support = u2.ProxyHandler({'http': proxy_url,
+                                             'ftp': proxy_url})
+            handlers.append(proxy_support)
+
+        # download all remote files to one temp dir
+        baseurl = None
+        repo_lic_dir = tempfile.mkdtemp(prefix = 'repolic')
+
+        for url in repo.baseurl:
+            if not url.endswith('/'):
+                url += '/'
+            tmphandlers = handlers
+            (scheme, host, path, parm, query, frag) = urlparse.urlparse(url)
+            if scheme not in ("http", "https", "ftp", "ftps", "file"):
+                raise CreateError("Error: invalid url %s" % url)
+            if '@' in host:
+                try:
+                    user_pass, host = host.split('@', 1)
+                    if ':' in user_pass:
+                        user, password = user_pass.split(':', 1)
+                except ValueError, e:
+                    raise CreateError('Bad URL: %s' % url)
+                print "adding HTTP auth: %s, %s" %(user, password)
+                auth_handler.add_password(None, host, user, password)
+                tmphandlers.append(auth_handler)
+                url = scheme + "://" + host + path + parm + query + frag
+            if len(tmphandlers) != 0:
+                u2opener = u2.build_opener(*tmphandlers)
+            # try to download
+            repo_eula_url = urlparse.urljoin(url, "LICENSE.txt")
+            repo_eula_path = self.__checkAndDownloadURL(
+                                    u2opener,
+                                    repo_eula_url,
+                                    os.path.join(repo_lic_dir, repo.id + 
'_LICENSE.txt'))
+            if repo_eula_path:
+                # found
+                baseurl = url
+                break
+
+        if not baseurl:
+            return True
+
+        # show the license file
+        print 'For the software packages in this yum repo:'
+        print '    %s: %s' % (name, baseurl)
+        print 'There is an "End User License Agreement" file that need to be 
checked.'
+        print 'Please read the terms and conditions outlined in it and answer 
the followed qustions.'
+        raw_input('press <ENTER> to continue...')
+
+        self.__pagerFile(repo_eula_path)
+
+        # Asking for the "Accept/Decline"
+        accept = True
+        while accept:
+            input_accept = raw_input('Would you agree to the terms and 
conditions outlined in the above End User License Agreement? (Yes/No): ')
+            if input_accept.upper() in ('YES', 'Y'):
+                break
+            elif input_accept.upper() in ('NO', 'N'):
+                accept = None
+                print 'Will not install pkgs from this repo.'
+
+        if not accept:
+            #cleanup
+            shutil.rmtree(repo_lic_dir)
+            return None
+
+        # try to find support_info.html for extra infomation
+        repo_info_url = urlparse.urljoin(baseurl, "support_info.html")
+        repo_info_path = self.__checkAndDownloadURL(
+                                u2opener,
+                                repo_info_url,
+                                os.path.join(repo_lic_dir, repo.id + 
'_support_info.html'))
+        if repo_info_path:
+            print 'There is one more file in the repo for additional support 
information, please read it'
+            raw_input('press <ENTER> to continue...')
+            self.__pagerFile(repo_info_path)
+
+        #cleanup
+        shutil.rmtree(repo_lic_dir)
+        return True
+
+    def addRepository(self, name, url = None, mirrorlist = None, proxy = None, 
proxy_username = None, proxy_password = None):
+        if not self.repo_manager:
+            self.__initialize_repo_manager()
+
+        repo = RepositoryStub()
+        repo.name = name
+        repo.id = name
+        repo.proxy = proxy
+        repo.proxy_username = proxy_username
+        repo.proxy_password = proxy_password
+        repo.baseurl.append(url)
+
+        # check LICENSE files
+        if not self.checkRepositoryEULA(name, repo):
+            return None
+
+        if mirrorlist:
+            repo.mirrorlist = mirrorlist
+
+        # Enable gpg check for verifying corrupt packages
+        repo.gpgcheck = 1
+        self.repos.append(repo)
+
+
+        repo_info = zypp.RepoInfo()
+        repo_info.setAlias(repo.id)
+        repo_info.setName(repo.name)
+        repo_info.setEnabled(repo.enabled)
+        repo_info.setAutorefresh(repo.autorefresh)
+        repo_info.setKeepPackages(repo.keeppackages)
+        repo_info.addBaseUrl(zypp.Url(repo.baseurl[0]))
+        self.repo_manager.addRepository(repo_info)
+        self.__build_repo_cache(name)
+
+        return repo
+
+    def installHasFile(self, file):
+        return False
+
+    def runInstall(self, checksize = 0):
+        os.environ["HOME"] = "/"
+        self.buildTransaction()
+
+        todo = zypp.GetResolvablesToInsDel(self.Z.pool())
+        installed_pkgs = todo._toInstall
+        dlpkgs = []
+        print "\n\nThese packages will be installed:"
+        for item in installed_pkgs:
+            if not zypp.isKindPattern(item):
+                dlpkgs.append(item)
+                print "%s" % item.name()
+
+        # record the total size of installed pkgs
+        pkgs_total_size = sum(map(lambda x: int(x.installSize()), dlpkgs))
+
+        # check needed size before actually download and install
+        if checksize and pkgs_total_size > checksize:
+            raise CreatorError("Size of specified root partition in kickstart 
file is too small to install all selected packages.")
+
+        if self.__recording_pkgs:
+            # record all pkg and the content
+            for pkg in dlpkgs:
+                pkg_long_name = "%s.%s %s" % (pkg.name(), pkg.arch(), 
pkg.edition())
+                self.__pkgs_content[pkg_long_name] = {} #TBD: to get file list
+
+        total_count = len(dlpkgs)
+        cached_count = 0
+        localpkgs = self.localpkgs.keys()
+        for po in dlpkgs:
+            """ Check if it is cached locally """
+            if po.name() in localpkgs:
+                cached_count += 1
+            else:
+                local = self.getLocalPkgPath(po)
+                if os.path.exists(local):
+                    cached_count += 1
+        print "%d packages to be installed, %d packages gotten from cache, %d 
packages to be downloaded" % (total_count, cached_count, total_count - 
cached_count)
+        try:
+            self.downloadPkgs(dlpkgs)
+            self.installPkgs(dlpkgs)
+    
+        except RepoError, e:
+            raise CreatorError("Unable to download from repo : %s" % (e,))
+        except RpmError, e:
+            raise CreatorError("Unable to install: %s" % (e,))
+
+    def getAllContent(self):
+        return self.__pkgs_content
+
+    def __initialize_repo_manager(self):
+        if self.repo_manager:
+            return
+
+        """ Clean up repo metadata """
+        shutil.rmtree(self.creator.cachedir + "/var", ignore_errors = True)
+        shutil.rmtree(self.creator.cachedir + "/etc", ignore_errors = True)
+        shutil.rmtree(self.creator.cachedir + "/raw", ignore_errors = True)
+        shutil.rmtree(self.creator.cachedir + "/solv", ignore_errors = True)
+        
+        zypp.KeyRing.setDefaultAccept( zypp.KeyRing.ACCEPT_UNSIGNED_FILE
+                                       | 
zypp.KeyRing.ACCEPT_VERIFICATION_FAILED
+                                       | zypp.KeyRing.ACCEPT_UNKNOWNKEY
+                                       | zypp.KeyRing.TRUST_KEY_TEMPORARILY
+                                     )
+        self.repo_manager_options = 
zypp.RepoManagerOptions(zypp.Pathname(self.creator._instroot))
+        self.repo_manager_options.knownReposPath = 
zypp.Pathname(self.creator.cachedir + "/etc/zypp/repos.d")
+        self.repo_manager_options.repoCachePath = 
zypp.Pathname(self.creator.cachedir + "/var/cache/zypp")
+        self.repo_manager_options.repoRawCachePath = 
zypp.Pathname(self.creator.cachedir + "/raw")
+        self.repo_manager_options.repoSolvCachePath = 
zypp.Pathname(self.creator.cachedir + "/solv")
+        self.repo_manager_options.repoPackagesCachePath = 
zypp.Pathname(self.creator.cachedir + "/packages")
+        
+        self.repo_manager = zypp.RepoManager(self.repo_manager_options)
+
+
+    def __build_repo_cache(self, name):
+        repos = self.repo_manager.knownRepositories()
+        for repo in repos:
+            if not repo.enabled():
+                continue
+            reponame = "%s" % repo.name()
+            if reponame != name:
+                continue
+            if self.repo_manager.isCached( repo ):
+                return
+            print "Retrieving repo metedata from %s ..." % repo.url()
+            self.repo_manager.buildCache( repo, zypp.RepoManager.BuildIfNeeded 
)
+
+
+    def __initialize_zypp(self):
+        if self.Z:
+            return
+
+        """ repoPackagesCachePath is corrected by this """
+        self.repo_manager = zypp.RepoManager(self.repo_manager_options)
+        repos = self.repo_manager.knownRepositories()
+        for repo in repos:
+            if not repo.enabled():
+                continue
+            if not self.repo_manager.isCached( repo ):
+                print "Retrieving repo metedata from %s ..." % repo.url()
+                self.repo_manager.buildCache( repo, 
zypp.RepoManager.BuildIfNeeded )
+            else:
+                self.repo_manager.refreshMetadata(repo, 
zypp.RepoManager.BuildIfNeeded)
+            self.repo_manager.loadFromCache( repo );
+
+        self.Z = zypp.ZYppFactory_instance().getZYpp()
+        self.Z.initializeTarget( zypp.Pathname(self.creator._instroot) )
+        self.Z.target().load();
+
+
+    def buildTransaction(self):
+        print self.packages
+        print self.patterns
+        if not self.Z.resolver().resolvePool():
+            print self.Z.resolver().problems()
+            #print "Problem count: %d" % len(self.Z.resolver().problems())
+            for problem in self.Z.resolver().problems():
+                print "%s" % problem
+            #raise CreatorError("Solver Error")
+            pass
+
+    def getLocalPkgPath(self, po):
+        repoinfo = po.repoInfo()
+        name = po.name()
+        cacheroot = repoinfo.packagesPath()
+        arch =  po.arch()
+        version = po.edition()
+        pkgpath = "%s/%s/%s-%s.%s.rpm" % (cacheroot, arch, name, version, arch)
+        return pkgpath
+
+    def installLocal(self, pkg, po=None, updateonly=False):
+        if not self.ts:
+            self.__initialize_transaction()
+        pkgname = self.__get_pkg_name(pkg)
+        self.localpkgs[pkgname] = pkg
+        self.selectPackage(pkgname)
+
+    def __get_pkg_name(self, pkgpath):
+        h = readRpmHeader(self.ts, pkgpath)
+        return h["name"]
+
+    def downloadPkgs(self, package_objects):
+        localpkgs = self.localpkgs.keys()
+        for po in package_objects:
+            if po.name() in localpkgs:
+                continue
+            filename = self.getLocalPkgPath(po)
+            if os.path.exists(filename):
+                continue
+            dir = os.path.dirname(filename)
+            if not os.path.exists(dir):
+                makedirs(dir)
+            baseurl = "%s" % po.repoInfo().baseUrls()[0]
+            proxy = get_proxy(baseurl)
+            proxies = {}
+            if proxy:
+                proxies = {str(proxy.split(":")[0]):str(proxy)}
+            
+            url = baseurl + "/%s/%s" % (po.arch(), os.path.basename(filename))
+            filename = myurlgrab(url, filename, proxies)
+
+    def installPkgs(self, package_objects):
+        if not self.ts:
+            self.__initialize_transaction()
+        localpkgs = self.localpkgs.keys()
+        for po in package_objects:
+            pkgname = po.name()
+            if pkgname in localpkgs:
+                rpmpath = self.localpkgs[pkgname]
+            else:
+                rpmpath = self.getLocalPkgPath(po)
+            if not os.path.exists(rpmpath):
+                raise RpmError("Error: %s doesn't exist" % rpmpath)
+            h = readRpmHeader(self.ts, rpmpath)
+            self.ts.addInstall(h, rpmpath, 'u')
+
+        unresolved_dependencies = self.ts.check()
+        if not unresolved_dependencies:
+            self.ts.order()
+            cb = RPMInstallCallback(self.ts)
+            self.ts.run(cb.callback, '')
+            self.ts.closeDB()
+        else:
+            print unresolved_dependencies
+            raise RepoError("Error: Unresolved dependencies, transaction 
failed.")
+
+    def __initialize_transaction(self):
+        if not self.ts:
+            self.ts = rpm.TransactionSet(self.creator._instroot)
+            # Set to not verify DSA signatures.
+            self.ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
+
+    def zypp_install(self):
+        policy = zypp.ZYppCommitPolicy()
+        policy.downloadMode(zypp.DownloadInAdvance)
+        policy.dryRun( False )
+        policy.syncPoolAfterCommit( False )
+        result = self.Z.commit( policy )
+        print result
+
 _pkgmgr = ["zypper", Zypper]
+
diff --git a/mic/imgcreate/rpmmisc.py b/mic/imgcreate/rpmmisc.py
new file mode 100644
index 0000000..a1fe7e6
--- /dev/null
+++ b/mic/imgcreate/rpmmisc.py
@@ -0,0 +1,146 @@
+import rpm, os, sys, re
+
+class RPMInstallCallback:
+    """
+    command line callback class for callbacks from the RPM library.
+    """
+
+    def __init__(self, ts, output=1):
+        self.output = output
+        self.callbackfilehandles = {}
+        self.total_actions = 0
+        self.total_installed = 0
+        self.installed_pkg_names = []
+        self.total_removed = 0
+        self.mark = "#"
+        self.marks = 27
+        self.lastmsg = None
+        self.tsInfo = None # this needs to be set for anything else to work
+        self.ts = ts
+
+    def _dopkgtup(self, hdr):
+        tmpepoch = hdr['epoch']
+        if tmpepoch is None: epoch = '0'
+        else: epoch = str(tmpepoch)
+
+        return (hdr['name'], hdr['arch'], epoch, hdr['version'], 
hdr['release'])
+
+    def _makeHandle(self, hdr):
+        handle = '%s:%s.%s-%s-%s' % (hdr['epoch'], hdr['name'], hdr['version'],
+          hdr['release'], hdr['arch'])
+
+        return handle
+
+    def _localprint(self, msg):
+        if self.output:
+            print msg
+
+    def _makefmt(self, percent, progress = True):
+        l = len(str(self.total_actions))
+        size = "%s.%s" % (l, l)
+        fmt_done = "[%" + size + "s/%" + size + "s]"
+        done = fmt_done % (self.total_installed + self.total_removed,
+                           self.total_actions)
+        marks = self.marks - (2 * l)
+        width = "%s.%s" % (marks, marks)
+        fmt_bar = "%-" + width + "s"
+        if progress:
+            bar = fmt_bar % (self.mark * int(marks * (percent / 100.0)), )
+            fmt = "\r  %-10.10s: %-28.28s " + bar + " " + done
+        else:
+            bar = fmt_bar % (self.mark * marks, )
+            fmt = "  %-10.10s: %-28.28s "  + bar + " " + done
+        return fmt
+
+    def _logPkgString(self, hdr):
+        """return nice representation of the package for the log"""
+        (n,a,e,v,r) = self._dopkgtup(hdr)
+        if e == '0':
+            pkg = '%s.%s %s-%s' % (n, a, v, r)
+        else:
+            pkg = '%s.%s %s:%s-%s' % (n, a, e, v, r)
+
+        return pkg
+
+    def callback(self, what, bytes, total, h, user):
+        if what == rpm.RPMCALLBACK_TRANS_START:
+            if bytes == 6:
+                self.total_actions = total
+
+        elif what == rpm.RPMCALLBACK_TRANS_PROGRESS:
+            pass
+
+        elif what == rpm.RPMCALLBACK_TRANS_STOP:
+            pass
+
+        elif what == rpm.RPMCALLBACK_INST_OPEN_FILE:
+            self.lastmsg = None
+            hdr = None
+            if h is not None:
+                rpmloc = h
+                hdr = readRpmHeader(self.ts, h)
+                handle = self._makeHandle(hdr)
+                fd = os.open(rpmloc, os.O_RDONLY)
+                self.callbackfilehandles[handle]=fd
+                self.total_installed += 1
+                self.installed_pkg_names.append(hdr['name'])
+                return fd
+            else:
+                self._localprint("No header - huh?")
+
+        elif what == rpm.RPMCALLBACK_INST_CLOSE_FILE:
+            hdr = None
+            if h is not None:
+                rpmloc = h
+                hdr = readRpmHeader(self.ts, h)
+                handle = self._makeHandle(hdr)
+                os.close(self.callbackfilehandles[handle])
+                fd = 0
+
+                # log stuff
+                pkgtup = self._dopkgtup(hdr)
+                
+
+        elif what == rpm.RPMCALLBACK_INST_PROGRESS:
+            if h is not None:
+                if total == 0:
+                    percent = 0
+                else:
+                    percent = (bytes*100L)/total
+                    m = re.match("(.*)-(\d+.*)-(\d+\.\d+)\.(.+)\.rpm", 
os.path.basename(h))
+                    if m:
+                        pkgname = m.group(1)
+                    else:
+                        pkgname = os.path.basename(h)
+                if self.output and (sys.stdout.isatty() or bytes == total):
+                    fmt = self._makefmt(percent)
+                    msg = fmt % ("Installing", pkgname)
+                    if msg != self.lastmsg:
+                        sys.stdout.write(msg)
+                        sys.stdout.flush()
+                        self.lastmsg = msg
+                        if bytes == total:
+                            print " "
+
+        elif what == rpm.RPMCALLBACK_UNINST_START:
+            pass
+
+        elif what == rpm.RPMCALLBACK_UNINST_PROGRESS:
+            pass
+
+        elif what == rpm.RPMCALLBACK_UNINST_STOP:
+            self.total_removed += 1
+            
+        elif what == rpm.RPMCALLBACK_REPACKAGE_START:
+            pass
+        elif what == rpm.RPMCALLBACK_REPACKAGE_STOP:
+            pass
+        elif what == rpm.RPMCALLBACK_REPACKAGE_PROGRESS:
+            pass
+
+def readRpmHeader(ts, filename):
+    """ Read an rpm header. """
+    fd = os.open(filename, os.O_RDONLY)
+    h = ts.hdrFromFdno(fd)
+    os.close(fd)
+    return h
_______________________________________________
MeeGo-dev mailing list
[email protected]
http://lists.meego.com/listinfo/meego-dev

Reply via email to