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
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)
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 && (PkgState[Pkg->ID].iFlags & Protected) != Protected)
+ SetCandidateVersion(Pkg.CurrentVer());
+ return false;
+ }
+ }
+
return true;
}
/*}}}*/
{
/* Not source/not automatic versions cannot be a candidate version
unless they are already installed */
- VerIterator Last(*(pkgCache *)this,0);
+ VerIterator Last;
for (VerIterator I = Pkg.VersionList(); I.end() == false; ++I)
{