+ 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)
+{
+ if (FromUser == true) // as always: user is always right
+ return true;
+
+ // if we have checked before and it was okay, it will still be okay
+ if (PkgState[Pkg->ID].Mode == ModeInstall &&
+ PkgState[Pkg->ID].InstallVer == PkgState[Pkg->ID].CandidateVer)
+ return true;
+
+ // ignore packages with none-M-A:same candidates
+ VerIterator const CandVer = PkgState[Pkg->ID].CandidateVerIter(*this);
+ if (unlikely(CandVer.end() == true) || CandVer == Pkg.CurrentVer() ||
+ (CandVer->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same)
+ return true;
+
+ GrpIterator const Grp = Pkg.Group();
+ for (PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P))
+ {
+ // not installed or self-check: fine by definition
+ if (P->CurrentVer == 0 || P == Pkg)
+ continue;
+
+ // not having a candidate or being in sync
+ // (simple string-compare as stuff like '1' == '0:1-0' can't happen here)
+ VerIterator CV = PkgState[P->ID].CandidateVerIter(*this);
+ if (CV.end() == true || strcmp(Pkg.CandVersion(), CV.VerStr()) == 0)
+ continue;
+
+ // packages losing M-A:same can be out-of-sync
+ if ((CV->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same)
+ continue;
+
+ // not downloadable means the package is obsolete, so allow out-of-sync
+ if (CV.Downloadable() == false)
+ continue;
+
+ PkgState[Pkg->ID].iFlags |= AutoKept;
+ if (unlikely(DebugMarker == true))
+ std::clog << OutputInDepth(Depth) << "Ignore MarkInstall of " << Pkg
+ << " as it is not in sync with its M-A:same sibling " << P
+ << " (" << Pkg.CandVersion() << " != " << CV.VerStr() << ")" << std::endl;
+ 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;