Uninstall the packages before update while re-creating image.
authorwanchao-xu <wanchao.xu@samsung.com>
Fri, 16 Aug 2024 12:22:30 +0000 (20:22 +0800)
committerwanchao-xu <wanchao.xu@samsung.com>
Tue, 27 Aug 2024 05:24:25 +0000 (13:24 +0800)
  - Support the uninstall packages for zypppkgmgr.
  - Support to get all packages which depended on updated packages.

Change-Id: I5e3026c83cf7b3cae98aa3cc60115923bc096918
Signed-off-by: wanchao-xu <wanchao.xu@samsung.com>
mic/imager/baseimager.py
mic/utils/rpmmisc.py
plugins/backend/zypppkgmgr.py

index 67007783132a01c6a4c27f3f8dc0f5823b8e4c54..2c539cee9198c16e6cc0d45aac640fb4236e3047 100644 (file)
@@ -1149,7 +1149,9 @@ class BaseImageCreator(object):
 
         try:
             if self.reuse_environment and updated_pkgs != None:
+                self.__preinstall_packages(pkg_manager)
                 self.__update_packages(pkg_manager, updated_pkgs)
+                self.__deselect_packages(pkg_manager)
             else:
                 self.__preinstall_packages(pkg_manager)
                 self.__select_packages(pkg_manager)
index 3dde377049a81b31e1d5fc86195d5edf39d36430..a5fca96be8d3ee3bf77407cb4c8ba6c41125380c 100644 (file)
@@ -25,7 +25,6 @@ from mic.utils.errors import CreatorError
 from mic.utils.proxy import get_proxy_for
 from mic.utils import runner
 
-
 class RPMInstallCallback:
     """ Command line callback class for callbacks from the RPM library.
     """
@@ -38,6 +37,7 @@ class RPMInstallCallback:
         self.total_installing = 0
         self.installed_pkg_names = []
         self.total_removed = 0
+        self.total_removing = 0
         self.mark = "+"
         self.marks = 40
         self.lastmsg = None
@@ -45,7 +45,6 @@ class RPMInstallCallback:
         self.ts = ts
         self.filelog = False
         self.logString = []
-        self.headmsg = "Installing"
 
     def _dopkgtup(self, hdr):
         tmpepoch = hdr['epoch']
@@ -64,12 +63,11 @@ class RPMInstallCallback:
         if self.output:
             msger.info(msg)
 
-    def _makefmt(self, percent, progress = True):
+    def _makefmt(self, doing, 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_installing,
-                           self.total_actions)
+        done = fmt_done % (doing, self.total_actions)
         marks = self.marks - (2 * l)
         width = "%s.%s" % (marks, marks)
         fmt_bar = "%-" + width + "s"
@@ -149,7 +147,7 @@ class RPMInstallCallback:
         elif what == rpm.RPMCALLBACK_INST_START:
             self.total_installing += 1
 
-        elif what == rpm.RPMCALLBACK_UNINST_STOP:
+        elif what == rpm.RPMCALLBACK_INST_STOP:
             pass
 
         elif what == rpm.RPMCALLBACK_INST_PROGRESS:
@@ -167,8 +165,8 @@ class RPMInstallCallback:
                     else:
                         pkgname = os.path.basename(rpmloc)
                 if self.output:
-                    fmt = self._makefmt(percent)
-                    msg = fmt % (self.headmsg, pkgname)
+                    fmt = self._makefmt(self.total_installing, percent)
+                    msg = fmt % ("Installing", pkgname)
                     if msg != self.lastmsg:
                         self.lastmsg = msg
 
@@ -179,10 +177,33 @@ class RPMInstallCallback:
                             msger.verbose('\n'.join(self.logString))
 
         elif what == rpm.RPMCALLBACK_UNINST_START:
-            pass
+            self.total_removing += 1
 
         elif what == rpm.RPMCALLBACK_UNINST_PROGRESS:
-            pass
+            if h is not None:
+                percent = (self.total_removed*100)/self.total_actions
+                if total > 0:
+                    try:
+                        hdr, rpmloc = h
+                    except:
+                        rpmloc = h
+
+                    m = re.match(r"(.*)-(\d+.*)-(\d+\.\d+)\.(.+)\.rpm", os.path.basename(rpmloc))
+                    if m:
+                        pkgname = m.group(1)
+                    else:
+                        pkgname = os.path.basename(rpmloc)
+                if self.output:
+                    fmt = self._makefmt(self.total_removing, percent)
+                    msg = fmt % ("Uninstalling", pkgname)
+                    if msg != self.lastmsg:
+                        self.lastmsg = msg
+
+                        msger.info(msg)
+
+                        if self.total_installed == self.total_actions:
+                            msger.raw('')
+                            msger.verbose('\n'.join(self.logString))
 
         elif what == rpm.RPMCALLBACK_UNINST_STOP:
             self.total_removed += 1
index 2733493f1c10e6ebe44fc6fe63492892c4866ff5..ac64e05eeb7943f404d7acb6afa343f36ae1217d 100644 (file)
@@ -507,24 +507,9 @@ class Zypp(BackendPlugin):
             elif os.path.splitext(cropts['local_pkgs_path'])[-1] == '.rpm':
                 return [cropts['local_pkgs_path']]
         return []
-
     def __localinst_packages(self):
         for rpm_path in self._get_local_packages():
             self.installLocal(rpm_path)
-
-    def _getPackagesToReinstall(self):
-        to_install_pkgs = []
-        for pkg in self.update_pkgs:
-            to_install_pkgs.append(pkg)
-            isInstalled = pkg.status().isInstalled()
-            msger.info("Update package %s : installed = %s" % (pkg.name(), isInstalled))
-
-            for item in self.Z.pool():
-                if item.name() == pkg.name and item.kind() == pkg.kind():
-                    msger.info("package %s in pool : installed = %s" % (item.name(), item.status().isInstalled()))
-
-        return to_install_pkgs
-
     def runInstall(self, checksize = 0):
         if not self.Z:
             self.__initialize_zypp()
@@ -538,8 +523,10 @@ class Zypp(BackendPlugin):
         installed_pkgs = todo._toInstall
         dlpkgs = []
 
+        # re-create image with updating some packages
         if len(installed_pkgs) == 0:
-            installed_pkgs = self._getPackagesToReinstall()
+            self.deleteUpdatedPkgs()
+            installed_pkgs = self.update_pkgs
 
         for pitem in installed_pkgs:
             if not zypp.isKindPattern(pitem) and \
@@ -985,6 +972,77 @@ class Zypp(BackendPlugin):
             self.show_unresolved_dependencies_msg(unresolved_dependencies)
             raise RepoError("Unresolved dependencies, transaction failed.")
 
+    def deleteUpdatedPkgs(self):
+        if not self.update_pkgs:
+            return
+
+        if not self.ts:
+            self.__initialize_transaction()
+
+        # clean rpm lock
+        self._cleanupRpmdbLocks(self.instroot)
+        self._cleanupZyppJunk(self.instroot)
+        # Set filters
+        probfilter = 0
+        for flag in self.probFilterFlags:
+            probfilter |= flag
+        self.ts.setProbFilter(probfilter)
+
+        to_delete = []
+        for po in self.update_pkgs:
+            self.ts.addErase(po.name())
+            to_delete.append(po.name())
+        self.ts.order()
+
+        unresolved_dependencies = self.ts.check()
+        while unresolved_dependencies:
+            self.ts.clean()
+            check = False
+            for pkg, need, needflags, sense, key in unresolved_dependencies:
+                (name, version, release) = pkg
+                if sense == rpm.RPMDEP_SENSE_REQUIRES and name not in to_delete:
+                    self.ts.addErase(name)
+                    to_delete.append(name)
+                    check = True
+
+            if check:
+                self.ts.order()
+                unresolved_dependencies = self.ts.check()
+            else:
+                self.show_unresolved_dependencies_msg(unresolved_dependencies)
+                raise RepoError("Unresolved dependencies, transaction failed.")
+
+        cb = rpmmisc.RPMInstallCallback(self.ts)
+        logfile = "%s/__catched_stderr.buf" % (self.instroot)
+
+        # start to catch stderr output from librpm
+        msger.enable_logstderr(logfile)
+
+        errors = self.ts.run(cb.callback, '')
+        # stop catch
+        msger.disable_logstderr()
+        self.ts.closeDB()
+        self.ts = None
+
+        if errors is not None:
+            if len(errors) == 0:
+                msger.warning('scriptlet or other non-fatal errors occurred '
+                              'during transaction.')
+                if self.strict_mode:
+                    raise CreatorError("mic failes to uninstall some packages")
+            else:
+                for e in errors:
+                    msger.warning(e[0])
+                raise RepoError('Could not run transaction.')
+
+        self.update_pkgs.clear()
+        for item in to_delete:
+            pkg = self._zyppQueryPackage(item)
+            if pkg:
+                self.update_pkgs.append(pkg)
+            else:
+                msger.warning("No updated rpm found for: %s" % item)
+
     def __initialize_transaction(self):
         if not self.ts:
             self.ts = rpm.TransactionSet(self.instroot)