Browse Source

discard candidates via IsInstallOk to allow override

In commit 446551c8 I changed MarkInstall to discard the candidate if the
candidate can't satisfy the dependency. This breaks interactive solvers
like aptitude which can change the candidate on-the-fly later.

In commit df77d8a5 I introduced this 'early' loop-breaking to begin with
which can't be that helpful for interactive solvers as well, but makes
perfect sense for non-interactives to stop them from exploring trees
which can't be satisfied, but it isn't perfect as ideally we would check
this before auto-installing the first dependency.

This commit therefore moves the loop into its own IsInstallOk hook so
that frontends can override this check if they want to and in exchange
removes the loop-breaking from MarkInstall itself and does it before any
dependency is installed.

Closes: 740750
tags/debian/1.0
David Kalnischkies 7 years ago
parent
commit
21b3eac8f9
3 changed files with 63 additions and 20 deletions
  1. +58
    -20
      apt-pkg/depcache.cc
  2. +2
    -0
      apt-pkg/depcache.h
  3. +3
    -0
      test/integration/test-bug-735967-lib32-to-i386-unavailable

+ 58
- 20
apt-pkg/depcache.cc View File

@@ -1122,32 +1122,22 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
continue;

/* Check if this dep should be consider for install. If it is a user
defined important dep and we are installed a new package then
defined important dep and we are installed a new package then
it will be installed. Otherwise we only check for important
deps that have changed from the installed version
*/
deps that have changed from the installed version */
if (IsImportantDep(Start) == false)
continue;

/* If we are in an or group locate the first or that can
succeed. We have already cached this.. */
/* If we are in an or group locate the first or that can
succeed. We have already cached this */
for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; --Ors)
++Start;

/* unsatisfiable dependency: IsInstallOkDependenciesSatisfiableByCandidates
would have prevented us to get here if not overridden, so just skip
over the problem here as the frontend will know what it is doing */
if (Ors == 1 && (DepState[Start->ID] &DepCVer) != DepCVer && Start.IsNegative() == false)
{
if(DebugAutoInstall == true)
std::clog << OutputInDepth(Depth) << Start << " can't be satisfied!" << std::endl;
if (Start.IsCritical() == false)
continue;
// if the dependency was critical, we have absolutely no chance to install it,
// so if it wasn't installed remove it again. If it was, discard the candidate
// as the problemresolver will trip over it otherwise trying to install it (#735967)
if (Pkg->CurrentVer == 0)
MarkDelete(Pkg,false,Depth + 1, false);
else
SetCandidateVersion(Pkg.CurrentVer());
return false;
}
continue;

/* Check if any ImportantDep() (but not Critical) were added
* since we installed the package. Also check for deps that
@@ -1299,7 +1289,8 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
unsigned long Depth, bool FromUser)
{
return IsInstallOkMultiArchSameVersionSynced(Pkg,AutoInst, Depth, FromUser);
return IsInstallOkMultiArchSameVersionSynced(Pkg,AutoInst, Depth, FromUser) &&
IsInstallOkDependenciesSatisfiableByCandidates(Pkg,AutoInst, Depth, FromUser);
}
bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg,
bool const /*AutoInst*/, unsigned long const Depth, bool const FromUser)
@@ -1342,6 +1333,53 @@ bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg,
return false;
}

return true;
}
bool pkgDepCache::IsInstallOkDependenciesSatisfiableByCandidates(PkgIterator const &Pkg,
bool const AutoInst, unsigned long const Depth, bool const /*FromUser*/)
{
if (AutoInst == false)
return true;

VerIterator const CandVer = PkgState[Pkg->ID].CandidateVerIter(*this);
if (unlikely(CandVer.end() == true) || CandVer == Pkg.CurrentVer())
return true;

for (DepIterator Dep = CandVer.DependsList(); Dep.end() != true;)
{
// Grok or groups
DepIterator Start = Dep;
bool Result = true;
unsigned Ors = 0;
for (bool LastOR = true; Dep.end() == false && LastOR == true; ++Dep, ++Ors)
{
LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;

if ((DepState[Dep->ID] & DepInstall) == DepInstall)
Result = false;
}

if (Start.IsCritical() == false || Start.IsNegative() == true || Result == false)
continue;

/* If we are in an or group locate the first or that can succeed.
We have already cached this… */
for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; --Ors)
++Start;

if (Ors == 1 && (DepState[Start->ID] &DepCVer) != DepCVer)
{
if (DebugAutoInstall == true)
std::clog << OutputInDepth(Depth) << Start << " can't be satisfied!" << std::endl;

// the dependency is critical, but can't be installed, so discard the candidate
// as the problemresolver will trip over it otherwise trying to install it (#735967)
if (Pkg->CurrentVer != 0)
SetCandidateVersion(Pkg.CurrentVer());
return false;
}
}

return true;
}
/*}}}*/


+ 2
- 0
apt-pkg/depcache.h View File

@@ -506,6 +506,8 @@ class pkgDepCache : protected pkgCache::Namespace
// methods call by IsInstallOk
bool IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg,
bool const AutoInst, unsigned long const Depth, bool const FromUser);
bool IsInstallOkDependenciesSatisfiableByCandidates(PkgIterator const &Pkg,
bool const AutoInst, unsigned long const Depth, bool const FromUser);

// methods call by IsDeleteOk
bool IsDeleteOkProtectInstallRequests(PkgIterator const &Pkg,


+ 3
- 0
test/integration/test-bug-735967-lib32-to-i386-unavailable View File

@@ -12,6 +12,9 @@ insertpackage 'unstable' 'libnss-mdns' 'amd64,i386' '0.10-6' 'Multi-Arch: same
Breaks: lib32nss-mdns (<< 0.10-6)'
insertpackage 'unstable' 'libnss-mdns-i386' 'i386' '0.10-6' 'Multi-Arch: foreign
Depends: libnss-mdns'
# introduce some dummies so that there are versions, but none works
insertpackage 'unstable' 'libnss-mdns-i386' 'amd64' '0.1-6'
insertpackage 'experimental' 'libnss-mdns-amd64' 'i386,amd64' '0.10-6' 'Provides: libnss-mdns-i386'

insertpackage 'unstable' 'foo' 'amd64' '1' 'Depends: libfoo'
insertpackage 'unstable' 'libfoo' 'amd64' '1' 'Depends: libfoo-bin'


Loading…
Cancel
Save