[devel] [PATCH for apt] Implemented generic callback system for package manager transactions

Oleg Solovyov mcpain на altlinux.org
Пт Дек 6 16:12:01 MSK 2019


---
 apt/apt-pkg/packagemanager.cc |   4 +-
 apt/apt-pkg/packagemanager.h  |  30 +++++++-
 apt/apt-pkg/rpm/rpmpm.cc      | 137 ++++++++++++++++++++++++++++++++--
 apt/apt-pkg/rpm/rpmpm.h       |  16 ++--
 4 files changed, 170 insertions(+), 17 deletions(-)

diff --git a/apt/apt-pkg/packagemanager.cc b/apt/apt-pkg/packagemanager.cc
index 0bcd902..f5adbfd 100644
--- a/apt/apt-pkg/packagemanager.cc
+++ b/apt/apt-pkg/packagemanager.cc
@@ -665,11 +665,11 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
 // ---------------------------------------------------------------------
 /* This uses the filenames in FileNames and the information in the
    DepCache to perform the installation of packages.*/
-pkgPackageManager::OrderResult pkgPackageManager::DoInstall()
+pkgPackageManager::OrderResult pkgPackageManager::DoInstall(PackageManagerCallback_t callback, void *callbackData)
 {
    OrderResult Res = OrderInstall();
    if (Res != Failed)
-      if (Go() == false)
+      if (Go(callback, callbackData) == false)
 	 return Failed;
    return Res;
 }
diff --git a/apt/apt-pkg/packagemanager.h b/apt/apt-pkg/packagemanager.h
index 917dbc1..e60ba51 100644
--- a/apt/apt-pkg/packagemanager.h
+++ b/apt/apt-pkg/packagemanager.h
@@ -49,6 +49,32 @@ class pkgDepCache;
 class pkgSourceList;
 class pkgOrderList;
 class pkgRecords;
+
+typedef enum aptCallbackType_e {
+    APTCALLBACK_UNKNOWN = 0,
+    APTCALLBACK_INST_PROGRESS,
+    APTCALLBACK_INST_START,
+    APTCALLBACK_INST_STOP,
+    APTCALLBACK_TRANS_PROGRESS,
+    APTCALLBACK_TRANS_START,
+    APTCALLBACK_TRANS_STOP,
+    APTCALLBACK_UNINST_PROGRESS,
+    APTCALLBACK_UNINST_START,
+    APTCALLBACK_UNINST_STOP,
+    APTCALLBACK_UNPACK_ERROR,
+    APTCALLBACK_CPIO_ERROR,
+    APTCALLBACK_SCRIPT_ERROR,
+    APTCALLBACK_SCRIPT_START,
+    APTCALLBACK_SCRIPT_STOP,
+    APTCALLBACK_ELEM_PROGRESS,
+} aptCallbackType;
+
+typedef void (*PackageManagerCallback_t)(const char *nevra,
+                                         const aptCallbackType what,
+                                         const uint64_t amount,
+                                         const uint64_t total,
+                                         void *callbackData);
+
 class pkgPackageManager : protected pkgCache::Namespace
 {
    public:
@@ -80,7 +106,7 @@ class pkgPackageManager : protected pkgCache::Namespace
    virtual bool Install(PkgIterator /*Pkg*/,const string &/*File*/) {return false;};
    virtual bool Configure(PkgIterator /*Pkg*/) {return false;};
    virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
-   virtual bool Go() {return true;};
+   virtual bool Go(PackageManagerCallback_t /*callback*/ = nullptr, void * /*callbackData*/ = nullptr) {return true;};
    virtual void Reset() {};
    
    public:
@@ -88,7 +114,7 @@ class pkgPackageManager : protected pkgCache::Namespace
    // Main action members
    bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
 		    pkgRecords *Recs);
-   OrderResult DoInstall();
+   OrderResult DoInstall(PackageManagerCallback_t callback = nullptr, void *callbackData = nullptr);
    bool FixMissing();
    
    // If marks updating not supported, skip this step
diff --git a/apt/apt-pkg/rpm/rpmpm.cc b/apt/apt-pkg/rpm/rpmpm.cc
index a6a3837..d5ff786 100644
--- a/apt/apt-pkg/rpm/rpmpm.cc
+++ b/apt/apt-pkg/rpm/rpmpm.cc
@@ -278,7 +278,7 @@ bool pkgRPMPM::RunScriptsWithPkgs(const char *Cnf)
 // RPMPM::Go - Run the sequence						/*{{{*/
 // ---------------------------------------------------------------------
 /* This globs the operations and calls rpm */
-bool pkgRPMPM::Go()
+bool pkgRPMPM::Go(PackageManagerCallback_t callback, void *callbackData)
 {
    if (List.empty() == true)
       return true;
@@ -364,7 +364,7 @@ bool pkgRPMPM::Go()
    }
 #endif
 
-   if (Process(install, upgrade, uninstall) == false)
+   if (Process(install, upgrade, uninstall, callback, callbackData) == false)
       Ret = false;
 
 #ifdef WITH_LUA
@@ -687,7 +687,8 @@ bool pkgRPMExtPM::ExecRPM(Item::RPMOps op, const std::vector<apt_item> &files)
 
 bool pkgRPMExtPM::Process(const std::vector<apt_item> &install,
 		       const std::vector<apt_item> &upgrade,
-		       const std::vector<apt_item> &uninstall)
+		       const std::vector<apt_item> &uninstall,
+		       PackageManagerCallback_t callback, void *callbackData)
 {
    if (uninstall.empty() == false)
        ExecRPM(Item::RPMErase, uninstall);
@@ -827,9 +828,108 @@ bool pkgRPMLibPM::AddToTransaction(Item::RPMOps op, const std::vector<apt_item>
    return true;
 }
 
+struct CallbackData
+{
+   PackageManagerCallback_t callback;
+   void *callbackData;
+};
+
+void * pkgRPMLibPM::customCallback(const void * h,
+                                   const rpmCallbackType what,
+                                   const uint64_t amount,
+                                   const uint64_t total,
+                                   const void * pkgKey,
+                                   void * data)
+{
+   /* When invoking rpmShowProgress, the last parameter is notifyFlags,
+      which ain't used when callback type is OPEN_FILE or CLOSE_FILE
+      so it's safe to just pass zero. */
+   if (what == RPMCALLBACK_INST_OPEN_FILE || what == RPMCALLBACK_INST_CLOSE_FILE)
+      return rpmShowProgress(h, what, amount, total, pkgKey, 0);
+
+   CallbackData *s = (CallbackData *) data;
+   PackageManagerCallback_t func = s->callback;
+   rpmtd td = nullptr;
+
+   const char* nevra = nullptr;
+   if (h != nullptr) {
+      td = rpmtdNew();
+
+      // Get NEVRA for package
+      int rc = headerGet((rpmHeader) h, RPMTAG_NEVRA, td, HEADERGET_DEFAULT);
+      if (rc == 1)
+         nevra = rpmtdGetString(td);
+   }
+
+   aptCallbackType callbackType = APTCALLBACK_UNKNOWN;
+   switch (what) {
+      case RPMCALLBACK_INST_PROGRESS:
+         callbackType = APTCALLBACK_INST_PROGRESS;
+         break;
+      case RPMCALLBACK_INST_START:
+         callbackType = APTCALLBACK_INST_START;
+         break;
+      case RPMCALLBACK_TRANS_PROGRESS:
+         callbackType = APTCALLBACK_TRANS_PROGRESS;
+         break;
+      case RPMCALLBACK_TRANS_START:
+         callbackType = APTCALLBACK_TRANS_START;
+         break;
+      case RPMCALLBACK_TRANS_STOP:
+         callbackType = APTCALLBACK_TRANS_STOP;
+         break;
+      case RPMCALLBACK_UNINST_PROGRESS:
+         callbackType = APTCALLBACK_UNINST_PROGRESS;
+         break;
+      case RPMCALLBACK_UNINST_START:
+         callbackType = APTCALLBACK_UNINST_START;
+         break;
+      case RPMCALLBACK_UNINST_STOP:
+         callbackType = APTCALLBACK_UNINST_STOP;
+         break;
+      case RPMCALLBACK_UNPACK_ERROR:
+         callbackType = APTCALLBACK_UNPACK_ERROR;
+         break;
+      case RPMCALLBACK_CPIO_ERROR:
+         callbackType = APTCALLBACK_CPIO_ERROR;
+         break;
+      case RPMCALLBACK_SCRIPT_ERROR:
+         callbackType = APTCALLBACK_SCRIPT_ERROR;
+         break;
+      case RPMCALLBACK_SCRIPT_START:
+         callbackType = APTCALLBACK_SCRIPT_START;
+         break;
+      case RPMCALLBACK_SCRIPT_STOP:
+         callbackType = APTCALLBACK_SCRIPT_STOP;
+         break;
+      case RPMCALLBACK_INST_STOP:
+         callbackType = APTCALLBACK_INST_STOP;
+         break;
+      case RPMCALLBACK_ELEM_PROGRESS:
+         callbackType = APTCALLBACK_ELEM_PROGRESS;
+         break;
+      default:
+         break;
+   }
+
+   try {
+      func(nevra, callbackType, amount, total, s->callbackData);
+   }
+   catch (...)
+   {
+   }
+
+   if (h != nullptr) {
+      rpmtdFreeData(td);
+      rpmtdFree(td);
+   }
+   return nullptr;
+}
+
 bool pkgRPMLibPM::Process(const std::vector<apt_item> &install,
 			  const std::vector<apt_item> &upgrade,
-			  const std::vector<apt_item> &uninstall)
+			  const std::vector<apt_item> &uninstall,
+			  PackageManagerCallback_t callback, void *callbackData)
 {
    int rc = 0;
    bool Success = false;
@@ -990,13 +1090,34 @@ bool pkgRPMLibPM::Process(const std::vector<apt_item> &install,
    probFilter |= rpmtsFilterFlags(TS);
    rpmtsSetFlags(TS, (rpmtransFlags)(rpmtsFlags(TS) | tsFlags));
    rpmtsClean(TS);
-   rc = rpmtsSetNotifyCallback(TS, rpmShowProgress, (void *)notifyFlags);
+
+   struct CallbackData data;
+
+   if (callback != nullptr ) {
+      data.callback = callback;
+      data.callbackData = callbackData;
+
+      rc = rpmtsSetNotifyCallback(TS, customCallback, &data);
+   } else {
+      rc = rpmtsSetNotifyCallback(TS, rpmShowProgress, (void *)notifyFlags);
+   }
+
    rc = rpmtsRun(TS, NULL, (rpmprobFilterFlags)probFilter);
    probs = rpmtsProblems(TS);
 #else
-   rc = rpmRunTransactions(TS, rpmShowProgress, (void *)notifyFlags, NULL,
-                           &probs, (rpmtransFlags)tsFlags,
-			   (rpmprobFilterFlags)probFilter);
+   if (callback != nullptr ) {
+      struct CallbackData data;
+      data.callback = callback;
+      data.callbackData = callbackData;
+
+      rc = rpmRunTransactions(TS, customCallback, &data, NULL,
+                              &probs, (rpmtransFlags)tsFlags,
+			      (rpmprobFilterFlags)probFilter);
+   } else {
+      rc = rpmRunTransactions(TS, rpmShowProgress, (void *)notifyFlags, NULL,
+                              &probs, (rpmtransFlags)tsFlags,
+			      (rpmprobFilterFlags)probFilter);
+   }
 #endif
 
    if (rc > 0) {
diff --git a/apt/apt-pkg/rpm/rpmpm.h b/apt/apt-pkg/rpm/rpmpm.h
index e6968b8..692b9a9 100644
--- a/apt/apt-pkg/rpm/rpmpm.h
+++ b/apt/apt-pkg/rpm/rpmpm.h
@@ -54,12 +54,13 @@ class pkgRPMPM : public pkgPackageManager
    virtual bool Install(PkgIterator Pkg,const string &File) override;
    virtual bool Configure(PkgIterator Pkg) override;
    virtual bool Remove(PkgIterator Pkg,bool Purge = false) override;
-    
+
    virtual bool Process(const std::vector<apt_item> &install,
 		const std::vector<apt_item> &upgrade,
-		const std::vector<apt_item> &uninstall) {return false;};
+		const std::vector<apt_item> &uninstall,
+		PackageManagerCallback_t callback, void *callbackData) {return false;};
    
-   virtual bool Go() override;
+   virtual bool Go(PackageManagerCallback_t callback, void *callbackData) override;
    virtual void Reset() override;
    
    public:
@@ -74,7 +75,8 @@ class pkgRPMExtPM : public pkgRPMPM
    bool ExecRPM(Item::RPMOps op, const std::vector<apt_item> &files);
    virtual bool Process(const std::vector<apt_item> &install,
 		const std::vector<apt_item> &upgrade,
-		const std::vector<apt_item> &uninstall) override;
+		const std::vector<apt_item> &uninstall,
+		PackageManagerCallback_t callback, void *callbackData) override;
 
    public:
    pkgRPMExtPM(pkgDepCache *Cache);
@@ -93,9 +95,13 @@ class pkgRPMLibPM : public pkgRPMPM
 
    bool ParseRpmOpts(const char *Cnf, int *tsFlags, int *probFilter);
    bool AddToTransaction(Item::RPMOps op, const std::vector<apt_item> &files);
+   static void * customCallback(const void * h, const rpmCallbackType what,
+				const uint64_t amount, const uint64_t total,
+				const void * pkgKey, void * data);
    virtual bool Process(const std::vector<apt_item> &install,
 		const std::vector<apt_item> &upgrade,
-		const std::vector<apt_item> &uninstall) override;
+		const std::vector<apt_item> &uninstall,
+		PackageManagerCallback_t callback, void *callbackData) override;
 
    public:
 
-- 
2.24.0



Подробная информация о списке рассылки Devel