ALT Linux Team development discussions
 help / color / mirror / Atom feed
* [devel] [PATCH for apt] Implemented generic callback system for package manager transactions
@ 2019-12-06 13:12 Oleg Solovyov
  2019-12-10  0:30 ` Dmitry V. Levin
  0 siblings, 1 reply; 7+ messages in thread
From: Oleg Solovyov @ 2019-12-06 13:12 UTC (permalink / raw)
  To: devel; +Cc: Oleg Solovyov

---
 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



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [devel] [PATCH for apt] Implemented generic callback system for package manager transactions
  2019-12-06 13:12 [devel] [PATCH for apt] Implemented generic callback system for package manager transactions Oleg Solovyov
@ 2019-12-10  0:30 ` Dmitry V. Levin
  2019-12-10  7:27   ` Oleg Solovyov
                     ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Dmitry V. Levin @ 2019-12-10  0:30 UTC (permalink / raw)
  To: Oleg Solovyov; +Cc: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 2444 bytes --]

On Fri, Dec 06, 2019 at 04:12:01PM +0300, Oleg Solovyov wrote:
> ---
>  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(-)

I agree the code should speak for itself, but it would be great
if you could shed some light on what's going on.

[...]
> +   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;
> +   }

This looks ugly.  Could we use the same values for corresponding
APTCALLBACK_* and RPMCALLBACK_* constants instead?


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [devel] [PATCH for apt] Implemented generic callback system for package manager transactions
  2019-12-10  0:30 ` Dmitry V. Levin
@ 2019-12-10  7:27   ` Oleg Solovyov
  2019-12-10 22:39     ` Dmitry V. Levin
  2019-12-10  7:37   ` Aleksei Nikiforov
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Oleg Solovyov @ 2019-12-10  7:27 UTC (permalink / raw)
  To: devel

[-- Attachment #1: Type: text/plain, Size: 1407 bytes --]

On вторник, 10 декабря 2019 г. 03:30:42 MSK Dmitry V. Levin wrote:
> On Fri, Dec 06, 2019 at 04:12:01PM +0300, Oleg Solovyov wrote:
> > ---
> > 
> >  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(-)
> 
> I agree the code should speak for itself, but it would be great
> if you could shed some light on what's going on.
We're introducing custom callback for higher layers (like packagekit), letting 
them pass their own callbacks to APT instead of using rpmShowProgress when 
it's necessary.
It's useful in particular case of offline updating when packagekit can send 
messages to plymouth letting user know about transaction progress but because 
APT does not send anything since it's using rpmShowProgress, packagekit 
reports nothing because it's just nothing to report.

> > [...]
> 
> This looks ugly.  Could we use the same values for corresponding
> APTCALLBACK_* and RPMCALLBACK_* constants instead?
They're passed to packagekit.
I don't think it's a good idea to let packagekit know something about RPM 
internals.
Better introduce something similar in APT than include RPM headers in 
packagekit (which is two layers above RPM) I think.

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [devel] [PATCH for apt] Implemented generic callback system for package manager transactions
  2019-12-10  0:30 ` Dmitry V. Levin
  2019-12-10  7:27   ` Oleg Solovyov
@ 2019-12-10  7:37   ` Aleksei Nikiforov
  2019-12-10 14:38   ` [devel] [PATCH for apt v2] " Oleg Solovyov
  2019-12-11  9:15   ` [devel] [PATCH for apt v3] " Oleg Solovyov
  3 siblings, 0 replies; 7+ messages in thread
From: Aleksei Nikiforov @ 2019-12-10  7:37 UTC (permalink / raw)
  To: devel

10.12.2019 3:30, Dmitry V. Levin пишет:
> On Fri, Dec 06, 2019 at 04:12:01PM +0300, Oleg Solovyov wrote:
>> ---
>>   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(-)
> 
> I agree the code should speak for itself, but it would be great
> if you could shed some light on what's going on.
> 
> [...]
>> +   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;
>> +   }
> 
> This looks ugly.  Could we use the same values for corresponding
> APTCALLBACK_* and RPMCALLBACK_* constants instead?
> 
> 

Not all RPMCALLBACK_* values are present in APTCALLBACK_* by design. How 
would you treat 'default' case?

Before this change, APT was hiding RPM interfaces from APT users. This 
enum was introduced to keep RPM interface hidden. How do you intend to 
have same constants in different enum? If you propose something like 
'APTCALLBACK_UNKNOWN = RPMCALLBACK_UNKNOWN', it'd couple APT interface 
with RPM interface. And hardcoding same values is more ugly than 
switch/case in my opinion.

> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [devel] [PATCH for apt v2] Implemented generic callback system for package manager transactions
  2019-12-10  0:30 ` Dmitry V. Levin
  2019-12-10  7:27   ` Oleg Solovyov
  2019-12-10  7:37   ` Aleksei Nikiforov
@ 2019-12-10 14:38   ` Oleg Solovyov
  2019-12-11  9:15   ` [devel] [PATCH for apt v3] " Oleg Solovyov
  3 siblings, 0 replies; 7+ messages in thread
From: Oleg Solovyov @ 2019-12-10 14:38 UTC (permalink / raw)
  To: devel; +Cc: Oleg Solovyov

We're introducing custom callback for higher layers (like packagekit),
letting them pass their own callbacks to APT instead of using rpmShowProgress
when it's necessary.
It's useful in particular case of offline updating when packagekit can
send messages to plymouth letting user know about transaction progress but
because APT does not send anything since it's using rpmShowProgress, packagekit
reports nothing because it's just nothing to report.
---
 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



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [devel] [PATCH for apt] Implemented generic callback system for package manager transactions
  2019-12-10  7:27   ` Oleg Solovyov
@ 2019-12-10 22:39     ` Dmitry V. Levin
  0 siblings, 0 replies; 7+ messages in thread
From: Dmitry V. Levin @ 2019-12-10 22:39 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 2028 bytes --]

On Tue, Dec 10, 2019 at 10:27:54AM +0300, Oleg Solovyov wrote:
> On вторник, 10 декабря 2019 г. 03:30:42 MSK Dmitry V. Levin wrote:
> > On Fri, Dec 06, 2019 at 04:12:01PM +0300, Oleg Solovyov wrote:
> > > ---
> > > 
> > >  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(-)
> > 
> > I agree the code should speak for itself, but it would be great
> > if you could shed some light on what's going on.
> We're introducing custom callback for higher layers (like packagekit), letting 
> them pass their own callbacks to APT instead of using rpmShowProgress when 
> it's necessary.
> It's useful in particular case of offline updating when packagekit can send 
> messages to plymouth letting user know about transaction progress but because 
> APT does not send anything since it's using rpmShowProgress, packagekit 
> reports nothing because it's just nothing to report.

Thanks, that's much better, and, btw, that's the main purpose of commit
messages - to let people know why you are doing this.

> > This looks ugly.  Could we use the same values for corresponding
> > APTCALLBACK_* and RPMCALLBACK_* constants instead?
> They're passed to packagekit.
> I don't think it's a good idea to let packagekit know something about RPM 
> internals.
> Better introduce something similar in APT than include RPM headers in 
> packagekit (which is two layers above RPM) I think.

There is definitely no need to expose rpm internals to apt clients.

If you prefer to define APTCALLBACK_* values this way,
could you think of an alternative customCallback implementation
that would be easy to verify?

For example, despite being a C++ project, you are still allowed
to use macros:

#define DEF_CASE(name)	case RPMCALLBACK_ ## name: return APTCALLBACK_ ## name


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [devel] [PATCH for apt v3] Implemented generic callback system for package manager transactions
  2019-12-10  0:30 ` Dmitry V. Levin
                     ` (2 preceding siblings ...)
  2019-12-10 14:38   ` [devel] [PATCH for apt v2] " Oleg Solovyov
@ 2019-12-11  9:15   ` Oleg Solovyov
  3 siblings, 0 replies; 7+ messages in thread
From: Oleg Solovyov @ 2019-12-11  9:15 UTC (permalink / raw)
  To: devel; +Cc: Oleg Solovyov

We're introducing custom callback for higher layers (like packagekit),
letting them pass their own callbacks to APT instead of using rpmShowProgress
when it's necessary.
It's useful in particular case of offline updating when packagekit can
send messages to plymouth letting user know about transaction progress but
because APT does not send anything since it's using rpmShowProgress, packagekit
reports nothing because it's just nothing to report.
---
 apt/apt-pkg/packagemanager.cc |   4 +-
 apt/apt-pkg/packagemanager.h  |  30 ++++++++-
 apt/apt-pkg/rpm/rpmpm.cc      | 111 +++++++++++++++++++++++++++++++---
 apt/apt-pkg/rpm/rpmpm.h       |  16 +++--
 4 files changed, 144 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..a2c9068 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,82 @@ 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);
+   }
+
+#define DEF_CASE(name) case RPMCALLBACK_##name: callbackType = APTCALLBACK_##name; break
+
+   aptCallbackType callbackType = APTCALLBACK_UNKNOWN;
+   switch (what) {
+      DEF_CASE(INST_PROGRESS);
+      DEF_CASE(INST_START);
+      DEF_CASE(INST_STOP);
+      DEF_CASE(TRANS_PROGRESS);
+      DEF_CASE(TRANS_START);
+      DEF_CASE(TRANS_STOP);
+      DEF_CASE(UNINST_PROGRESS);
+      DEF_CASE(UNINST_START);
+      DEF_CASE(UNINST_STOP);
+      DEF_CASE(UNPACK_ERROR);
+      DEF_CASE(CPIO_ERROR);
+      DEF_CASE(SCRIPT_ERROR);
+      DEF_CASE(SCRIPT_START);
+      DEF_CASE(SCRIPT_STOP);
+      DEF_CASE(ELEM_PROGRESS);
+
+#undef DEF_CASE
+      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 +1064,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.1



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-12-11  9:15 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-06 13:12 [devel] [PATCH for apt] Implemented generic callback system for package manager transactions Oleg Solovyov
2019-12-10  0:30 ` Dmitry V. Levin
2019-12-10  7:27   ` Oleg Solovyov
2019-12-10 22:39     ` Dmitry V. Levin
2019-12-10  7:37   ` Aleksei Nikiforov
2019-12-10 14:38   ` [devel] [PATCH for apt v2] " Oleg Solovyov
2019-12-11  9:15   ` [devel] [PATCH for apt v3] " Oleg Solovyov

ALT Linux Team development discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \
		devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru
	public-inbox-index devel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git