cache.MarkAndSweep();
}
- released = false;
+ released = true;
}
}
/* Check simple depends. A depends -should- never self match but
we allow it anyhow because dpkg does. Technically it is a packaging
bug. Conflicts may never self match */
- if (Dep.TargetPkg() != Dep.ParentPkg() ||
- (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
+ if (Dep.TargetPkg() != Dep.ParentPkg() || Dep.IsNegative() == false)
{
PkgIterator Pkg = Dep.TargetPkg();
// Check the base package
{
/* Provides may never be applied against the same package (or group)
if it is a conflicts. See the comment above. */
- if (P.OwnerPkg()->Group == Pkg->Group &&
- (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
+ if (P.OwnerPkg()->Group == Pkg->Group && Dep.IsNegative() == true)
continue;
// Check if the provides is a hit
// Not installed
if (Pkg->CurrentVer == 0)
{
- if (State.Mode == ModeDelete &&
- (State.iFlags | Purge) == Purge && Pkg.Purge() == false)
+ if (State.Mode == ModeDelete &&
+ (State.iFlags & Purge) == Purge && Pkg.Purge() == false)
iDelCount += Add;
if (State.Mode == ModeInstall)
/* Invert for Conflicts. We have to do this twice to get the
right sense for a conflicts group */
- if (D->Type == Dep::Conflicts ||
- D->Type == Dep::DpkgBreaks ||
- D->Type == Dep::Obsoletes)
+ if (D.IsNegative() == true)
State = ~State;
// Add to the group if we are within an or..
Group = 0;
// Invert for Conflicts
- if (D->Type == Dep::Conflicts ||
- D->Type == Dep::DpkgBreaks ||
- D->Type == Dep::Obsoletes)
+ if (D.IsNegative() == true)
State = ~State;
}
}
Group = 0;
// Invert for Conflicts
- if (D->Type == Dep::Conflicts ||
- D->Type == Dep::DpkgBreaks ||
- D->Type == Dep::Obsoletes)
+ if (D.IsNegative() == true)
State = ~State;
}
}
State = DependencyState(D);
// Invert for Conflicts
- if (D->Type == Dep::Conflicts ||
- D->Type == Dep::DpkgBreaks ||
- D->Type == Dep::Obsoletes)
+ if (D.IsNegative() == true)
State = ~State;
RemoveStates(D.ParentPkg());
void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser,
unsigned long Depth)
{
- // Simplifies other routines.
- if (Pkg.end() == true)
+ if (IsModeChangeOk(ModeKeep, Pkg, Depth, FromUser) == false)
return;
/* Reject an attempt to keep a non-source broken installed package, those
if (Pkg.State() == PkgIterator::NeedsUnpack &&
Pkg.CurrentVer().Downloadable() == false)
return;
-
- /** \todo Can this be moved later in the method? */
- ActionGroup group(*this);
/* We changed the soft state all the time so the UI is a bit nicer
to use */
StateCache &P = PkgState[Pkg->ID];
+
+ // Check that it is not already kept
+ if (P.Mode == ModeKeep)
+ return;
+
if (Soft == true)
P.iFlags |= AutoKept;
else
P.iFlags &= ~AutoKept;
-
- // Check that it is not already kept
- if (P.Mode == ModeKeep)
- return;
- // We dont even try to keep virtual packages..
- if (Pkg->VersionList == 0)
- return;
+ ActionGroup group(*this);
+
#if 0 // reseting the autoflag here means we lose the
// auto-mark information if a user selects a package for removal
// but changes his mind then and sets it for keep again
void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
unsigned long Depth, bool FromUser)
{
- // Simplifies other routines.
- if (Pkg.end() == true)
+ if (IsModeChangeOk(ModeDelete, Pkg, Depth, FromUser) == false)
return;
- ActionGroup group(*this);
+ StateCache &P = PkgState[Pkg->ID];
// Check that it is not already marked for delete
- StateCache &P = PkgState[Pkg->ID];
- P.iFlags &= ~(AutoKept | Purge);
- if (rPurge == true)
- P.iFlags |= Purge;
-
if ((P.Mode == ModeDelete || P.InstallVer == 0) &&
(Pkg.Purge() == true || rPurge == false))
return;
-
- // We dont even try to delete virtual packages..
- if (Pkg->VersionList == 0)
- return;
- // check if we are allowed to install the package
+ // check if we are allowed to remove the package
if (IsDeleteOk(Pkg,rPurge,Depth,FromUser) == false)
return;
+ P.iFlags &= ~(AutoKept | Purge);
+ if (rPurge == true)
+ P.iFlags |= Purge;
+
+ ActionGroup group(*this);
+
if (DebugMarker == true)
std::clog << OutputInDepth(Depth) << (rPurge ? "MarkPurge " : "MarkDelete ") << Pkg << " FU=" << FromUser << std::endl;
/*}}}*/
// DepCache::IsDeleteOk - check if it is ok to remove this package /*{{{*/
// ---------------------------------------------------------------------
-/* The default implementation just honors dpkg hold
- But an application using this library can override this method
- to control the MarkDelete behaviour */
+/* The default implementation tries to prevent deletion of install requests.
+ dpkg holds are enforced by the private IsModeChangeOk */
bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge,
unsigned long Depth, bool FromUser)
{
- if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false)
- {
- if (DebugMarker == true)
- std::clog << OutputInDepth(Depth) << "Hold prevents MarkDelete of " << Pkg << " FU=" << FromUser << std::endl;
- return false;
- }
- else if (FromUser == false && Pkg->CurrentVer == 0)
+ if (FromUser == false && Pkg->CurrentVer == 0)
{
StateCache &P = PkgState[Pkg->ID];
if (P.InstallVer != 0 && P.Status == 2 && (P.Flags & Flag::Auto) != Flag::Auto)
return false;
}
}
+ return true;
+}
+ /*}}}*/
+// DepCache::IsModeChangeOk - check if it is ok to change the mode /*{{{*/
+// ---------------------------------------------------------------------
+/* this is used by all Mark methods on the very first line to check sanity
+ and prevents mode changes for packages on hold for example.
+ If you want to check Mode specific stuff you can use the virtual public
+ Is<Mode>Ok methods instead */
+char const* PrintMode(char const mode)
+{
+ switch (mode)
+ {
+ case pkgDepCache::ModeInstall: return "Install";
+ case pkgDepCache::ModeKeep: return "Keep";
+ case pkgDepCache::ModeDelete: return "Delete";
+ default: return "UNKNOWN";
+ }
+}
+bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
+ unsigned long const Depth, bool const FromUser)
+{
+ // we are not trying to hard…
+ if (unlikely(Depth > 100))
+ return false;
+
+ // general sanity
+ if (unlikely(Pkg.end() == true || Pkg->VersionList == 0))
+ return false;
+
+ // the user is always right
+ if (FromUser == true)
+ return true;
+
+ StateCache &P = PkgState[Pkg->ID];
+
+ // if previous state was set by user only user can reset it
+ if ((P.iFlags & Protected) == Protected)
+ {
+ if (unlikely(DebugMarker == true) && P.Mode != mode)
+ std::clog << OutputInDepth(Depth) << "Ignore Mark" << PrintMode(mode)
+ << " of " << Pkg << " as its mode (" << PrintMode(P.Mode)
+ << ") is protected" << std::endl;
+ return false;
+ }
+ // enforce dpkg holds
+ else if (mode != ModeKeep && Pkg->SelectedState == pkgCache::State::Hold &&
+ _config->FindB("APT::Ignore-Hold",false) == false)
+ {
+ if (unlikely(DebugMarker == true) && P.Mode != mode)
+ std::clog << OutputInDepth(Depth) << "Hold prevents Mark" << PrintMode(mode)
+ << " of " << Pkg << std::endl;
+ return false;
+ }
+
return true;
}
/*}}}*/
unsigned long Depth, bool FromUser,
bool ForceImportantDeps)
{
- if (Depth > 100)
+ if (IsModeChangeOk(ModeInstall, Pkg, Depth, FromUser) == false)
return;
-
- // Simplifies other routines.
- if (Pkg.end() == true)
+
+ StateCache &P = PkgState[Pkg->ID];
+
+ // See if there is even any possible instalation candidate
+ if (P.CandidateVer == 0)
return;
-
- ActionGroup group(*this);
/* Check that it is not already marked for install and that it can be
installed */
- StateCache &P = PkgState[Pkg->ID];
- P.iFlags &= ~AutoKept;
if ((P.InstPolicyBroken() == false && P.InstBroken() == false) &&
(P.Mode == ModeInstall ||
P.CandidateVer == (Version *)Pkg.CurrentVer()))
return;
}
- // See if there is even any possible instalation candidate
- if (P.CandidateVer == 0)
- return;
- // We dont even try to install virtual packages..
- if (Pkg->VersionList == 0)
- return;
-
// check if we are allowed to install the package
if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false)
return;
+ ActionGroup group(*this);
+ P.iFlags &= ~AutoKept;
+
/* Target the candidate version and remove the autoflag. We reset the
autoflag below if this was called recursively. Otherwise the user
should have the ability to de-auto a package by changing its state */
*/
if (IsImportantDep(Start) == 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 && 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 can't install it, so remove it again
+ MarkDelete(Pkg,false,Depth + 1, false);
+ return;
+ }
+
/* Check if any ImportantDep() (but not Critical) were added
* since we installed the package. Also check for deps that
* were satisfied in the past: for instance, if a version
&& !ForceImportantDeps)
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++;
-
/* This bit is for processing the possibilty of an install/upgrade
fixing the problem */
SPtrArray<Version *> List = Start.AllTargets();
/* For conflicts we just de-install the package and mark as auto,
Conflicts may not have or groups. For dpkg's Breaks we try to
upgrade the package. */
- if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes ||
- Start->Type == Dep::DpkgBreaks)
+ if (Start.IsNegative() == true)
{
for (Version **I = List; *I != 0; I++)
{
/*}}}*/
// DepCache::IsInstallOk - check if it is ok to install this package /*{{{*/
// ---------------------------------------------------------------------
-/* The default implementation just honors dpkg hold
- But an application using this library can override this method
- to control the MarkInstall behaviour */
+/* The default implementation does nothing.
+ dpkg holds are enforced by the private IsModeChangeOk */
bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
unsigned long Depth, bool FromUser)
{
- if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false)
- {
- if (DebugMarker == true)
- std::clog << OutputInDepth(Depth) << "Hold prevents MarkInstall of " << Pkg << " FU=" << FromUser << std::endl;
- return false;
- }
return true;
}
/*}}}*/
AddStates(Pkg);
AddSizes(Pkg);
-
- if (unlikely(Pkg.CurrentVer().end() == true))
- return;
-
- SetReInstall(Pkg.Group().FindPkg("all"), To);
}
/*}}}*/
// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/