[Apt-Rpm] multiple good providers, how does apt pick the right one?
Panu Matilainen
pmatilai at laiskiainen.org
Sun Feb 24 05:56:43 PST 2008
On Sat, 23 Feb 2008, Panu Matilainen wrote:
>
> Whether it's reasonably possible to have Lua-hook in the lowlevel depsolve
> logic remains to be seen, but a C++-level callback shouldn't have such
> problems. It'd be sad if Lua can't be used but (optional) app-specific
> callback would still enable what you want, so not all hope is lost anyway
> :)
...and here's the first rough-cut of the C++ callback approach this time
batter^H^H^H^H^H^H patch included.
There are all sorts of nitty details to sort out, such as dealing with -y
and it's variants in semi-intelligent manner and probably some more
fundamental issues too but at least you'll get to play around with it a
bit.
Haven't done any extensive testing, just some basic "seems to do what
intended" runs so watch out for any falling pieces :)
- Panu -
-------------- next part --------------
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 758612c..40dea40 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -26,15 +26,27 @@
#include <apti18n.h>
/*}}}*/
+/*
+ * Default callback for multiple good providers: just pick whatever's first..
+ */
+static pkgCache::Package * pkgDefaultProviderCb(
+ pkgDepCache * const Cache,
+ pkgCache::DepIterator Dep,
+ const vector<pkgCache::Package *> Providers)
+{
+ return Providers[0];
+}
// DepCache::pkgDepCache - Constructors /*{{{*/
// ---------------------------------------------------------------------
/* */
pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
- Cache(pCache), PkgState(0), DepState(0)
+ Cache(pCache), PkgState(0), DepState(0),
+ SelectProvider(pkgDefaultProviderCb)
{
delLocalPolicy = 0;
LocalPolicy = Plcy;
+
if (LocalPolicy == 0)
delLocalPolicy = LocalPolicy = new Policy;
}
@@ -109,6 +121,13 @@ bool pkgDepCache::Init(OpProgress *Prog)
return true;
}
/*}}}*/
+pkgSelectProviderFunction pkgDepCache::SetProviderCallback(pkgSelectProviderFunction cb)
+{
+ pkgSelectProviderFunction oldCb = SelectProvider;
+ SelectProvider = cb;
+ return oldCb;
+}
+
// DepCache::CheckDep - Checks a single dependency /*{{{*/
// ---------------------------------------------------------------------
@@ -733,6 +752,7 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
Update(Pkg);
AddSizes(Pkg);
}
+
/*}}}*/
// DepCache::MarkInstall - Put the package in the install state /*{{{*/
// ---------------------------------------------------------------------
@@ -849,14 +869,29 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
// Select the highest priority providing package
if (InstPkg.end() == true)
{
+ vector<pkgCache::Package *> Providers;
pkgPrioSortList(*Cache,Cur);
for (; *Cur != 0; Cur++)
{
PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
if (PkgState[Pkg->ID].CandidateVer != *Cur)
continue;
- InstPkg = Pkg;
- break;
+ Providers.push_back(Pkg);
+ }
+
+ int numprov = Providers.size();
+ if (numprov == 1) {
+ pkgCache::PkgIterator GoodPkg(*Cache, Providers[0]);
+ InstPkg = GoodPkg;
+ } else if (numprov > 1) {
+ pkgCache::Package * selected;
+ selected = SelectProvider(this, Start, Providers);
+ if (! selected) {
+ cout << "Oops, SelectProvider() didn't select" << endl;
+ selected = pkgDefaultProviderCb(this, Start, Providers);
+ }
+ pkgCache::PkgIterator GoodPkg(*Cache, selected);
+ InstPkg = GoodPkg;
}
}
@@ -1093,6 +1128,5 @@ void pkgDepCache::State::UnIgnoreAll()
memset(PkgIgnore, 0, Dep->Head().PackageCount*sizeof(*PkgIgnore));
}
- /*}}}*/
// vim:sts=3:sw=3
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
index 8f814e7..da11dc7 100644
--- a/apt-pkg/depcache.h
+++ b/apt-pkg/depcache.h
@@ -42,9 +42,20 @@
#pragma interface "apt-pkg/depcache.h"
#endif
+#include <vector>
+
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/progress.h>
+using std::vector;
+
+class pkgDepCache;
+class pkgCache;
+typedef pkgCache::Package * (*pkgSelectProviderFunction)
+ (pkgDepCache * const Cache,
+ pkgCache::DepIterator Dep,
+ const vector<pkgCache::Package *> Providers);
+
class pkgDepCache : protected pkgCache::Namespace
{
public:
@@ -141,6 +152,8 @@ class pkgDepCache : protected pkgCache::Namespace
Policy *delLocalPolicy; // For memory clean up..
Policy *LocalPolicy;
+
+ pkgSelectProviderFunction SelectProvider;
// Check for a matching provides
bool CheckDep(DepIterator Dep,int Type,PkgIterator &Res);
@@ -165,9 +178,10 @@ class pkgDepCache : protected pkgCache::Namespace
inline void RemoveSizes(const PkgIterator &Pkg) {AddSizes(Pkg,-1);}
void AddStates(const PkgIterator &Pkg,int Add = 1);
inline void RemoveStates(const PkgIterator &Pkg) {AddStates(Pkg,-1);}
-
+
public:
+ pkgSelectProviderFunction SetProviderCallback(pkgSelectProviderFunction cb);
// CNC:2003-02-23 - See below.
class State;
friend class State;
@@ -280,7 +294,6 @@ class pkgDepCache::State
}
};
-
/* This is an exact copy of the structure above, nested in pkgDepCache.
* This is defined again here since SWIG doesn't know how to handle nested
* structures yet. It will be dropped once that situation changes. */
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index 031950b..a3b1f56 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -90,6 +90,8 @@ class CacheFile : public cmdCacheFile
if (pkgCacheFile::Open(Prog,WithLock) == false)
return false;
Sort();
+
+ DCache->SetProviderCallback(cmdSelectProvider);
return true;
}
diff --git a/cmdline/cmdline.cc b/cmdline/cmdline.cc
index 71fd14e..284a2a4 100644
--- a/cmdline/cmdline.cc
+++ b/cmdline/cmdline.cc
@@ -1935,4 +1935,36 @@ bool cmdChangeLog(CommandLine &CmdL, pkgCache &Cache)
return true;
}
+pkgCache::Package * cmdSelectProvider(
+ pkgDepCache * const Cache,
+ pkgCache::DepIterator Dep,
+ const vector<pkgCache::Package *> Providers)
+{
+ ioprintf(cout,_("Package %s is a virtual package provided by:\n"),
+ Dep.TargetPkg().Name());
+
+ size_t numProv = Providers.size();
+ vector<pkgCache::Package *>::const_iterator P = Providers.begin();
+ for (; P != Providers.end(); P++) {
+ pkgCache::PkgIterator GoodPkg(*Cache, (*P));
+ cout << (P - Providers.begin()) + 1 << ". " << GoodPkg.Name() << endl;
+ }
+
+ size_t selection = 0;
+ while (selection < 1) {
+ size_t inp;
+ ioprintf(cout, _("Select one of 1-%zu: "), numProv);
+ if (!(cin >> inp)) {
+ cin.clear();
+ cin.ignore(256,'\n');
+ continue;
+ }
+ if (inp > 0 && inp <= numProv)
+ selection = inp;
+ }
+
+ return Providers[selection-1];
+}
+
+
// vim:sts=3:sw=3
diff --git a/cmdline/cmdline.h b/cmdline/cmdline.h
index 7f7808a..b7d884e 100644
--- a/cmdline/cmdline.h
+++ b/cmdline/cmdline.h
@@ -93,5 +93,9 @@ bool cmdSearchFile(CommandLine &CmdL, pkgCache &Cache);
bool cmdFileList(CommandLine &CmdL, pkgCache &Cache);
bool cmdChangeLog(CommandLine &CmdL, pkgCache &Cache);
+pkgCache::Package * cmdSelectProvider(
+ pkgDepCache * const Cache,
+ pkgCache::DepIterator Dep,
+ const vector<pkgCache::Package *> Providers);
// vim:sts=3:sw=3
More information about the Apt-Rpm
mailing list