From: Oleg Solovyov <mcpain@altlinux.org> To: devel@lists.altlinux.org Cc: Oleg Solovyov <mcpain@altlinux.org> Subject: [devel] [PATCH for apt v2] Implemented generic callback system for package manager transactions Date: Tue, 10 Dec 2019 17:38:10 +0300 Message-ID: <20191210143810.68331-1-mcpain@altlinux.org> (raw) In-Reply-To: <20191210003042.GF15867@altlinux.org> 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
next prev parent reply other threads:[~2019-12-10 14:38 UTC|newest] Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-12-06 13:12 [devel] [PATCH for apt] " 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 ` Oleg Solovyov [this message] 2019-12-11 9:15 ` [devel] [PATCH for apt v3] " Oleg Solovyov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20191210143810.68331-1-mcpain@altlinux.org \ --to=mcpain@altlinux.org \ --cc=devel@lists.altlinux.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
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