summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2025-03-09 13:29:29 +0000
committerJulian Andres Klode <jak@debian.org>2025-03-09 13:29:29 +0000
commit153bbf448f91eb347574624890c36f97cd168b53 (patch)
tree8f5f98fbe27ac7060b38e545eb43317215f1ae89 /apt-pkg
parent1e7f123ea59d6ae3af74725d4dab846f81d122e8 (diff)
parent6c112f9860c1730237029f4e23d40bf658d73704 (diff)
Merge branch 'transaction' into 'main'
Run 3.0 solver if internal is unsuccessful or we have apport for automatic solver evaluation See merge request apt-team/apt!446
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/depcache.cc87
-rw-r--r--apt-pkg/depcache.h39
2 files changed, 126 insertions, 0 deletions
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 970b4c01d..f7f508f85 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -110,6 +110,7 @@ struct pkgDepCache::Private
std::unique_ptr<InRootSetFunc> inRootSetFunc;
std::unique_ptr<APT::CacheFilter::Matcher> IsAVersionedKernelPackage, IsProtectedKernelPackage;
std::string machineID;
+ unsigned long iUpgradeCount{0};
};
pkgDepCache::pkgDepCache(pkgCache *const pCache, Policy *const Plcy) : group_level(0), Cache(pCache), PkgState(0), DepState(0),
iUsrSize(0), iDownloadSize(0), iInstCount(0), iDelCount(0), iKeepCount(0),
@@ -148,6 +149,7 @@ bool pkgDepCache::CheckConsistency(char const *const msgtag) /*{{{*/
auto const origUsrSize = iUsrSize;
auto const origDownloadSize = iDownloadSize;
auto const origInstCount = iInstCount;
+ auto const origUpgradeCount = d->iUpgradeCount;
auto const origDelCount = iDelCount;
auto const origKeepCount = iKeepCount;
auto const origBrokenCount = iBrokenCount;
@@ -208,6 +210,7 @@ bool pkgDepCache::CheckConsistency(char const *const msgtag) /*{{{*/
iUsrSize = origUsrSize;
iDownloadSize = origDownloadSize;
iInstCount = origInstCount;
+ d->iUpgradeCount = origUpgradeCount;
iDelCount = origDelCount;
iKeepCount = origKeepCount;
iBrokenCount = origBrokenCount;
@@ -632,7 +635,11 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg, bool const Invert)
else if (State.Mode == ModeKeep)
iKeepCount += Add;
else if (State.Mode == ModeInstall)
+ {
iInstCount += Add;
+ if (Pkg->CurrentVer != 0 && State.Status > 0)
+ d->iUpgradeCount += Add;
+ }
}
/*}}}*/
// DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
@@ -762,6 +769,7 @@ void pkgDepCache::PerformDependencyPass(OpProgress * const Prog)
iUsrSize = 0;
iDownloadSize = 0;
iInstCount = 0;
+ d->iUpgradeCount = 0;
iDelCount = 0;
iKeepCount = 0;
iBrokenCount = 0;
@@ -2650,3 +2658,82 @@ unsigned long long pkgDepCache::BootSize(bool initrdOnly)
return std::accumulate(sizes, sizes + MAX_ARTEFACT, off_t{0}) * BootCount * 110 / 100;
}
/*}}}*/
+// pkgDepCache::UpgradeCount /*{{{*/
+unsigned long pkgDepCache::UpgradeCount()
+{
+ return d->iUpgradeCount;
+}
+ /*}}}*/
+// pkgDepCache::Transaction /*{{{*/
+struct pkgDepCache::Transaction::Private
+{
+ template <typename T>
+ static T *copyArray(T *array, size_t count)
+ {
+ auto out = new T[count];
+ memcpy(&out[0], &array[0], sizeof(T) * count);
+ return out;
+ }
+ // State information
+ pkgDepCache &cache;
+ Behavior behavior;
+ std::unique_ptr<StateCache[]> PkgState{copyArray(cache.PkgState, cache.GetCache().Head().PackageCount)};
+ std::unique_ptr<unsigned char[]> DepState{copyArray(cache.DepState, cache.GetCache().Head().DependsCount)};
+ signed long long iUsrSize{cache.iUsrSize};
+ unsigned long long iDownloadSize{cache.iDownloadSize};
+ unsigned long iInstCount{cache.iInstCount};
+ unsigned long iUpgradeCount{cache.d->iUpgradeCount};
+ unsigned long iDelCount{cache.iDelCount};
+ unsigned long iKeepCount{cache.iKeepCount};
+ unsigned long iBrokenCount{cache.iBrokenCount};
+ unsigned long iPolicyBrokenCount{cache.iPolicyBrokenCount};
+ unsigned long iBadCount{cache.iBadCount};
+
+ void rollback()
+ {
+ memcpy(&cache.PkgState[0], &PkgState[0], sizeof(PkgState[0]) * cache.GetCache().Head().PackageCount);
+ memcpy(&cache.DepState[0], &DepState[0], sizeof(DepState[0]) * cache.GetCache().Head().DependsCount);
+
+ cache.iUsrSize = iUsrSize;
+ cache.iDownloadSize = iDownloadSize;
+ cache.iInstCount = iInstCount;
+ cache.d->iUpgradeCount = iUpgradeCount;
+ cache.iDelCount = iDelCount;
+ cache.iKeepCount = iKeepCount;
+ cache.iBrokenCount = iBrokenCount;
+ cache.iPolicyBrokenCount = iPolicyBrokenCount;
+ cache.iBadCount = iBadCount;
+ }
+};
+
+pkgDepCache::Transaction::Transaction(pkgDepCache &cache, Behavior behavior) : d(new Private{cache, behavior}) {}
+
+void pkgDepCache::Transaction::temporaryRollback()
+{
+ d->rollback();
+}
+
+void pkgDepCache::Transaction::commit()
+{
+ d.reset();
+}
+
+void pkgDepCache::Transaction::rollback()
+{
+ if (d == nullptr)
+ return;
+
+ temporaryRollback();
+ d.reset();
+}
+
+pkgDepCache::Transaction::~Transaction()
+{
+ if (not d)
+ return;
+ if (d->behavior == Behavior::ROLLBACK || (d->behavior == Behavior::AUTO && d->cache.iBrokenCount > d->iBrokenCount))
+ rollback();
+ else
+ commit();
+}
+ /*}}}*/
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
index 39d34d3e4..bab524853 100644
--- a/apt-pkg/depcache.h
+++ b/apt-pkg/depcache.h
@@ -267,6 +267,42 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace
bool InstallSuggests;
};
+ /**
+ * \brief Perform changes to the depcache atomically.
+ *
+ * The default policy for a transaction is to rollback if the number of broken packages
+ * increased, otherwise to commit. Call commit() or rollback() to override the default
+ * policy.
+ */
+ class APT_PUBLIC Transaction final
+ {
+ struct Private;
+ std::unique_ptr<Private> d;
+
+ public:
+ enum class Behavior
+ {
+ COMMIT,
+ ROLLBACK,
+ AUTO,
+ };
+
+ explicit Transaction(pkgDepCache &cache, Behavior behavior);
+ /** \brief Commit the transaction immediately */
+ void commit();
+ /** \brief Rollback the transaction immediately */
+ void rollback();
+ /** \brief Like rollback, but can be called multiple times.
+ *
+ * You can for example create a new transaction, then temporarily
+ * rollback to the state before the previous transaction in that
+ * transaction.
+ */
+ void temporaryRollback();
+ /** \brief Commit or rollback the transaction based on default policy */
+ ~Transaction();
+ };
+
private:
/** The number of open "action groups"; certain post-action
* operations are suppressed if this number is > 0.
@@ -274,6 +310,8 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace
int group_level;
friend class ActionGroup;
+ friend class Transaction;
+
public:
int IncreaseActionGroupLevel();
int DecreaseActionGroupLevel();
@@ -479,6 +517,7 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace
inline unsigned long DelCount() {return iDelCount;};
inline unsigned long KeepCount() {return iKeepCount;};
inline unsigned long InstCount() {return iInstCount;};
+ unsigned long UpgradeCount();
inline unsigned long BrokenCount() {return iBrokenCount;};
inline unsigned long PolicyBrokenCount() {return iPolicyBrokenCount;};
inline unsigned long BadCount() {return iBadCount;};